diff --git a/CHANGES.current b/CHANGES.current index 14f6fb4cb..6a372cb56 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -5,6 +5,11 @@ See the RELEASENOTES file for a summary of changes in each release. Version 3.0.11 (in progress) ============================ +2016-11-30: olly + [PHP] Add support for PHP7. PHP5's C extension API has changed substantially + so you need to use -php7 to specify you want PHP7 compatible wrappers. + Fixes https://github.com/swig/swig/issues/571 + 2016-11-28: wsfulton Fix %rename override of wildcard %rename for templates. For example: diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 56a6ba530..fea70a9fa 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -49,19 +49,6 @@ -

-SWIG supports generating wrappers for PHP5. Support for PHP4 was removed -in SWIG 1.3.37. The PHP developers are no longer making new PHP4 releases, -and won't even be patching critical security issues after 2008-08-08, so it -doesn't make much sense for SWIG to continue to support PHP4 now. If you -really need to continue to use PHP4, just stick with SWIG 1.3.36. -

- -

-Currently any PHP5 release should work, but we don't regularly test with -PHP < 5.3. -

-

In this chapter, we discuss SWIG's support of PHP. The PHP module was extensively rewritten in release 1.3.26, and support for generating @@ -70,7 +57,17 @@ of the features available in some of the other languages.

-In order to use this module, you will need to have a copy of the PHP5 +SWIG supports generating wrappers for PHP5 and PHP7. Support for PHP4 was removed +in SWIG 1.3.37. +

+ +

+Currently any PHP5 or PHP7 release should work, but we don't regularly test with +PHP < 5.3. +

+ +

+In order to use this module, you will need to have a copy of the PHP include files to compile the SWIG generated files. If you installed PHP from a binary package, you may need to install a "php-dev" or "php-devel" package for these to be installed. You can find out where these files are @@ -84,12 +81,13 @@ available.

-To build a PHP extension, run swig using the -php option as -follows: +To build a PHP extension, run swig using the -php5 or +-php7 option as follows (-php is also supported +and currently is an alias for -php5):

-swig -php example.i
+swig -php7 example.i
 

@@ -102,7 +100,7 @@ The third file, example.php can be included by PHP scripts. It attempts to dynamically load the extension and contains extra php code specified in the interface file. If wrapping C++ code with PHP classes, it will -also contain PHP5 class wrappers. +also contain PHP class wrappers.

@@ -611,7 +609,7 @@ struct Complex {

-Would be used in the following way from PHP5: +Would be used in the following way from PHP:

@@ -646,7 +644,7 @@ Member variables and methods are accessed using the -> operator.
 

The -noproxy option flattens the object structure and generates collections of named functions (these are the functions -which the PHP5 class wrappers call). The above example results +which the PHP class wrappers call). The above example results in the following PHP functions:

diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html index 8eaed7f4f..ab32f79c7 100644 --- a/Doc/Manual/Preprocessor.html +++ b/Doc/Manual/Preprocessor.html @@ -125,7 +125,9 @@ SWIGMZSCHEME Defined when using Mzscheme SWIGOCAML Defined when using Ocaml SWIGOCTAVE Defined when using Octave SWIGPERL Defined when using Perl -SWIGPHP Defined when using PHP +SWIGPHP Defined when using PHP5 or PHP7 +SWIGPHP5 Defined when using PHP5 +SWIGPHP7 Defined when using PHP7 SWIGPIKE Defined when using Pike SWIGPYTHON Defined when using Python SWIGR Defined when using R diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index ae489f574..77481f279 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -131,7 +131,8 @@ can be obtained by typing swig -help or swig -ocaml Generate Ocaml wrappers -octave Generate Octave wrappers -perl Generate Perl wrappers --php Generate PHP wrappers +-php5 Generate PHP5 wrappers +-php7 Generate PHP7 wrappers -pike Generate Pike wrappers -python Generate Python wrappers -r Generate R (aka GNU S) wrappers diff --git a/Examples/Makefile.in b/Examples/Makefile.in index 9b510274a..d10f0f9a2 100644 --- a/Examples/Makefile.in +++ b/Examples/Makefile.in @@ -1116,7 +1116,57 @@ ruby_clean: rm -f *.@OBJEXT@ *$(RUBY_SO) ################################################################## -##### PHP ###### +##### PHP5 ###### +################################################################## + +PHP5 = @PHP5@ +PHP5_INCLUDE = @PHP5INC@ +PHP5_SO = @PHP5_SO@ +PHP5_SCRIPT = $(SRCDIR)$(RUNME).php + +# ------------------------------------------------------------------- +# Build a PHP5 dynamically loadable module (C) +# ------------------------------------------------------------------- + +php5: $(SRCDIR_SRCS) + $(SWIG) -php5 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PHP5_INCLUDE) + $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(PHP5_SO) + +# -------------------------------------------------------------------- +# Build a PHP5 dynamically loadable module (C++) +# -------------------------------------------------------------------- + +php5_cpp: $(SRCDIR_SRCS) + $(SWIG) -php5 -cppext cxx -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PHP5_INCLUDE) + $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(PHP5_SO) + +# ----------------------------------------------------------------- +# Running a PHP5 example +# ----------------------------------------------------------------- + +php5_run: + $(RUNTOOL) $(PHP5) -n -q -d extension_dir=. -d safe_mode=Off $(PHP5_SCRIPT) $(RUNPIPE) + +# ----------------------------------------------------------------- +# Version display +# ----------------------------------------------------------------- + +php5_version: + $(PHP5) -v | head -n 1 + +# ----------------------------------------------------------------- +# Cleaning the PHP5 examples +# ----------------------------------------------------------------- + +php5_clean: + rm -f *_wrap* *~ .~* example.php php_example.h + rm -f core @EXTRA_CLEAN@ + rm -f *.@OBJEXT@ *$(PHP5_SO) + +################################################################## +##### PHP7 ###### ################################################################## PHP = @PHP@ @@ -1129,7 +1179,7 @@ PHP_SCRIPT = $(SRCDIR)$(RUNME).php # ------------------------------------------------------------------- php: $(SRCDIR_SRCS) - $(SWIG) -php $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) + $(SWIG) -php7 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH) $(CC) -c $(CCSHARED) $(CPPFLAGS) $(CFLAGS) $(SRCDIR_SRCS) $(ISRCS) $(INCLUDES) $(PHP_INCLUDE) $(LDSHARED) $(CFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) @@ -1138,7 +1188,7 @@ php: $(SRCDIR_SRCS) # -------------------------------------------------------------------- php_cpp: $(SRCDIR_SRCS) - $(SWIG) -php -cppext cxx -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) + $(SWIG) -php7 -cppext cxx -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH) $(CXX) -c $(CCSHARED) $(CPPFLAGS) $(CXXFLAGS) $(SRCDIR_SRCS) $(SRCDIR_CXXSRCS) $(ICXXSRCS) $(INCLUDES) $(PHP_INCLUDE) $(CXXSHARED) $(CXXFLAGS) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) $(CPP_DLLIBS) -o $(LIBPREFIX)$(TARGET)$(PHP_SO) diff --git a/Examples/php5/callback/Makefile b/Examples/php5/callback/Makefile new file mode 100644 index 000000000..3a34106c3 --- /dev/null +++ b/Examples/php5/callback/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php5_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' $(SWIGLIB) CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php5_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php5_clean diff --git a/Examples/php5/callback/example.cxx b/Examples/php5/callback/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/php5/callback/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/php5/callback/example.h b/Examples/php5/callback/example.h new file mode 100644 index 000000000..2a0194999 --- /dev/null +++ b/Examples/php5/callback/example.h @@ -0,0 +1,22 @@ +/* File : example.h */ + +#include + +class Callback { +public: + virtual ~Callback() { std::cout << "Callback::~Callback()" << std:: endl; } + virtual void run() { std::cout << "Callback::run()" << std::endl; } +}; + + +class Caller { +private: + Callback *_callback; +public: + Caller(): _callback(0) {} + ~Caller() { delCallback(); } + void delCallback() { delete _callback; _callback = 0; } + void setCallback(Callback *cb) { delCallback(); _callback = cb; } + void call() { if (_callback) _callback->run(); } +}; + diff --git a/Examples/php5/callback/example.i b/Examples/php5/callback/example.i new file mode 100644 index 000000000..cf61ef9d2 --- /dev/null +++ b/Examples/php5/callback/example.i @@ -0,0 +1,11 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +/* turn on director wrapping Callback */ +%feature("director") Callback; + +%include "example.h" + diff --git a/Examples/php5/callback/index.html b/Examples/php5/callback/index.html new file mode 100644 index 000000000..2a6cbdff9 --- /dev/null +++ b/Examples/php5/callback/index.html @@ -0,0 +1,19 @@ + + +SWIG:Examples:php5:callback + + + + + +SWIG/Examples/php5/callback/ +
+ +

Implementing C++ callbacks in PHP5

+ +

+This example illustrates how to use directors to implement C++ callbacks in PHP5. + +


+ + diff --git a/Examples/php5/callback/runme.php b/Examples/php5/callback/runme.php new file mode 100644 index 000000000..2be71994f --- /dev/null +++ b/Examples/php5/callback/runme.php @@ -0,0 +1,47 @@ +thisown = 0; +$caller->setCallback($callback); +$caller->call(); +$caller->delCallback(); + +print "\n"; +print "Adding and calling a PHP callback\n"; +print "------------------------------------\n"; + +# Add a PHP callback. + +$callback = new PhpCallback(); +$callback->thisown = 0; +$caller->setCallback($callback); +$caller->call(); +$caller->delCallback(); + +# All done. + +print "php exit\n"; + +?> diff --git a/Examples/php5/check.list b/Examples/php5/check.list new file mode 100644 index 000000000..fef3feba6 --- /dev/null +++ b/Examples/php5/check.list @@ -0,0 +1,19 @@ +# see top-level Makefile.in +# (see also top-level configure.ac kludge) +callback +class +constants +cpointer +disown +enum +extend +funcptr +overloading +pointer +pragmas +proxy +reference +simple +sync +value +variables diff --git a/Examples/php5/class/Makefile b/Examples/php5/class/Makefile new file mode 100644 index 000000000..8346a1dae --- /dev/null +++ b/Examples/php5/class/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php5_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php5_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php5_clean diff --git a/Examples/php5/class/example.cxx b/Examples/php5/class/example.cxx new file mode 100644 index 000000000..046304519 --- /dev/null +++ b/Examples/php5/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/php5/class/example.h b/Examples/php5/class/example.h new file mode 100644 index 000000000..0dff185b2 --- /dev/null +++ b/Examples/php5/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/php5/class/example.i b/Examples/php5/class/example.i new file mode 100644 index 000000000..fbdf7249f --- /dev/null +++ b/Examples/php5/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/php5/class/runme.php b/Examples/php5/class/runme.php new file mode 100644 index 000000000..99c253b46 --- /dev/null +++ b/Examples/php5/class/runme.php @@ -0,0 +1,60 @@ +x = 20; +$c->y = 30; +$s->x = -10; +$s->y = 5; + +print "\nHere is their current position:\n"; +print " Circle = ({$c->x},{$c->y})\n"; +print " Square = ({$s->x},{$s->y})\n"; + +# ----- Call some methods ----- + +# Notice how the Shape_area() and Shape_perimeter() functions really +# invoke the appropriate virtual method on each object. +print "\nHere are some properties of the shapes:\n"; +foreach (array($c,$s) as $o) { + print " ". get_class($o) . "\n"; + print " area = {$o->area()}\n"; + print " perimeter = {$o->perimeter()}\n"; +} + +# ----- Delete everything ----- + +print "\nGuess I'll clean up now\n"; + +# Note: this invokes the virtual destructor +$c = NULL; +$s = NULL; + +# and don't forget the $o from the for loop above. It still refers to +# the square. +$o = NULL; + +print Shape::nshapes() . " shapes remain\n"; +print "Goodbye\n"; + +?> diff --git a/Examples/php5/constants/Makefile b/Examples/php5/constants/Makefile new file mode 100644 index 000000000..a05be202b --- /dev/null +++ b/Examples/php5/constants/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/constants/example.i b/Examples/php5/constants/example.i new file mode 100644 index 000000000..0098a893a --- /dev/null +++ b/Examples/php5/constants/example.i @@ -0,0 +1,26 @@ +/* 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 statements also produce constants */ +%constant int iconst = 37; +%constant double fconst = 3.14; + + diff --git a/Examples/php5/constants/runme.php b/Examples/php5/constants/runme.php new file mode 100644 index 000000000..cea06485f --- /dev/null +++ b/Examples/php5/constants/runme.php @@ -0,0 +1,28 @@ + diff --git a/Examples/php5/cpointer/Makefile b/Examples/php5/cpointer/Makefile new file mode 100644 index 000000000..47e5ed9f9 --- /dev/null +++ b/Examples/php5/cpointer/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/cpointer/example.c b/Examples/php5/cpointer/example.c new file mode 100644 index 000000000..04dd08df0 --- /dev/null +++ b/Examples/php5/cpointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(int *x, int *y, int *result) { + *result = *x + *y; +} + +void sub(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/php5/cpointer/example.i b/Examples/php5/cpointer/example.i new file mode 100644 index 000000000..c61d92858 --- /dev/null +++ b/Examples/php5/cpointer/example.i @@ -0,0 +1,31 @@ +/* File : example.i */ +%module example + +%{ +extern void add(int *, int *, int *); +extern void sub(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 sub(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/php5/cpointer/runme.php b/Examples/php5/cpointer/runme.php new file mode 100644 index 000000000..22e8a681a --- /dev/null +++ b/Examples/php5/cpointer/runme.php @@ -0,0 +1,47 @@ + diff --git a/Examples/php5/disown/Makefile b/Examples/php5/disown/Makefile new file mode 100644 index 000000000..063a0645f --- /dev/null +++ b/Examples/php5/disown/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/disown/example.cxx b/Examples/php5/disown/example.cxx new file mode 100644 index 000000000..6393735e9 --- /dev/null +++ b/Examples/php5/disown/example.cxx @@ -0,0 +1,51 @@ +/* File : example.c */ + +#include "example.h" +#include +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +int Shape::get_nshapes() { + return nshapes; +} + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +void Circle::set_radius( double r ) { + radius = r; +} + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} + +ShapeContainer::~ShapeContainer() { + iterator i=shapes.begin(); + for( iterator i = shapes.begin(); i != shapes.end(); ++i ) { + delete *i; + } +} + +void +ShapeContainer::addShape( Shape *s ) { + shapes.push_back( s ); +} diff --git a/Examples/php5/disown/example.h b/Examples/php5/disown/example.h new file mode 100644 index 000000000..e9f96743f --- /dev/null +++ b/Examples/php5/disown/example.h @@ -0,0 +1,50 @@ +/* File : example.h */ + +#include + +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; + static int get_nshapes(); +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + ~Circle() { } + void set_radius( double r ); + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + ~Square() { } + virtual double area(void); + virtual double perimeter(void); +}; + +class ShapeContainer { +private: + typedef std::vector::iterator iterator; + std::vector shapes; +public: + ShapeContainer() : shapes() {} + ~ShapeContainer(); + void addShape( Shape *s ); +}; diff --git a/Examples/php5/disown/example.i b/Examples/php5/disown/example.i new file mode 100644 index 000000000..599f162c5 --- /dev/null +++ b/Examples/php5/disown/example.i @@ -0,0 +1,12 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%apply SWIGTYPE *DISOWN {(Shape *s)}; + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/php5/disown/runme.php b/Examples/php5/disown/runme.php new file mode 100644 index 000000000..d90b03a9d --- /dev/null +++ b/Examples/php5/disown/runme.php @@ -0,0 +1,49 @@ +addShape($c); +$container->addShape($s); + +# ----- Access a static member ----- + +print "\nA total of " . Shape::nshapes() . " shapes were created\n"; + +# ----- Delete by the old references ----- +# This should not truely delete the shapes because they are now owned +# by the ShapeContainer. + +print "Delete the old references."; + +# Note: this invokes the virtual destructor +$c = NULL; +$s = NULL; + +print "\nA total of " . Shape::nshapes() . " shapes remain\n"; + +# ----- Delete by the container ----- +# This should truely delete the shapes + +print "Delete the container."; +$container = NULL; +print "\nA total of " . Shape::nshapes() . " shapes remain\n"; + +print "Goodbye\n"; + +?> diff --git a/Examples/php5/enum/Makefile b/Examples/php5/enum/Makefile new file mode 100644 index 000000000..4483f781e --- /dev/null +++ b/Examples/php5/enum/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = -noproxy + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/enum/example.cxx b/Examples/php5/enum/example.cxx new file mode 100644 index 000000000..df7bb6328 --- /dev/null +++ b/Examples/php5/enum/example.cxx @@ -0,0 +1,37 @@ +/* File : example.cxx */ + +#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/php5/enum/example.h b/Examples/php5/enum/example.h new file mode 100644 index 000000000..525d62afc --- /dev/null +++ b/Examples/php5/enum/example.h @@ -0,0 +1,13 @@ +/* File : example.h */ + +enum color { RED, BLUE, GREEN }; + +class Foo { + public: + Foo() { } + enum speed { IMPULSE, WARP, LUDICROUS }; + void enum_test(speed s); +}; + +void enum_test(color c, Foo::speed s); + diff --git a/Examples/php5/enum/example.i b/Examples/php5/enum/example.i new file mode 100644 index 000000000..abf254731 --- /dev/null +++ b/Examples/php5/enum/example.i @@ -0,0 +1,12 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + + +/* Let's just grab the original header file here */ + +%include "example.h" + diff --git a/Examples/php5/enum/runme.php b/Examples/php5/enum/runme.php new file mode 100644 index 000000000..55b0bc4c3 --- /dev/null +++ b/Examples/php5/enum/runme.php @@ -0,0 +1,32 @@ + diff --git a/Examples/php5/extend/Makefile b/Examples/php5/extend/Makefile new file mode 100644 index 000000000..7f91fd56c --- /dev/null +++ b/Examples/php5/extend/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = -lm +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' $(SWIGLIB) CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/extend/example.cxx b/Examples/php5/extend/example.cxx new file mode 100644 index 000000000..450d75608 --- /dev/null +++ b/Examples/php5/extend/example.cxx @@ -0,0 +1,4 @@ +/* File : example.cxx */ + +#include "example.h" + diff --git a/Examples/php5/extend/example.h b/Examples/php5/extend/example.h new file mode 100644 index 000000000..ca1aed28f --- /dev/null +++ b/Examples/php5/extend/example.h @@ -0,0 +1,56 @@ +/* File : example.h */ + +#include +#include +#include +#include +#include + +class Employee { +private: + std::string name; +public: + Employee(const char* n): name(n) {} + virtual std::string getTitle() { return getPosition() + " " + getName(); } + virtual std::string getName() { return name; } + virtual std::string getPosition() const { return "Employee"; } + virtual ~Employee() { printf("~Employee() @ %p\n", (void *)this); } +}; + + +class Manager: public Employee { +public: + Manager(const char* n): Employee(n) {} + virtual std::string getPosition() const { return "Manager"; } +}; + + +class EmployeeList { + std::vector list; +public: + EmployeeList() { + list.push_back(new Employee("Bob")); + list.push_back(new Employee("Jane")); + list.push_back(new Manager("Ted")); + } + void addEmployee(Employee *p) { + list.push_back(p); + std::cout << "New employee added. Current employees are:" << std::endl; + std::vector::iterator i; + for (i=list.begin(); i!=list.end(); i++) { + std::cout << " " << (*i)->getTitle() << std::endl; + } + } + const Employee *get_item(int i) { + return list[i]; + } + ~EmployeeList() { + std::vector::iterator i; + std::cout << "~EmployeeList, deleting " << list.size() << " employees." << std::endl; + for (i=list.begin(); i!=list.end(); i++) { + delete *i; + } + std::cout << "~EmployeeList empty." << std::endl; + } +}; + diff --git a/Examples/php5/extend/example.i b/Examples/php5/extend/example.i new file mode 100644 index 000000000..c8ec32e09 --- /dev/null +++ b/Examples/php5/extend/example.i @@ -0,0 +1,15 @@ +/* File : example.i */ +%module(directors="1") example +%{ +#include "example.h" +%} + +%include "std_vector.i" +%include "std_string.i" + +/* turn on director wrapping for Manager */ +%feature("director") Employee; +%feature("director") Manager; + +%include "example.h" + diff --git a/Examples/php5/extend/index.html b/Examples/php5/extend/index.html new file mode 100644 index 000000000..32c6a4913 --- /dev/null +++ b/Examples/php5/extend/index.html @@ -0,0 +1,19 @@ + + +SWIG:Examples:php:extend + + + + + +SWIG/Examples/php/extend/ +
+ +

Extending a simple C++ class in PHP

+ +

+This example illustrates the extending of a C++ class with cross language polymorphism. + +


+ + diff --git a/Examples/php5/extend/runme.php b/Examples/php5/extend/runme.php new file mode 100644 index 000000000..158683142 --- /dev/null +++ b/Examples/php5/extend/runme.php @@ -0,0 +1,76 @@ +getName() . " is a " . $e->getPosition() . "\n"; +printf("Just call her \"%s\"\n", $e->getTitle()); +print "----------------------\n"; + +# Create a new EmployeeList instance. This class does not have a C++ +# director wrapper, but can be used freely with other classes that do. + +$list = new EmployeeList(); + +# EmployeeList owns its items, so we must surrender ownership of objects +# we add. This involves first clearing the ->disown member to tell the +# C++ director to start reference counting. + +$e->thisown = 0; +$list->addEmployee($e); +print "----------------------\n"; + +# Now we access the first four items in list (three are C++ objects that +# EmployeeList's constructor adds, the last is our CEO). The virtual +# methods of all these instances are treated the same. For items 0, 1, and +# 2, both all methods resolve in C++. For item 3, our CEO, getTitle calls +# getPosition which resolves in PHP. The call to getPosition is +# slightly different, however, from the e.getPosition() call above, since +# now the object reference has been "laundered" by passing through +# EmployeeList as an Employee*. Previously, PHP resolved the call +# immediately in CEO, but now PHP thinks the object is an instance of +# class Employee (actually EmployeePtr). So the call passes through the +# Employee proxy class and on to the C wrappers and C++ director, +# eventually ending up back at the CEO implementation of getPosition(). +# The call to getTitle() for item 3 runs the C++ Employee::getTitle() +# method, which in turn calls getPosition(). This virtual method call +# passes down through the C++ director class to the PHP implementation +# in CEO. All this routing takes place transparently. + +print "(position, title) for items 0-3:\n"; + +printf(" %s, \"%s\"\n", $list->get_item(0)->getPosition(), $list->get_item(0)->getTitle()); +printf(" %s, \"%s\"\n", $list->get_item(1)->getPosition(), $list->get_item(1)->getTitle()); +printf(" %s, \"%s\"\n", $list->get_item(2)->getPosition(), $list->get_item(2)->getTitle()); +printf(" %s, \"%s\"\n", $list->get_item(3)->getPosition(), $list->get_item(3)->getTitle()); +print "----------------------\n"; + +# Time to delete the EmployeeList, which will delete all the Employee* +# items it contains. The last item is our CEO, which gets destroyed as its +# reference count goes to zero. The PHP destructor runs, and is still +# able to call the getName() method since the underlying C++ object still +# exists. After this destructor runs the remaining C++ destructors run as +# usual to destroy the object. + +unset($list); +print "----------------------\n"; + +# All done. + +print "php exit\n"; + +?> diff --git a/Examples/php5/funcptr/Makefile b/Examples/php5/funcptr/Makefile new file mode 100644 index 000000000..47e5ed9f9 --- /dev/null +++ b/Examples/php5/funcptr/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/funcptr/example.c b/Examples/php5/funcptr/example.c new file mode 100644 index 000000000..99583b72e --- /dev/null +++ b/Examples/php5/funcptr/example.c @@ -0,0 +1,17 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} diff --git a/Examples/php5/funcptr/example.h b/Examples/php5/funcptr/example.h new file mode 100644 index 000000000..58989db79 --- /dev/null +++ b/Examples/php5/funcptr/example.h @@ -0,0 +1,7 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + diff --git a/Examples/php5/funcptr/example.i b/Examples/php5/funcptr/example.i new file mode 100644 index 000000000..39390da27 --- /dev/null +++ b/Examples/php5/funcptr/example.i @@ -0,0 +1,15 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Wrap a function taking a pointer to a function */ +extern int do_op(int a, int b, int (*op)(int, int)); + +/* Now install a bunch of "ops" as constants */ +%constant int (*ADD)(int,int) = add; +%constant int (*SUB)(int,int) = sub; +%constant int (*MUL)(int,int) = mul; + + diff --git a/Examples/php5/funcptr/runme.php b/Examples/php5/funcptr/runme.php new file mode 100644 index 000000000..712d4147c --- /dev/null +++ b/Examples/php5/funcptr/runme.php @@ -0,0 +1,24 @@ + + diff --git a/Examples/php5/overloading/Makefile b/Examples/php5/overloading/Makefile new file mode 100644 index 000000000..063a0645f --- /dev/null +++ b/Examples/php5/overloading/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/overloading/example.cxx b/Examples/php5/overloading/example.cxx new file mode 100644 index 000000000..2f684f05c --- /dev/null +++ b/Examples/php5/overloading/example.cxx @@ -0,0 +1,55 @@ +/* File : example.c */ + +#include "example.h" +#include +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +int Shape::get_nshapes() { + return nshapes; +} + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} + +const char *overloaded(int i) { + return "Overloaded with int"; +} + +const char *overloaded(double d) { + return "Overloaded with double"; +} + +const char *overloaded(const char * str) { + return "Overloaded with char *"; +} + +const char *overloaded( const Circle& ) { + return "Overloaded with Circle"; +} + +const char *overloaded( const Shape& ) { + return "Overloaded with Shape"; +} diff --git a/Examples/php5/overloading/example.h b/Examples/php5/overloading/example.h new file mode 100644 index 000000000..01d71dd70 --- /dev/null +++ b/Examples/php5/overloading/example.h @@ -0,0 +1,46 @@ +/* File : example.h */ + +#include + +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; + static int get_nshapes(); +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + ~Circle() { } + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + ~Square() { } + virtual double area(void); + virtual double perimeter(void); +}; + +const char *overloaded( int i ); +const char *overloaded( double d ); +const char *overloaded( const char * str ); +const char *overloaded( const Circle& ); +const char *overloaded( const Shape& ); + diff --git a/Examples/php5/overloading/example.i b/Examples/php5/overloading/example.i new file mode 100644 index 000000000..950d2549d --- /dev/null +++ b/Examples/php5/overloading/example.i @@ -0,0 +1,8 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%include "example.h" diff --git a/Examples/php5/overloading/runme.php b/Examples/php5/overloading/runme.php new file mode 100644 index 000000000..56d515138 --- /dev/null +++ b/Examples/php5/overloading/runme.php @@ -0,0 +1,58 @@ +x = 20; +$c->y = 30; +$s->x = -10; +$s->y = 5; + +print "\nHere is their current position:\n"; +print " Circle = (" . $c->x . "," . $c->y . ")\n"; +print " Square = (" . $s->x . "," . $s->y . ")\n"; + +# ----- Call some methods ----- + +print "\nCall some overloaded methods:\n"; +foreach (array(1, 2.1, "quick brown fox", $c, $s) as $o) { + print " overloaded = " . overloaded($o) . "\n"; +} + +# Need to unset($o) or else we hang on to a reference to the Square object. +unset($o); + +# ----- Delete everything ----- + +print "\nGuess I'll clean up now\n"; + +# Note: this invokes the virtual destructor +unset($c); +$s = 42; + +print Shape::nshapes() . " shapes remain\n"; + +print "Goodbye\n"; + +?> diff --git a/Examples/php5/pointer/Makefile b/Examples/php5/pointer/Makefile new file mode 100644 index 000000000..47e5ed9f9 --- /dev/null +++ b/Examples/php5/pointer/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/pointer/example.c b/Examples/php5/pointer/example.c new file mode 100644 index 000000000..3326dec3e --- /dev/null +++ b/Examples/php5/pointer/example.c @@ -0,0 +1,16 @@ +/* File : example.c */ + +void add(double *x, double *y, double *result) { + *result = *x + *y; +} + +void sub(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/php5/pointer/example.i b/Examples/php5/pointer/example.i new file mode 100644 index 000000000..1f0059406 --- /dev/null +++ b/Examples/php5/pointer/example.i @@ -0,0 +1,30 @@ +/* File : example.i */ +%module example + +%{ +extern void add(double *, double *, double *); +extern void sub(int *, int *, int *); +extern int divide(int, int, int *); +%} + +/* This example illustrates a couple of different techniques + for manipulating C pointers */ + +%include phppointers.i +/* First we'll use the pointer library */ +extern void add(double *REF, double *REF, double *REF); + +/* Next we'll use some typemaps */ + +%include typemaps.i +extern void sub(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/php5/pointer/runme.php b/Examples/php5/pointer/runme.php new file mode 100644 index 000000000..e79b23810 --- /dev/null +++ b/Examples/php5/pointer/runme.php @@ -0,0 +1,35 @@ + diff --git a/Examples/php5/pragmas/Makefile b/Examples/php5/pragmas/Makefile new file mode 100644 index 000000000..a05be202b --- /dev/null +++ b/Examples/php5/pragmas/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/pragmas/example.i b/Examples/php5/pragmas/example.i new file mode 100644 index 000000000..c7e8bf303 --- /dev/null +++ b/Examples/php5/pragmas/example.i @@ -0,0 +1,31 @@ +/* File : example.i */ +%module example + +%init{ + zend_printf("This was %%init\n"); +} + +%minit{ + zend_printf("This was %%minit\n"); +} + +%mshutdown{ + zend_printf("This was %%shutdown\n"); +} + +%rinit{ + zend_printf("This was %%rinit\n"); +} + +%rshutdown{ + zend_printf("This was %%rshutdown\n"); +} + +%pragma(php) include="include.php"; + +%pragma(php) code=" +# This code is inserted into example.php +echo \"this was php code\\n\"; +" + +%pragma(php) phpinfo="php_info_print_table_start();" diff --git a/Examples/php5/pragmas/include.php b/Examples/php5/pragmas/include.php new file mode 100644 index 000000000..e19880a06 --- /dev/null +++ b/Examples/php5/pragmas/include.php @@ -0,0 +1,7 @@ + diff --git a/Examples/php5/pragmas/runme.php b/Examples/php5/pragmas/runme.php new file mode 100644 index 000000000..538548b6f --- /dev/null +++ b/Examples/php5/pragmas/runme.php @@ -0,0 +1,5 @@ + diff --git a/Examples/php5/proxy/Makefile b/Examples/php5/proxy/Makefile new file mode 100644 index 000000000..063a0645f --- /dev/null +++ b/Examples/php5/proxy/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/proxy/example.cxx b/Examples/php5/proxy/example.cxx new file mode 100644 index 000000000..94e4a7888 --- /dev/null +++ b/Examples/php5/proxy/example.cxx @@ -0,0 +1,43 @@ +/* File : example.c */ + +#include "example.h" +#include +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +int Shape::get_nshapes() { + return nshapes; +} + +/* Move the shape to a new location */ +void Shape::move(double dx, double dy) { + x += dx; + y += dy; +} + +int Shape::nshapes = 0; + +void Circle::set_radius( double r ) { + radius = r; +} + +double Circle::area(void) { + return M_PI*radius*radius; +} + +double Circle::perimeter(void) { + return 2*M_PI*radius; +} + +double Square::area(void) { + return width*width; +} + +double Square::perimeter(void) { + return 4*width; +} + +Circle *CircleFactory( double r ) { + return new Circle(r); +} diff --git a/Examples/php5/proxy/example.h b/Examples/php5/proxy/example.h new file mode 100644 index 000000000..0683f07f3 --- /dev/null +++ b/Examples/php5/proxy/example.h @@ -0,0 +1,43 @@ +/* File : example.h */ + +#include + +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; + static int get_nshapes(); +}; + +class Circle : public Shape { +private: + double radius; +public: + Circle(double r) : radius(r) { } + ~Circle() { } + void set_radius( double r ); + virtual double area(void); + virtual double perimeter(void); +}; + +class Square : public Shape { +private: + double width; +public: + Square(double w) : width(w) { } + ~Square() { } + virtual double area(void); + virtual double perimeter(void); +}; + +Circle *CircleFactory( double r ); + diff --git a/Examples/php5/proxy/example.i b/Examples/php5/proxy/example.i new file mode 100644 index 000000000..ce73746d0 --- /dev/null +++ b/Examples/php5/proxy/example.i @@ -0,0 +1,12 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +/* Let's just grab the original header file here */ + +%newobject CircleFactory; +%include "example.h" + diff --git a/Examples/php5/proxy/runme.php b/Examples/php5/proxy/runme.php new file mode 100644 index 000000000..e70ab229f --- /dev/null +++ b/Examples/php5/proxy/runme.php @@ -0,0 +1,68 @@ +area() ."\n"; +$s = new Square(10); +print " Created square \$s\n"; + +# ----- Access a static member ----- + +print "\nA total of " . Shape::nshapes() . " shapes were created\n"; + +# ----- 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; + +print "\nHere is their current position:\n"; +print " Circle = (" . $c->x . "," . $c->y . ")\n"; +print " Square = (" . $s->x . "," . $s->y . ")\n"; + +# ----- Call some methods ----- + +print "\nHere are some properties of the shapes:\n"; +foreach (array($c,$s) as $o) { + print " ".get_class($o)." \$o\n"; + print " x = " . $o->x . "\n"; + print " y = " . $o->y . "\n"; + print " area = " . $o->area() . "\n"; + print " perimeter = " . $o->perimeter() . "\n"; + } + +# Need to unset($o) or else we hang on to a reference to the Square object. +unset($o); + +# ----- Delete everything ----- + +print "\nGuess I'll clean up now\n"; + +# Note: this invokes the virtual destructor +unset($c); +$s = 42; + +print Shape::nshapes() . " shapes remain\n"; + +print "Manually setting nshapes\n"; + +Shape::nshapes(42); + +print Shape::get_nshapes() ." == 42\n"; + +print "Goodbye\n"; + +?> diff --git a/Examples/php5/reference/Makefile b/Examples/php5/reference/Makefile new file mode 100644 index 000000000..063a0645f --- /dev/null +++ b/Examples/php5/reference/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/reference/example.cxx b/Examples/php5/reference/example.cxx new file mode 100644 index 000000000..7ead7fbf6 --- /dev/null +++ b/Examples/php5/reference/example.cxx @@ -0,0 +1,49 @@ +/* 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::as_string() { + static char temp[512]; + sprintf(temp,"Vector %p (%g,%g,%g)", (void *)this, x,y,z); + return temp; +} + +VectorArray::VectorArray(int size) { + items = new Vector[size]; + maxsize = size; + printf("VectorArray new: self=%p\n", (void *)this); +} + +VectorArray::~VectorArray() { + printf("VectorArray delete: self=%p\n", (void *)this); + delete [] items; +} + +Vector &VectorArray::operator[](int index) { + printf("VectorArray: read[%d] self=%p\n", index, (void *)this); + if ((index < 0) || (index >= maxsize)) { + printf("Panic! Array index out of bounds.\n"); + exit(1); + } + return items[index]; +} + +int VectorArray::size() { + printf("VectorArray: size %d self=%p\n", maxsize, (void *)this); + return maxsize; +} diff --git a/Examples/php5/reference/example.h b/Examples/php5/reference/example.h new file mode 100644 index 000000000..353b88835 --- /dev/null +++ b/Examples/php5/reference/example.h @@ -0,0 +1,22 @@ +/* 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 *as_string(); +}; + +class VectorArray { +private: + Vector *items; + int maxsize; +public: + VectorArray(int maxsize); + ~VectorArray(); + Vector &operator[](int); + int size(); +}; diff --git a/Examples/php5/reference/example.i b/Examples/php5/reference/example.i new file mode 100644 index 000000000..df1459921 --- /dev/null +++ b/Examples/php5/reference/example.i @@ -0,0 +1,43 @@ +/* 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 *as_string(); +}; + +/* 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) { + printf("VectorArray extended get: %p %d\n", (void *)$self, index); + return (*$self)[index]; + } + void set(int index, Vector &a) { + (*$self)[index] = a; + } + } +}; diff --git a/Examples/php5/reference/runme.php b/Examples/php5/reference/runme.php new file mode 100644 index 000000000..5d264ee43 --- /dev/null +++ b/Examples/php5/reference/runme.php @@ -0,0 +1,49 @@ +as_string()}\n"; +print " Created b: {$b->as_string()}\n"; + +# ----- Call an overloaded operator ----- + +# This calls the wrapper we placed around +# +# operator+(const Vector &a, const Vector &) +# +# It returns a new allocated object. + +print "Adding a+b\n"; +$c = example::addv($a, $b); +print " a+b ={$c->as_string()}\n"; + +# ----- Create a vector array ----- + +print "Creating an array of vectors\n"; +$va = new VectorArray(10); + +print " va: size={$va->size()}\n"; + +# ----- Set some values in the array ----- + +# These operators copy the value of $a and $b to the vector array +$va->set(0, $a); +$va->set(1, $b); +$va->set(2, addv($a, $b)); + +# Get some values from the array + +print "Getting some array values\n"; +for ($i = 0; $i < 5; $i++) { + print " va[$i] = {$va->get($i)->as_string()}\n"; +} + +?> diff --git a/Examples/php5/simple/Makefile b/Examples/php5/simple/Makefile new file mode 100644 index 000000000..47e5ed9f9 --- /dev/null +++ b/Examples/php5/simple/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/simple/example.c b/Examples/php5/simple/example.c new file mode 100644 index 000000000..2fe275632 --- /dev/null +++ b/Examples/php5/simple/example.c @@ -0,0 +1,23 @@ +/* File : example.c */ +#include + +/* A global variable */ +double Foo = 3.0; + +void print_Foo() { + printf("In C, Foo = %f\n",Foo); +} + +/* 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/php5/simple/example.i b/Examples/php5/simple/example.i new file mode 100644 index 000000000..9d4e22aa9 --- /dev/null +++ b/Examples/php5/simple/example.i @@ -0,0 +1,8 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +void print_Foo(); +%} diff --git a/Examples/php5/simple/runme.php b/Examples/php5/simple/runme.php new file mode 100644 index 000000000..0e96fe800 --- /dev/null +++ b/Examples/php5/simple/runme.php @@ -0,0 +1,25 @@ + diff --git a/Examples/php5/sync/Makefile b/Examples/php5/sync/Makefile new file mode 100644 index 000000000..063a0645f --- /dev/null +++ b/Examples/php5/sync/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +CXXSRCS = example.cxx +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php_cpp + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/sync/example.cxx b/Examples/php5/sync/example.cxx new file mode 100644 index 000000000..0942279b2 --- /dev/null +++ b/Examples/php5/sync/example.cxx @@ -0,0 +1,13 @@ +#include "example.h" +#include + +int x = 42; +char *s = (char *)"Test"; + +void Sync::printer(void) { + + printf("The value of global s is %s\n", s); + printf("The value of global x is %d\n", x); + printf("The value of class s is %s\n", s); + printf("The value of class x is %d\n", x); +} diff --git a/Examples/php5/sync/example.h b/Examples/php5/sync/example.h new file mode 100644 index 000000000..d67ec21dc --- /dev/null +++ b/Examples/php5/sync/example.h @@ -0,0 +1,9 @@ +extern char *s; +extern int x; + +class Sync { + public: + int x; + char *s; + void printer(void); +}; diff --git a/Examples/php5/sync/example.i b/Examples/php5/sync/example.i new file mode 100644 index 000000000..17ff87cf3 --- /dev/null +++ b/Examples/php5/sync/example.i @@ -0,0 +1,7 @@ +%module example + +%{ +#include "example.h" +%} + +%include "example.h" diff --git a/Examples/php5/sync/runme.php b/Examples/php5/sync/runme.php new file mode 100644 index 000000000..a7c43474f --- /dev/null +++ b/Examples/php5/sync/runme.php @@ -0,0 +1,15 @@ +printer(); + +?> + diff --git a/Examples/php5/value/Makefile b/Examples/php5/value/Makefile new file mode 100644 index 000000000..28fc3a127 --- /dev/null +++ b/Examples/php5/value/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = -noproxy + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/value/example.c b/Examples/php5/value/example.c new file mode 100644 index 000000000..3c402a214 --- /dev/null +++ b/Examples/php5/value/example.c @@ -0,0 +1,13 @@ +/* File : example.c */ + +#include "example.h" + +double dot_product(Vector a, Vector b) { + return (a.x*b.x + a.y*b.y + a.z*b.z); +} + +void vector_add(Vector a, Vector b, Vector* result) { + result->x = a.x + b.x; + result->y = a.y + b.y; + result->z = a.z + b.z; +} diff --git a/Examples/php5/value/example.h b/Examples/php5/value/example.h new file mode 100644 index 000000000..f55752a5f --- /dev/null +++ b/Examples/php5/value/example.h @@ -0,0 +1,8 @@ +/* File : example.h */ + +typedef struct { + double x, y, z; +} Vector; + +double dot_product(Vector a, Vector b); +void vector_add(Vector a, Vector b, Vector* result); diff --git a/Examples/php5/value/example.i b/Examples/php5/value/example.i new file mode 100644 index 000000000..20a453468 --- /dev/null +++ b/Examples/php5/value/example.i @@ -0,0 +1,17 @@ +// Tests SWIG's handling of pass-by-value for complex datatypes +%module example + +%{ +#include "example.h" +%} + +%include "example.h" + +/* Some helper functions for our interface */ +%inline %{ + +void vector_print(Vector *v) { + printf("Vector %p = (%g, %g, %g)\n", (void *)v, v->x, v->y, v->z); +} +%} + diff --git a/Examples/php5/value/runme.php b/Examples/php5/value/runme.php new file mode 100644 index 000000000..49115376c --- /dev/null +++ b/Examples/php5/value/runme.php @@ -0,0 +1,43 @@ + + + diff --git a/Examples/php5/variables/Makefile b/Examples/php5/variables/Makefile new file mode 100644 index 000000000..47e5ed9f9 --- /dev/null +++ b/Examples/php5/variables/Makefile @@ -0,0 +1,20 @@ +TOP = ../.. +SWIGEXE = $(TOP)/../swig +SWIG_LIB_DIR = $(TOP)/../$(TOP_BUILDDIR_TO_TOP_SRCDIR)Lib +SRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = +SWIGOPT = + +check: build + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_run + +build: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' SRCS='$(SRCS)' \ + SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \ + SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' \ + php + +clean: + $(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' php_clean diff --git a/Examples/php5/variables/example.c b/Examples/php5/variables/example.c new file mode 100644 index 000000000..d4c6d026d --- /dev/null +++ b/Examples/php5/variables/example.c @@ -0,0 +1,95 @@ +/* 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; +const char cstrvar[] = "Goodbye"; +int *iptrvar = 0; +char name[5] = "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", (void *)iptrvar); + printf("name = %c%c%c%c%c\n", name[0],name[1],name[2],name[3],name[4]); + printf("ptptr = %p %s\n", (void *)ptptr, Point_print( ptptr ) ); + 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; +} + +int value_int(int *value) { + return *value; +} + +/* 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/php5/variables/example.h b/Examples/php5/variables/example.h new file mode 100644 index 000000000..3b3659ce5 --- /dev/null +++ b/Examples/php5/variables/example.h @@ -0,0 +1,34 @@ +/* File: example.h */ + +typedef struct { + int x,y; +} Point; + +/* Some global variable declarations */ +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[5]; + +extern Point *ptptr; +extern Point pt; + +extern int status; +extern char path[256]; + +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/php5/variables/example.i b/Examples/php5/variables/example.i new file mode 100644 index 000000000..3edbb72d7 --- /dev/null +++ b/Examples/php5/variables/example.i @@ -0,0 +1,44 @@ +/* File : example.i */ +%module example +%{ +#include "example.h" +%} + +/* Some global variable declarations */ +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[5]; + +extern Point *ptptr; +extern Point pt; + +/* Some read-only variables */ + +%immutable; +extern int status; +extern char path[256]; +%mutable; + +/* Some helper functions to make it easier to test */ +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/php5/variables/runme.php b/Examples/php5/variables/runme.php new file mode 100644 index 000000000..bbfeb610b --- /dev/null +++ b/Examples/php5/variables/runme.php @@ -0,0 +1,96 @@ + + diff --git a/Examples/test-suite/php/director_thread_runme.php b/Examples/test-suite/php/director_thread_runme.php index 809dec3e2..ab0563213 100644 --- a/Examples/test-suite/php/director_thread_runme.php +++ b/Examples/test-suite/php/director_thread_runme.php @@ -3,7 +3,8 @@ require "tests.php"; require "director_thread.php"; -# Fails in a ZTS-build of PHP - see: https://github.com/swig/swig/pull/155 +# Fails in a ZTS-build of PHP5 - see: https://github.com/swig/swig/pull/155 +# FIXME: Does this still fail in a threaded build of PHP7? exit(0); // No new functions diff --git a/Examples/test-suite/php5/Makefile.in b/Examples/test-suite/php5/Makefile.in new file mode 100644 index 000000000..307fecea3 --- /dev/null +++ b/Examples/test-suite/php5/Makefile.in @@ -0,0 +1,79 @@ +####################################################################### +# Makefile for php5 test-suite +####################################################################### + +LANGUAGE = php5 +SCRIPTSUFFIX = _runme.php + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = @top_builddir@ + +CPP_TEST_CASES += \ + callback \ + php_iterator \ + php_namewarn_rename \ + +include $(srcdir)/../common.mk + +# Overridden variables here +TARGETPREFIX =# Should be php_ for Windows, empty otherwise + +# Custom tests - tests with additional commandline options +prefix.cpptest: SWIGOPT += -prefix Project + +# write out tests without a _runme.php +missingcpptests: + for test in $(CPP_TEST_CASES) ; do test -f $${test}_runme.php || echo $${test}; done + +missingctests: + for test in $(C_TEST_CASES) ; do test -f $${test}_runme.php || echo $${test}; done + +missingtests: missingcpptests missingctests + +# Rules for the different types of tests +%.cpptest: + $(setup) + +$(swig_and_compile_cpp) + +$(run_testcase) + +%.ctest: + $(setup) + +$(swig_and_compile_c) + +$(run_testcase) + +%.multicpptest: + $(setup) + +$(swig_and_compile_multi_cpp) + +$(run_testcase) + +# Smart target +%.test: + @echo ' $(C_TEST_CASES) '|grep -F -v ' $* ' >/dev/null ||\ + $(MAKE) $*.ctest + @echo ' $(CPP_TEST_CASES) '|grep -F -v ' $* ' >/dev/null ||\ + $(MAKE) $*.cpptest + @echo ' $(MULTI_CPP_TEST_CASES) '|grep -F -v ' $* ' >/dev/null ||\ + $(MAKE) $*.multicpptest + +# Runs the testcase. Tries to run testcase_runme.php, and if that's not +# found, runs testcase.php, except for multicpptests. +run_testcase = \ + if [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP5_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*$(SCRIPTSUFFIX) RUNTOOL='$(RUNTOOL)' php5_run; \ + elif [ -f $(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php -a ! -f $(top_srcdir)/$(EXAMPLES)/$(TEST_SUITE)/$*.list ]; then \ + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile PHP5_SCRIPT=$(SCRIPTDIR)/$(SCRIPTPREFIX)$*.php RUNTOOL='$(RUNTOOL)' php5_run; \ + fi + +# Clean: remove the generated .php file +%.clean: + @rm -f $*.php php_$*.h + +clean: + $(MAKE) -f $(top_builddir)/$(EXAMPLES)/Makefile SRCDIR='$(SRCDIR)' php5_clean + rm -f clientdata_prop_a.php clientdata_prop_b.php php_clientdata_prop_a.h php_clientdata_prop_b.h + rm -f import_stl_a.php import_stl_b.php php_import_stl_a.h php_import_stl_b.h + rm -f imports_a.php imports_b.php php_imports_a.h php_imports_b.h + rm -f mod_a.php mod_b.php php_mod_a.h php_mod_b.h + rm -f multi_import_a.php multi_import_b.php php_multi_import_a.h php_multi_import_b.h + rm -f packageoption_a.php packageoption_b.php packageoption_c.php php_packageoption_a.h php_packageoption_b.h php_packageoption_c.h diff --git a/Examples/test-suite/php5/abstract_inherit_ok_runme.php b/Examples/test-suite/php5/abstract_inherit_ok_runme.php new file mode 100644 index 000000000..c2d86499b --- /dev/null +++ b/Examples/test-suite/php5/abstract_inherit_ok_runme.php @@ -0,0 +1,12 @@ +blah(),"spam object method"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/abstract_inherit_runme.php b/Examples/test-suite/php5/abstract_inherit_runme.php new file mode 100644 index 000000000..3554e6fd8 --- /dev/null +++ b/Examples/test-suite/php5/abstract_inherit_runme.php @@ -0,0 +1,14 @@ +blah(),"spam object method"); +//check::equal(0,Spam::blah($spam),"spam class method"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/add_link_runme.php b/Examples/test-suite/php5/add_link_runme.php new file mode 100644 index 000000000..7523bd604 --- /dev/null +++ b/Examples/test-suite/php5/add_link_runme.php @@ -0,0 +1,22 @@ +blah(); +check::is_a($foo_blah,foo); + +//fails, can't be called as a class method, should allow and make it nil? +//$class_foo_blah=foo::blah(); +//check::is_a($class_foo_blah,foo); + +check::done(); +?> diff --git a/Examples/test-suite/php5/argout_runme.php b/Examples/test-suite/php5/argout_runme.php new file mode 100644 index 000000000..33fbd8129 --- /dev/null +++ b/Examples/test-suite/php5/argout_runme.php @@ -0,0 +1,38 @@ + diff --git a/Examples/test-suite/php5/arrayptr_runme.php b/Examples/test-suite/php5/arrayptr_runme.php new file mode 100644 index 000000000..3b9baed05 --- /dev/null +++ b/Examples/test-suite/php5/arrayptr_runme.php @@ -0,0 +1,14 @@ + diff --git a/Examples/test-suite/php5/arrays_global_runme.php b/Examples/test-suite/php5/arrays_global_runme.php new file mode 100644 index 000000000..12a7806c9 --- /dev/null +++ b/Examples/test-suite/php5/arrays_global_runme.php @@ -0,0 +1,19 @@ + diff --git a/Examples/test-suite/php5/arrays_global_twodim_runme.php b/Examples/test-suite/php5/arrays_global_twodim_runme.php new file mode 100644 index 000000000..40ecf1719 --- /dev/null +++ b/Examples/test-suite/php5/arrays_global_twodim_runme.php @@ -0,0 +1,22 @@ + diff --git a/Examples/test-suite/php5/arrays_runme.php b/Examples/test-suite/php5/arrays_runme.php new file mode 100644 index 000000000..ae17d05e7 --- /dev/null +++ b/Examples/test-suite/php5/arrays_runme.php @@ -0,0 +1,18 @@ +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/php5/arrays_scope_runme.php b/Examples/test-suite/php5/arrays_scope_runme.php new file mode 100644 index 000000000..c208b7518 --- /dev/null +++ b/Examples/test-suite/php5/arrays_scope_runme.php @@ -0,0 +1,16 @@ + diff --git a/Examples/test-suite/php5/callback_runme.php b/Examples/test-suite/php5/callback_runme.php new file mode 100644 index 000000000..fefa32502 --- /dev/null +++ b/Examples/test-suite/php5/callback_runme.php @@ -0,0 +1,9 @@ + diff --git a/Examples/test-suite/php5/casts_runme.php b/Examples/test-suite/php5/casts_runme.php new file mode 100644 index 000000000..10522dca4 --- /dev/null +++ b/Examples/test-suite/php5/casts_runme.php @@ -0,0 +1,18 @@ +hello(); + +check::done(); +?> diff --git a/Examples/test-suite/php5/char_strings_runme.php b/Examples/test-suite/php5/char_strings_runme.php new file mode 100644 index 000000000..e06ee9d2b --- /dev/null +++ b/Examples/test-suite/php5/char_strings_runme.php @@ -0,0 +1,43 @@ + diff --git a/Examples/test-suite/php5/class_ignore_runme.php b/Examples/test-suite/php5/class_ignore_runme.php new file mode 100644 index 000000000..d5ce36217 --- /dev/null +++ b/Examples/test-suite/php5/class_ignore_runme.php @@ -0,0 +1,16 @@ + diff --git a/Examples/test-suite/php5/conversion_namespace_runme.php b/Examples/test-suite/php5/conversion_namespace_runme.php new file mode 100644 index 000000000..e21ff7438 --- /dev/null +++ b/Examples/test-suite/php5/conversion_namespace_runme.php @@ -0,0 +1,13 @@ +toFoo(); +check::classname("foo",$foo); + +check::done(); +?> diff --git a/Examples/test-suite/php5/conversion_ns_template_runme.php b/Examples/test-suite/php5/conversion_ns_template_runme.php new file mode 100644 index 000000000..9702eedb7 --- /dev/null +++ b/Examples/test-suite/php5/conversion_ns_template_runme.php @@ -0,0 +1,10 @@ + diff --git a/Examples/test-suite/php5/conversion_runme.php b/Examples/test-suite/php5/conversion_runme.php new file mode 100644 index 000000000..1a10ff4f4 --- /dev/null +++ b/Examples/test-suite/php5/conversion_runme.php @@ -0,0 +1,13 @@ +toFoo(); +check::classname("foo",$foo); + +check::done(); +?> diff --git a/Examples/test-suite/php5/cpp11_strongly_typed_enumerations_runme.php b/Examples/test-suite/php5/cpp11_strongly_typed_enumerations_runme.php new file mode 100644 index 000000000..bee59b209 --- /dev/null +++ b/Examples/test-suite/php5/cpp11_strongly_typed_enumerations_runme.php @@ -0,0 +1,169 @@ +class1Test1(Enum1_Val5a), 13); +enumCheck($class1->class1Test2(Class1::Enum12_Val5c), 1121); +#enumCheck($class1.class1Test3(Class1::Struct1.Enum12_Val5f), 3121); + +enumCheck(globalTest1(Enum1_Val5a), 13); +enumCheck(globalTest2(Class1::Enum12_Val5c), 1121); +#enumCheck(globalTest3(Class1::Struct1.Enum12_Val5f), 3121); + +?> diff --git a/Examples/test-suite/php5/cpp_basic_runme.php b/Examples/test-suite/php5/cpp_basic_runme.php new file mode 100644 index 000000000..6a8522e3e --- /dev/null +++ b/Examples/test-suite/php5/cpp_basic_runme.php @@ -0,0 +1,20 @@ +func_ptr = get_func1_ptr(); +check::equal(test_func_ptr($f, 7), 2*7*3, "get_func1_ptr() didn't work"); +$f->func_ptr = get_func2_ptr(); +check::equal(test_func_ptr($f, 7), -7*3, "get_func2_ptr() didn't work"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/cpp_static_runme.php b/Examples/test-suite/php5/cpp_static_runme.php new file mode 100644 index 000000000..9b436b87c --- /dev/null +++ b/Examples/test-suite/php5/cpp_static_runme.php @@ -0,0 +1,14 @@ + diff --git a/Examples/test-suite/php5/director_abstract_runme.php b/Examples/test-suite/php5/director_abstract_runme.php new file mode 100644 index 000000000..ca3d676da --- /dev/null +++ b/Examples/test-suite/php5/director_abstract_runme.php @@ -0,0 +1,62 @@ +ping(), "MyFoo::ping()", "MyFoo::ping failed"); + +check::equal($a->pong(), "Foo::pong();MyFoo::ping()", "MyFoo::pong failed"); + +class MyExample1 extends Example1 { + function Color($r, $g, $b) { + return $r; + } +} + +class MyExample2 extends Example1 { + function Color($r, $g, $b) { + return $g; + } +} + +class MyExample3 extends Example1 { + function Color($r, $g, $b) { + return $b; + } +} + +$me1 = new MyExample1(); +check::equal($me1->Color(1, 2, 3), 1, "Example1_get_color failed"); + +$me2 = new MyExample2(1, 2); +check::equal($me2->Color(1, 2, 3), 2, "Example2_get_color failed"); + +$me3 = new MyExample3(); +check::equal($me3->Color(1, 2, 3), 3, "Example3_get_color failed"); + +$class = new ReflectionClass('Example1'); +check::equal($class->isAbstract(), true, "Example1 abstractness failed"); + +$class = new ReflectionClass('Example2'); +check::equal($class->isAbstract(), true, "Example2 abstractness failed"); + +$class = new ReflectionClass('Example3_i'); +check::equal($class->isAbstract(), true, "Example3_i abstractness failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_basic_runme.php b/Examples/test-suite/php5/director_basic_runme.php new file mode 100644 index 000000000..de6b50502 --- /dev/null +++ b/Examples/test-suite/php5/director_basic_runme.php @@ -0,0 +1,58 @@ +ping(), "PhpFoo::ping()", "ping failed"); + +check::equal($a->pong(), "Foo::pong();PhpFoo::ping()", "pong failed"); + +$b = new Foo(); + +check::equal($b->ping(), "Foo::ping()", "ping failed"); + +check::equal($b->pong(), "Foo::pong();Foo::ping()", "pong failed"); + +$a = new A1(1); + +check::equal($a->rg(2), 2, "rg failed"); + +class PhpClass extends MyClass { + function vmethod($b) { + $b->x = $b->x + 31; + return $b; + } +} + +$b = new Bar(3); +$d = new MyClass(); +$c = new PhpClass(); + +$cc = MyClass::get_self($c); +$dd = MyClass::get_self($d); + +$bc = $cc->cmethod($b); +$bd = $dd->cmethod($b); + +$cc->method($b); + +check::equal($bc->x, 34, "bc failed"); +check::equal($bd->x, 16, "bd failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_classic_runme.php b/Examples/test-suite/php5/director_classic_runme.php new file mode 100644 index 000000000..d2da1b1ba --- /dev/null +++ b/Examples/test-suite/php5/director_classic_runme.php @@ -0,0 +1,150 @@ +id(); + if ($debug) + print $ret . "\n"; + check::equal($ret, $expected, "#1 failed"); + + # Polymorphic call from C++ + $caller = new Caller(); + $caller->setCallback($person); + $ret = $caller->call(); + if ($debug) + print $ret . "\n"; + check::equal($ret, $expected, "#2 failed"); + + # Polymorphic call of object created in target language and passed to + # C++ and back again + $baseclass = $caller->baseClass(); + $ret = $baseclass->id(); + if ($debug) + print $ret . "\n"; + # TODO: Currently we do not track the dynamic type of returned + # objects, so in case it's possible that the dynamic type is not equal + # to the static type, we skip this check. + if (get_parent_class($person) === false) + check::equal($ret, $expected, "#3 failed"); + + $caller->resetCallback(); + if ($debug) + print "----------------------------------------\n"; +} + +$person = new Person(); +mycheck($person, "Person"); +unset($person); + +$person = new Child(); +mycheck($person, "Child"); +unset($person); + +$person = new GrandChild(); +mycheck($person, "GrandChild"); +unset($person); + +$person = new TargetLangPerson(); +mycheck($person, "TargetLangPerson"); +unset($person); + +$person = new TargetLangChild(); +mycheck($person, "TargetLangChild"); +unset($person); + +$person = new TargetLangGrandChild(); +mycheck($person, "TargetLangGrandChild"); +unset($person); + +# Semis - don't override id() in target language +$person = new TargetLangSemiPerson(); +mycheck($person, "Person"); +unset($person); + +$person = new TargetLangSemiChild(); +mycheck($person, "Child"); +unset($person); + +$person = new TargetLangSemiGrandChild(); +mycheck($person, "GrandChild"); +unset($person); + +# Orphans - don't override id() in C++ +$person = new OrphanPerson(); +mycheck($person, "Person"); +unset($person); + +$person = new OrphanChild(); +mycheck($person, "Child"); +unset($person); + +$person = new TargetLangOrphanPerson(); +mycheck($person, "TargetLangOrphanPerson"); +unset($person); + +$person = new TargetLangOrphanChild(); +mycheck($person, "TargetLangOrphanChild"); +unset($person); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_default_runme.php b/Examples/test-suite/php5/director_default_runme.php new file mode 100644 index 000000000..f97fc7425 --- /dev/null +++ b/Examples/test-suite/php5/director_default_runme.php @@ -0,0 +1,20 @@ + diff --git a/Examples/test-suite/php5/director_detect_runme.php b/Examples/test-suite/php5/director_detect_runme.php new file mode 100644 index 000000000..cc19c0302 --- /dev/null +++ b/Examples/test-suite/php5/director_detect_runme.php @@ -0,0 +1,55 @@ +val = $val; + } + + function get_value() { + $this->val = $this->val + 1; + return $this->val; + } + + function get_class() { + $this->val = $this->val + 1; + return new A(); + } + + function just_do_it() { + $this->val = $this->val + 1; + } + + /* clone is a reserved keyword */ + function clone_() { + return new MyBar($this->val); + } +} + +$b = new MyBar(); + +$f = $b->baseclass(); + +$v = $f->get_value(); +$a = $f->get_class(); +$f->just_do_it(); + +$c = $b->clone_(); +$vc = $c->get_value(); + +check::equal($v, 3, "f: Bad virtual detection"); +check::equal($b->val, 5, "b: Bad virtual detection"); +check::equal($vc, 6, "c: Bad virtual detection"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_enum_runme.php b/Examples/test-suite/php5/director_enum_runme.php new file mode 100644 index 000000000..8f6487a28 --- /dev/null +++ b/Examples/test-suite/php5/director_enum_runme.php @@ -0,0 +1,25 @@ +say_hi(director_enum::hello), $b->say_hello(director_enum::hi), "say failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_exception_runme.php b/Examples/test-suite/php5/director_exception_runme.php new file mode 100644 index 000000000..8b852c2ce --- /dev/null +++ b/Examples/test-suite/php5/director_exception_runme.php @@ -0,0 +1,127 @@ +msg = $a . $b; + } +} + +class MyFoo extends Foo { + function ping() { + throw new Exception("MyFoo::ping() EXCEPTION"); + } +} + +class MyFoo2 extends Foo { + function ping() { + return true; + } +} + +class MyFoo3 extends Foo { + function ping() { + throw new MyException("foo", "bar"); + } +} + +# Check that the Exception raised by MyFoo.ping() is returned by +# MyFoo.pong(). +$ok = 0; +$a = new MyFoo(); +# TODO: Currently we do not track the dynamic type of returned +# objects, so we skip the launder() call. +#$b = director_exception::launder($a); +$b = $a; +try { + $b->pong(); +} catch (Exception $e) { + $ok = 1; + check::equal($e->getMessage(), "MyFoo::ping() EXCEPTION", "Unexpected error message #1"); +} +check::equal($ok, 1, "Got no exception while expected one #1"); + +# Check that the director can return an exception which requires two +# arguments to the constructor, without mangling it. +$ok = 0; +$a = new MyFoo3(); +#$b = director_exception::launder($a); +$b = $a; +try { + $b->pong(); +} catch (Exception $e) { + $ok = 1; + check::equal($e->msg, "foobar", "Unexpected error message #2"); +} +check::equal($ok, 1, "Got no exception while expected one #2"); + +try { + throw new Exception2(); +} catch (Exception2 $e2) { +} + +try { + throw new Exception1(); +} catch (Exception1 $e1) { +} + +// Check that we can throw exceptions from director methods (this didn't used +// to work in all cases, as the exception gets "set" in PHP and the method +// then returns PHP NULL, which the directorout template may fail to convert. + +class Bad extends ReturnAllTypes { + function return_int() { throw new Exception("bad int"); } + function return_double() { throw new Exception("bad double"); } + function return_const_char_star() { throw new Exception("bad const_char_star"); } + function return_std_string() { throw new Exception("bad std_string"); } + function return_Bar() { throw new Exception("bad Bar"); } +} + +$bad = new Bad(); + +try { + $bad->call_int(); + check::fail("Exception wasn't propagated from Bad::return_int()"); +} catch (Exception $e) { + check::equal($e->getMessage(), "bad int", "propagated exception incorrect"); +} + +try { + $bad->call_double(); + check::fail("Exception wasn't propagated from Bad::return_double()"); +} catch (Exception $e) { + check::equal($e->getMessage(), "bad double", "propagated exception incorrect"); +} + +try { + $bad->call_const_char_star(); + check::fail("Exception wasn't propagated from Bad::return_const_char_star()"); +} catch (Exception $e) { + check::equal($e->getMessage(), "bad const_char_star", "propagated exception incorrect"); +} + +try { + $bad->call_std_string(); + check::fail("Exception wasn't propagated from Bad::return_std_string()"); +} catch (Exception $e) { + check::equal($e->getMessage(), "bad std_string", "propagated exception incorrect"); +} + +try { + $bad->call_Bar(); + check::fail("Exception wasn't propagated from Bad::return_Bar()"); +} catch (Exception $e) { + check::equal($e->getMessage(), "bad Bar", "propagated exception incorrect"); +} + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_extend_runme.php b/Examples/test-suite/php5/director_extend_runme.php new file mode 100644 index 000000000..f283aefbe --- /dev/null +++ b/Examples/test-suite/php5/director_extend_runme.php @@ -0,0 +1,24 @@ +dummy(), 666, "1st call"); +check::equal($m->dummy(), 666, "2st call"); // Locked system + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_finalizer_runme.php b/Examples/test-suite/php5/director_finalizer_runme.php new file mode 100644 index 000000000..0fcddfd8b --- /dev/null +++ b/Examples/test-suite/php5/director_finalizer_runme.php @@ -0,0 +1,61 @@ +orStatus(2); + if (method_exists(parent, "__destruct")) { + parent::__destruct(); + } + } +} + +resetStatus(); + +$a = new MyFoo(); +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #1"); + +resetStatus(); + +$a = new MyFoo(); +launder($a); + +check::equal(getStatus(), 0, "getStatus() failed #2"); + +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #3"); + +resetStatus(); + +$a = new MyFoo(); +$a->thisown = 0; +deleteFoo($a); +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #4"); + +resetStatus(); + +$a = new MyFoo(); +$a->thisown = 0; +deleteFoo(launder($a)); +unset($a); + +check::equal(getStatus(), 3, "getStatus() failed #5"); + +resetStatus(); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_frob_runme.php b/Examples/test-suite/php5/director_frob_runme.php new file mode 100644 index 000000000..548b0b804 --- /dev/null +++ b/Examples/test-suite/php5/director_frob_runme.php @@ -0,0 +1,19 @@ +abs_method(); + +check::equal($s, "Bravo::abs_method()", "s failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_nested_runme.php b/Examples/test-suite/php5/director_nested_runme.php new file mode 100644 index 000000000..4965e94f7 --- /dev/null +++ b/Examples/test-suite/php5/director_nested_runme.php @@ -0,0 +1,74 @@ +step(), "Bar::step;Foo::advance;Bar::do_advance;A::do_step;", "Bad A virtual resolution"); + +class B extends FooBar_int { + function do_advance() { + return "B::do_advance;" . $this->do_step(); + } + + function do_step() { + return "B::do_step;"; + } + + function get_value() { + return 1; + } +} + +$b = new B(); + +check::equal($b->step(), "Bar::step;Foo::advance;B::do_advance;B::do_step;", "Bad B virtual resolution"); + +class C extends FooBar_int { + function do_advance() { + return "C::do_advance;" . parent::do_advance(); + } + + function do_step() { + return "C::do_step;"; + } + + function get_value() { + return 2; + } + + function get_name() { + return parent::get_name() . " hello"; + } +} + +$cc = new C(); +# TODO: Currently we do not track the dynamic type of returned +# objects, so we skip the get_self() call. +#$c = Foobar_int::get_self($cc); +$c = $cc; +$c->advance(); + +check::equal($c->get_name(), "FooBar::get_name hello", "get_name failed"); + +check::equal($c->name(), "FooBar::get_name hello", "name failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_pass_by_value_runme.php b/Examples/test-suite/php5/director_pass_by_value_runme.php new file mode 100644 index 000000000..8a8b84d67 --- /dev/null +++ b/Examples/test-suite/php5/director_pass_by_value_runme.php @@ -0,0 +1,24 @@ +call_virtualMethod(new director_pass_by_value_Derived()); +$ret = $passByVal->getVal(); +if ($ret != 0x12345678) { + check::fail("Bad return value, got " . dechex($ret)); +} + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_profile_runme.php b/Examples/test-suite/php5/director_profile_runme.php new file mode 100644 index 000000000..c72421341 --- /dev/null +++ b/Examples/test-suite/php5/director_profile_runme.php @@ -0,0 +1,53 @@ +fi($a); #1 + $a = $b->fi($a); #2 + $a = $b->fi($a); #3 + $a = $b->fi($a); #4 + $a = $b->fi($a); #5 + $a = $b->fi($a); #6 + $a = $b->fi($a); #7 + $a = $b->fi($a); #8 + $a = $b->fi($a); #9 + $a = $b->fi($a); #10 + $a = $b->fi($a); #1 + $a = $b->fi($a); #2 + $a = $b->fi($a); #3 + $a = $b->fi($a); #4 + $a = $b->fi($a); #5 + $a = $b->fi($a); #6 + $a = $b->fi($a); #7 + $a = $b->fi($a); #8 + $a = $b->fi($a); #9 + $a = $b->fi($a); #20 + $i -= 1; +} + +print $a . "\n"; + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_protected_runme.php b/Examples/test-suite/php5/director_protected_runme.php new file mode 100644 index 000000000..18586ca62 --- /dev/null +++ b/Examples/test-suite/php5/director_protected_runme.php @@ -0,0 +1,70 @@ +create(); +$fb = new FooBar(); +$fb2 = new FooBar2(); +$fb3 = new FooBar3(); + +check::equal($fb->used(), "Foo::pang();Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::used"); + +check::equal($fb2->used(), "FooBar2::pang();Bar::pong();Foo::pong();FooBar2::ping();", "bad FooBar2::used"); + +check::equal($b->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Bar::pong"); + +check::equal($f->pong(), "Bar::pong();Foo::pong();Bar::ping();", "bad Foo::pong"); + +check::equal($fb->pong(), "Bar::pong();Foo::pong();FooBar::ping();", "bad FooBar::pong"); + +$method = new ReflectionMethod('Bar', 'ping'); +check::equal($method->isProtected(), true, "Foo::ping should be protected"); + +$method = new ReflectionMethod('Foo', 'ping'); +check::equal($method->isProtected(), true, "Foo::ping should be protected"); + +$method = new ReflectionMethod('FooBar', 'pang'); +check::equal($method->isProtected(), true, "FooBar::pang should be protected"); + +$method = new ReflectionMethod('Bar', 'cheer'); +check::equal($method->isProtected(), true, "Bar::cheer should be protected"); + +$method = new ReflectionMethod('Foo', 'cheer'); +check::equal($method->isProtected(), true, "Foo::cheer should be protected"); + +check::equal($fb3->cheer(), "FooBar3::cheer();", "bad fb3::pong"); +check::equal($fb2->callping(), "FooBar2::ping();", "bad fb2::callping"); +check::equal($fb2->callcheer(), "FooBar2::pang();Bar::pong();Foo::pong();FooBar2::ping();", "bad fb2::callcheer"); +check::equal($fb3->callping(), "Bar::ping();", "bad fb3::callping"); +check::equal($fb3->callcheer(), "FooBar3::cheer();", "bad fb3::callcheer"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_stl_runme.php b/Examples/test-suite/php5/director_stl_runme.php new file mode 100644 index 000000000..29addd261 --- /dev/null +++ b/Examples/test-suite/php5/director_stl_runme.php @@ -0,0 +1,60 @@ +tping("hello"); +$a->tpong("hello"); + +# TODO: automatic conversion between PHP arrays and std::pair or +# std::vector is not yet implemented. +/*$p = array(1, 2); +$a->pident($p); +$v = array(3, 4); +$a->vident($v); + +$a->tpident($p); +$a->tvident($v); + +$v1 = array(3, 4); +$v2 = array(5, 6); + +$a->tvsecond($v1, $v2); + +$vs = array("hi", "hello"); +$vs; +$a->tvidents($vs);*/ + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_string_runme.php b/Examples/test-suite/php5/director_string_runme.php new file mode 100644 index 000000000..5ac583f78 --- /dev/null +++ b/Examples/test-suite/php5/director_string_runme.php @@ -0,0 +1,34 @@ +smem = "hello"; + } +} + +$b = new B("hello"); + +$b->get(0); +check::equal($b->get_first(),"hello world!", "get_first failed"); + +$b->call_process_func(); + +check::equal($b->smem, "hello", "smem failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_thread_runme.php b/Examples/test-suite/php5/director_thread_runme.php new file mode 100644 index 000000000..809dec3e2 --- /dev/null +++ b/Examples/test-suite/php5/director_thread_runme.php @@ -0,0 +1,32 @@ +val = $this->val - 1; + } +} + +$d = new Derived(); +$d->run(); + +if ($d->val >= 0) { + check::fail($d->val); +} + +$d->stop(); + +check::done(); +?> diff --git a/Examples/test-suite/php5/director_unroll_runme.php b/Examples/test-suite/php5/director_unroll_runme.php new file mode 100644 index 000000000..626b1f07d --- /dev/null +++ b/Examples/test-suite/php5/director_unroll_runme.php @@ -0,0 +1,29 @@ +set($a); +$c = $b->get(); + +check::equal($a->this, $c->this, "this failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/enum_scope_template_runme.php b/Examples/test-suite/php5/enum_scope_template_runme.php new file mode 100644 index 000000000..85ba467b7 --- /dev/null +++ b/Examples/test-suite/php5/enum_scope_template_runme.php @@ -0,0 +1,15 @@ + diff --git a/Examples/test-suite/php5/evil_diamond_ns_runme.php b/Examples/test-suite/php5/evil_diamond_ns_runme.php new file mode 100644 index 000000000..fcce0f767 --- /dev/null +++ b/Examples/test-suite/php5/evil_diamond_ns_runme.php @@ -0,0 +1,18 @@ + diff --git a/Examples/test-suite/php5/evil_diamond_prop_runme.php b/Examples/test-suite/php5/evil_diamond_prop_runme.php new file mode 100644 index 000000000..02d9944d6 --- /dev/null +++ b/Examples/test-suite/php5/evil_diamond_prop_runme.php @@ -0,0 +1,38 @@ +_foo,"1==foo->_foo"); + +$bar=new bar(); +check::is_a($bar,"bar"); +check::equal(1,$bar->_foo,"1==bar->_foo"); +check::equal(2,$bar->_bar,"2==bar->_bar"); + +$baz=new baz(); +check::is_a($baz,"baz"); +check::equal(1,$baz->_foo,"1==baz->_foo"); +check::equal(3,$baz->_baz,"3==baz->_baz"); + +$spam=new spam(); +check::is_a($spam,"spam"); +check::equal(1,$spam->_foo,"1==spam->_foo"); +check::equal(2,$spam->_bar,"2==spam->_bar"); +// multiple inheritance not supported in PHP +check::equal(null,$spam->_baz,"null==spam->_baz"); +check::equal(4,$spam->_spam,"4==spam->_spam"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/evil_diamond_runme.php b/Examples/test-suite/php5/evil_diamond_runme.php new file mode 100644 index 000000000..a587ca359 --- /dev/null +++ b/Examples/test-suite/php5/evil_diamond_runme.php @@ -0,0 +1,16 @@ + diff --git a/Examples/test-suite/php5/exception_order_runme.php b/Examples/test-suite/php5/exception_order_runme.php new file mode 100644 index 000000000..acb83561a --- /dev/null +++ b/Examples/test-suite/php5/exception_order_runme.php @@ -0,0 +1,39 @@ +foo(); +} catch (Exception $e) { + check::equal($e->getMessage(), 'C++ E1 exception thrown', ''); +} + +try { + $a->bar(); +} catch (Exception $e) { + check::equal($e->getMessage(), 'C++ E2 exception thrown', ''); +} + +try { + $a->foobar(); +} catch (Exception $e) { + check::equal($e->getMessage(), 'postcatch unknown', ''); +} + +try { + $a->barfoo(1); +} catch (Exception $e) { + check::equal($e->getMessage(), 'C++ E1 exception thrown', ''); +} + +try { + $a->barfoo(2); +} catch (Exception $e) { + check::equal($e->getMessage(), 'C++ E2 * exception thrown', ''); +} +?> diff --git a/Examples/test-suite/php5/extend_template_ns_runme.php b/Examples/test-suite/php5/extend_template_ns_runme.php new file mode 100644 index 000000000..e6d3e9f73 --- /dev/null +++ b/Examples/test-suite/php5/extend_template_ns_runme.php @@ -0,0 +1,12 @@ +test1(2),"test1"); +check::equal(3,$foo->test2(3),"test2"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/extend_template_runme.php b/Examples/test-suite/php5/extend_template_runme.php new file mode 100644 index 000000000..41bde4458 --- /dev/null +++ b/Examples/test-suite/php5/extend_template_runme.php @@ -0,0 +1,12 @@ +test1(2),"test1"); +check::equal(3,$foo->test2(3),"test2"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/grouping_runme.php b/Examples/test-suite/php5/grouping_runme.php new file mode 100644 index 000000000..51446f473 --- /dev/null +++ b/Examples/test-suite/php5/grouping_runme.php @@ -0,0 +1,22 @@ + diff --git a/Examples/test-suite/php5/ignore_parameter_runme.php b/Examples/test-suite/php5/ignore_parameter_runme.php new file mode 100644 index 000000000..1c8c76ad4 --- /dev/null +++ b/Examples/test-suite/php5/ignore_parameter_runme.php @@ -0,0 +1,38 @@ +daimler(2,3.4),"hello",'$sc->daimler(2,3.4)=="hello"'); +check::equal($sc->astonmartin("eek",3.4),101,'$sc->mastonmartin("eek",3.4)==101'); +check::equal($sc->bugatti("eek",2),8.8,'$sc->bugatti("eek",2)==8.8'); +check::equal($sc->lamborghini(),101,'$sc->lamborghini(2)==101'); + +$mc=new minicooper(2,3.4); +check::classname("minicooper",$mc); + +$mm=new morrisminor("eek",3.4); +check::classname("morrisminor",$mm); + +$fa=new fordanglia("eek",2); +check::classname("fordanglia",$fa); + +$aa=new austinallegro(); +check::classname("austinallegro",$aa); + +check::done(); +?> diff --git a/Examples/test-suite/php5/import_nomodule_runme.php b/Examples/test-suite/php5/import_nomodule_runme.php new file mode 100644 index 000000000..41836ba0f --- /dev/null +++ b/Examples/test-suite/php5/import_nomodule_runme.php @@ -0,0 +1,20 @@ + diff --git a/Examples/test-suite/php5/li_carrays_cpp_runme.php b/Examples/test-suite/php5/li_carrays_cpp_runme.php new file mode 100644 index 000000000..3be09ca8c --- /dev/null +++ b/Examples/test-suite/php5/li_carrays_cpp_runme.php @@ -0,0 +1,22 @@ +setitem(0, 7); +$d->setitem(5, $d->getitem(0) + 3); +check::equal($d->getitem(0) + $d->getitem(5), 17., "7+10==17"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/li_carrays_runme.php b/Examples/test-suite/php5/li_carrays_runme.php new file mode 100644 index 000000000..fbe5cc793 --- /dev/null +++ b/Examples/test-suite/php5/li_carrays_runme.php @@ -0,0 +1,22 @@ +setitem(0, 7); +$d->setitem(5, $d->getitem(0) + 3); +check::equal($d->getitem(0) + $d->getitem(5), 17., "7+10==17"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/li_factory_runme.php b/Examples/test-suite/php5/li_factory_runme.php new file mode 100644 index 000000000..6623e2a8c --- /dev/null +++ b/Examples/test-suite/php5/li_factory_runme.php @@ -0,0 +1,22 @@ +radius(); +check::equal($r, 1.5, "r failed"); + +$point = Geometry::create(Geometry::POINT); +$w = $point->width(); +check::equal($w, 1.0, "w failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/li_std_string_runme.php b/Examples/test-suite/php5/li_std_string_runme.php new file mode 100644 index 000000000..ad62247e1 --- /dev/null +++ b/Examples/test-suite/php5/li_std_string_runme.php @@ -0,0 +1,31 @@ +MemberString2, "member string 2", "MemberString2 test 1"); +$myStructure->MemberString2 = $s; +check::equal($myStructure->MemberString2, $s, "MemberString2 test 2"); +check::equal($myStructure->ConstMemberString, "const member string", "ConstMemberString test"); + +check::equal(Structure::StaticMemberString2(), "static member string 2", "StaticMemberString2 test 1"); +Structure::StaticMemberString2($s); +check::equal(Structure::StaticMemberString2(), $s, "StaticMemberString2 test 2"); +// below broken ? +//check::equal(Structure::ConstStaticMemberString(), "const static member string", "ConstStaticMemberString test"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/li_std_vector_member_var_runme.php b/Examples/test-suite/php5/li_std_vector_member_var_runme.php new file mode 100644 index 000000000..238350352 --- /dev/null +++ b/Examples/test-suite/php5/li_std_vector_member_var_runme.php @@ -0,0 +1,30 @@ +x, 0, "Test::x != 0"); +check::equal($t->v->size(), 0, "Test::v.size() != 0"); + +$t->f(1); +check::equal($t->x, 1, "Test::x != 1"); +check::equal($t->v->size(), 1, "Test::v.size() != 1"); + +$t->f(2); +check::equal($t->x, 3, "Test::x != 3"); +check::equal($t->v->size(), 2, "Test::v.size() != 2"); + +$t->f(3); +check::equal($t->x, 6, "Test::x != 6"); +check::equal($t->v->size(), 3, "Test::v.size() != 3"); + +$T = new T(); +$T->start_t = new S(); +$T->length = 7; +check::equal($T->start_t->x, 4, "S::x != 4"); +check::equal($T->length, 7, "T::length != 7"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/newobject1_runme.php b/Examples/test-suite/php5/newobject1_runme.php new file mode 100644 index 000000000..5853a72c0 --- /dev/null +++ b/Examples/test-suite/php5/newobject1_runme.php @@ -0,0 +1,19 @@ +makeMore(); +check::equal(get_class($bar), "Foo", "regular failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/overload_rename_runme.php b/Examples/test-suite/php5/overload_rename_runme.php new file mode 100644 index 000000000..dce4c6cb3 --- /dev/null +++ b/Examples/test-suite/php5/overload_rename_runme.php @@ -0,0 +1,19 @@ + diff --git a/Examples/test-suite/php5/overload_return_type_runme.php b/Examples/test-suite/php5/overload_return_type_runme.php new file mode 100644 index 000000000..4fa19d22a --- /dev/null +++ b/Examples/test-suite/php5/overload_return_type_runme.php @@ -0,0 +1,13 @@ +foo(1), 0, ""); +check::classname("A", $b->foo("test")); + +check::equal(overload_return_type::foo(), 1, "overload_return_type::foo() should be 1"); +check::equal(overload_return_type::bar(), 1, "overload_return_type::bar() should be 1"); + +?> diff --git a/Examples/test-suite/php5/php_iterator_runme.php b/Examples/test-suite/php5/php_iterator_runme.php new file mode 100644 index 000000000..d69a5b385 --- /dev/null +++ b/Examples/test-suite/php5/php_iterator_runme.php @@ -0,0 +1,24 @@ + $v) { + $s .= "($k=>$v)"; +} +check::equal($s, '(0=>2)(1=>3)(2=>4)', 'Simple iteration failed'); + +check::done(); +?> diff --git a/Examples/test-suite/php5/pointer_reference_runme.php b/Examples/test-suite/php5/pointer_reference_runme.php new file mode 100644 index 000000000..52946177e --- /dev/null +++ b/Examples/test-suite/php5/pointer_reference_runme.php @@ -0,0 +1,18 @@ +value, 10, "pointer_reference::get() failed"); + +$ss = new Struct(20); +pointer_reference::set($ss); +$i = Struct::instance(); +check::equal($i->value, 20, "pointer_reference::set() failed"); + +check::equal(pointer_reference::overloading(1), 111, "overload test 1 failed"); +check::equal(pointer_reference::overloading($ss), 222, "overload test 2 failed"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/prefix_runme.php b/Examples/test-suite/php5/prefix_runme.php new file mode 100644 index 000000000..ead064f5b --- /dev/null +++ b/Examples/test-suite/php5/prefix_runme.php @@ -0,0 +1,18 @@ +get_self(); + +check::done(); +?> diff --git a/Examples/test-suite/php5/primitive_ref_runme.php b/Examples/test-suite/php5/primitive_ref_runme.php new file mode 100644 index 000000000..263a28074 --- /dev/null +++ b/Examples/test-suite/php5/primitive_ref_runme.php @@ -0,0 +1,34 @@ + diff --git a/Examples/test-suite/php5/rename_scope_runme.php b/Examples/test-suite/php5/rename_scope_runme.php new file mode 100644 index 000000000..df620d796 --- /dev/null +++ b/Examples/test-suite/php5/rename_scope_runme.php @@ -0,0 +1,16 @@ + diff --git a/Examples/test-suite/php5/skel.php b/Examples/test-suite/php5/skel.php new file mode 100644 index 000000000..780a999ed --- /dev/null +++ b/Examples/test-suite/php5/skel.php @@ -0,0 +1,15 @@ + diff --git a/Examples/test-suite/php5/smart_pointer_rename_runme.php b/Examples/test-suite/php5/smart_pointer_rename_runme.php new file mode 100644 index 000000000..26692dde5 --- /dev/null +++ b/Examples/test-suite/php5/smart_pointer_rename_runme.php @@ -0,0 +1,27 @@ +ftest1(1),"foo->ftest1"); +check::equal(2,$foo->ftest2(1,2),"foo->ftest2"); + +# check bar's ftest1, ftest2, ftest +check::equal(1,$bar->ftest1(1),"bar->ftest1"); +check::equal(2,$bar->ftest2(1,2),"bar->ftest2"); +check::equal(3,$bar->test(),"bar->test"); + +# check deref returns foo +check::classname("foo",$bar->__deref__()); + +check::done(); +?> diff --git a/Examples/test-suite/php5/swig_exception_runme.php b/Examples/test-suite/php5/swig_exception_runme.php new file mode 100644 index 000000000..76641996e --- /dev/null +++ b/Examples/test-suite/php5/swig_exception_runme.php @@ -0,0 +1,33 @@ +throwException(); + check::fail("Exception wasn't thrown"); +} catch (Exception $e) { + if ($e->getMessage() != "OK") { + check::fail("Exception getMessage() should be \"OK\", actually \"".$e->getMessage()."\""); + } +} + +# ----- Delete everything ----- + +$c = NULL; +$s = NULL; +$e = NULL; + +if (Shape::nshapes() != 0) { + check::fail("Shape::nshapes() should be 0, actually ".Shape::nshapes()); +} + +?> diff --git a/Examples/test-suite/php5/sym_runme.php b/Examples/test-suite/php5/sym_runme.php new file mode 100644 index 000000000..483aaa980 --- /dev/null +++ b/Examples/test-suite/php5/sym_runme.php @@ -0,0 +1,22 @@ +hulahoops(),"flim-jam","flim()->hulahoops==flim-jam"); +check::equal($flim->jar(),"flim-jar","flim()->jar==flim-jar"); +check::equal($flam->jam(),"flam-jam","flam()->jam==flam-jam"); +check::equal($flam->jar(),"flam-jar","flam()->jar==flam-jar"); + +check::done(); +?> diff --git a/Examples/test-suite/php5/template_arg_typename_runme.php b/Examples/test-suite/php5/template_arg_typename_runme.php new file mode 100644 index 000000000..7d60285e3 --- /dev/null +++ b/Examples/test-suite/php5/template_arg_typename_runme.php @@ -0,0 +1,18 @@ + diff --git a/Examples/test-suite/php5/template_construct_runme.php b/Examples/test-suite/php5/template_construct_runme.php new file mode 100644 index 000000000..3a3986f7e --- /dev/null +++ b/Examples/test-suite/php5/template_construct_runme.php @@ -0,0 +1,11 @@ + diff --git a/Examples/test-suite/php5/tests.php b/Examples/test-suite/php5/tests.php new file mode 100644 index 000000000..d3fd66868 --- /dev/null +++ b/Examples/test-suite/php5/tests.php @@ -0,0 +1,237 @@ + diff --git a/Examples/test-suite/php5/threads_exception_runme.php b/Examples/test-suite/php5/threads_exception_runme.php new file mode 100644 index 000000000..9e4d04e10 --- /dev/null +++ b/Examples/test-suite/php5/threads_exception_runme.php @@ -0,0 +1,43 @@ +unknown(); +} catch (Exception $e) { + check::equal($e->getMessage(), 'C++ A * exception thrown', ''); +} + +try { + $t->simple(); +} catch (Exception $e) { + check::equal($e->getCode(), 37, ''); +} + +try { + $t->message(); +} catch (Exception $e) { + check::equal($e->getMessage(), 'I died.', ''); +} + +try { + $t->hosed(); +} catch (Exception $e) { + check::equal($e->getMessage(), 'C++ Exc exception thrown', ''); +} + +foreach (Array(1,2,3,4) as $i) { + try { + $t->multi($i); + } catch (Exception $e) { + } +} diff --git a/Examples/test-suite/php5/typedef_reference_runme.php b/Examples/test-suite/php5/typedef_reference_runme.php new file mode 100644 index 000000000..88a70f8d3 --- /dev/null +++ b/Examples/test-suite/php5/typedef_reference_runme.php @@ -0,0 +1,13 @@ + diff --git a/Examples/test-suite/php5/typemap_ns_using_runme.php b/Examples/test-suite/php5/typemap_ns_using_runme.php new file mode 100644 index 000000000..6a599f008 --- /dev/null +++ b/Examples/test-suite/php5/typemap_ns_using_runme.php @@ -0,0 +1,9 @@ + diff --git a/Examples/test-suite/php5/using1_runme.php b/Examples/test-suite/php5/using1_runme.php new file mode 100644 index 000000000..51841bc78 --- /dev/null +++ b/Examples/test-suite/php5/using1_runme.php @@ -0,0 +1,9 @@ + diff --git a/Examples/test-suite/php5/using2_runme.php b/Examples/test-suite/php5/using2_runme.php new file mode 100644 index 000000000..391a98f52 --- /dev/null +++ b/Examples/test-suite/php5/using2_runme.php @@ -0,0 +1,9 @@ + diff --git a/Examples/test-suite/php5/valuewrapper_base_runme.php b/Examples/test-suite/php5/valuewrapper_base_runme.php new file mode 100644 index 000000000..6a1abdbd2 --- /dev/null +++ b/Examples/test-suite/php5/valuewrapper_base_runme.php @@ -0,0 +1,13 @@ + diff --git a/Examples/test-suite/php5/virtual_vs_nonvirtual_base_runme.php b/Examples/test-suite/php5/virtual_vs_nonvirtual_base_runme.php new file mode 100644 index 000000000..0d4aa3d5f --- /dev/null +++ b/Examples/test-suite/php5/virtual_vs_nonvirtual_base_runme.php @@ -0,0 +1,11 @@ +getInner()->get(), $fail->getInner()->get(), "should both be 10"); + +?> diff --git a/Examples/test-suite/php5/wrapmacro_runme.php b/Examples/test-suite/php5/wrapmacro_runme.php new file mode 100644 index 000000000..f32da990e --- /dev/null +++ b/Examples/test-suite/php5/wrapmacro_runme.php @@ -0,0 +1,12 @@ + diff --git a/Lib/allkw.swg b/Lib/allkw.swg index 563190e19..b9413191f 100644 --- a/Lib/allkw.swg +++ b/Lib/allkw.swg @@ -24,6 +24,7 @@ %include %include %include +%include %include %include %include diff --git a/Lib/cdata.i b/Lib/cdata.i index b9b8e1887..730ecccfb 100644 --- a/Lib/cdata.i +++ b/Lib/cdata.i @@ -29,13 +29,20 @@ typedef struct SWIGCDATA { } %typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH); -#elif SWIGPHP +#elif SWIGPHP5 %typemap(out) SWIGCDATA { ZVAL_STRINGL($result, $1.data, $1.len, 1); } %typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH); +#elif SWIGPHP7 + +%typemap(out) SWIGCDATA { + ZVAL_STRINGL($result, $1.data, $1.len); +} +%typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH); + #elif SWIGJAVA %apply (char *STRING, int LENGTH) { (const void *indata, int inlen) } diff --git a/Lib/exception.i b/Lib/exception.i index c8509987b..da0d56cdd 100644 --- a/Lib/exception.i +++ b/Lib/exception.i @@ -12,13 +12,20 @@ %insert("runtime") "swigerrors.swg" -#ifdef SWIGPHP +#ifdef SWIGPHP5 %{ #include "zend_exceptions.h" #define SWIG_exception(code, msg) do { zend_throw_exception(NULL, (char*)msg, code TSRMLS_CC); goto thrown; } while (0) %} #endif +#ifdef SWIGPHP7 +%{ +#include "zend_exceptions.h" +#define SWIG_exception(code, msg) do { zend_throw_exception(NULL, (char*)msg, code); goto thrown; } while (0) +%} +#endif + #ifdef SWIGGUILE %{ SWIGINTERN void SWIG_exception_ (int code, const char *msg, diff --git a/Lib/php/const.i b/Lib/php/const.i index 061ba99a2..644fd2c78 100644 --- a/Lib/php/const.i +++ b/Lib/php/const.i @@ -33,18 +33,13 @@ SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] { - zval *z_var; zend_constant c; - size_t len = sizeof("$symname") - 1; - MAKE_STD_ZVAL(z_var); - SWIG_SetPointerZval(z_var, (void*)$value, $1_descriptor, 0); - c.value = *z_var; + SWIG_SetPointerZval(&c.value, (void*)$value, $1_descriptor, 0); zval_copy_ctor(&c.value); - c.name = zend_strndup("$symname", len); - c.name_len = len+1; - c.flags = CONST_CS | CONST_PERSISTENT; + c.name = zend_string_init("$symname", sizeof("$symname") - 1, 0); + c.flags = CONST_CS; c.module_number = module_number; - zend_register_constant( &c TSRMLS_CC ); + zend_register_constant(&c); } /* Handled as a global variable. */ diff --git a/Lib/php/director.swg b/Lib/php/director.swg index 638a1697d..ea0eba8ac 100644 --- a/Lib/php/director.swg +++ b/Lib/php/director.swg @@ -77,30 +77,30 @@ namespace Swig { class Director { protected: - zval *swig_self; + // "mutable" so we can get a non-const pointer to it in const methods. + mutable zval swig_self; typedef std::map swig_ownership_map; mutable swig_ownership_map swig_owner; -#ifdef ZTS - // Store the ZTS context so it's available when C++ calls back to PHP. - void *** swig_zts_ctx; -#endif public: - Director(zval *self TSRMLS_DC) : swig_self(self) { - TSRMLS_SET_CTX(swig_zts_ctx); + Director(zval *self) { + ZVAL_COPY_VALUE(&swig_self, self); } - static bool swig_is_overridden_method(char *cname, char *lc_fname TSRMLS_DC) { - zend_class_entry **ce; - zend_function *mptr; - - if (zend_lookup_class(cname, strlen(cname), &ce TSRMLS_CC) != SUCCESS) { - return false; + static bool swig_is_overridden_method(const char *cname, const char *lc_fname) { + bool result = false; + zend_string * cname_str = zend_string_init(cname, strlen(cname), 0); + zend_class_entry *ce = zend_lookup_class(cname_str); + if (ce) { + zval * mptr = zend_hash_str_find(&ce->function_table, lc_fname, strlen(lc_fname)); + if (mptr) { + // common.scope points to zend_class_entry for the declaring class, + // and there's only one of those per class, so we can just use a + // pointer compare here. + result = Z_FUNC_P(mptr)->common.scope != ce; + } } - if (zend_hash_find(&(*ce)->function_table, lc_fname, strlen(lc_fname) + 1, (void **) &mptr) != SUCCESS) { - return false; - } - // common.scope points to the declaring class - return strcmp(mptr->common.scope->name, cname); + zend_string_release(cname_str); + return result; } template @@ -116,8 +116,8 @@ namespace Swig { protected: std::string swig_msg; public: - DirectorException(int code, const char *hdr, const char *msg TSRMLS_DC) : swig_msg(hdr) { - if (msg[0]) { + DirectorException(int code, const char *hdr, const char *msg) : swig_msg(hdr) { + if (msg && msg[0]) { swig_msg += " "; swig_msg += msg; } @@ -132,20 +132,20 @@ namespace Swig { return swig_msg.c_str(); } - static void raise(int code, const char *hdr, const char *msg TSRMLS_DC) { - throw DirectorException(code, hdr, msg TSRMLS_CC); + static void raise(int code, const char *hdr, const char *msg) { + throw DirectorException(code, hdr, msg); } }; /* attempt to call a pure virtual method via a director method */ class DirectorPureVirtualException : public DirectorException { public: - DirectorPureVirtualException(const char *msg TSRMLS_DC) - : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg TSRMLS_CC) { + DirectorPureVirtualException(const char *msg) + : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg) { } - static void raise(const char *msg TSRMLS_DC) { - throw DirectorPureVirtualException(msg TSRMLS_CC); + static void raise(const char *msg) { + throw DirectorPureVirtualException(msg); } }; @@ -153,18 +153,18 @@ namespace Swig { class DirectorMethodException : public DirectorException { public: - DirectorMethodException(const char *msg TSRMLS_DC) - : DirectorException(E_ERROR, "SWIG director method error", msg TSRMLS_CC) { + DirectorMethodException() + : DirectorException(E_ERROR, "SWIG director method error", NULL) { } - static void raise(const char *msg TSRMLS_DC) { - throw DirectorMethodException(msg TSRMLS_CC); + DirectorMethodException(const char *msg) + : DirectorException(E_ERROR, "SWIG director method error", msg) { + } + + static void raise(const char *msg) { + throw DirectorMethodException(msg); } }; } -// DirectorMethodException() is documented to be callable with no parameters -// so use a macro to insert TSRMLS_CC so any ZTS context gets passed. -#define DirectorMethodException() DirectorMethodException("" TSRMLS_CC) - #endif diff --git a/Lib/php/globalvar.i b/Lib/php/globalvar.i index a3e99f510..a5fd779ab 100644 --- a/Lib/php/globalvar.i +++ b/Lib/php/globalvar.i @@ -6,27 +6,20 @@ %typemap(varinit) char * { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_STRING; - if($1) { - z_var->value.str.val = estrdup($1); - z_var->value.str.len = strlen($1); + zval z_var; + if ($1) { + ZVAL_STRING(&z_var, $1); } else { - z_var->value.str.val = 0; - z_var->value.str.len = 0; + ZVAL_STR(&z_var, ZSTR_EMPTY_ALLOC()); } - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) char [] { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_STRING; - z_var->value.str.val = estrdup($1); - z_var->value.str.len = strlen($1); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zval z_var; + ZVAL_STRING(&z_var, $1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) int, @@ -40,136 +33,98 @@ unsigned char, enum SWIGTYPE { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_LONG; - z_var->value.lval = (long)$1; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zval z_var; + ZVAL_LONG(&z_var, (long)$1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) bool { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_BOOL; - z_var->value.lval = ($1)?1:0; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); + zval z_var; + ZVAL_BOOL(&z_var, ($1)?1:0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) float, double { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_DOUBLE; - z_var->value.dval = $1; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, - sizeof(zval *), NULL); + zval z_var; + ZVAL_DOUBLE(&z_var, (double)$1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) char { - zval *z_var; - char c[2]; - MAKE_STD_ZVAL(z_var); - c[0] = $1; - c[1] = 0; - z_var->type = IS_STRING; - z_var->value.str.val = estrndup(c, 1); - z_var->value.str.len = 1; - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, - sizeof(zval *), NULL); + zval z_var; + char c = $1; + ZVAL_STRINGL(&z_var, &c, 1); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) SWIGTYPE *, SWIGTYPE [] { - zval *z_var; - MAKE_STD_ZVAL(z_var); - SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, - sizeof(zval *), NULL); + zval z_var; + SWIG_SetPointerZval(&z_var, (void*)$1, $1_descriptor, 0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) SWIGTYPE, SWIGTYPE &, SWIGTYPE && { - zval *z_var; - - MAKE_STD_ZVAL(z_var); - SWIG_SetPointerZval(z_var, (void*)&$1, $&1_descriptor, 0); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, - sizeof(zval *), NULL); + zval z_var; + SWIG_SetPointerZval(&z_var, (void*)&$1, $&1_descriptor, 0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit) char [ANY] { - zval *z_var; - MAKE_STD_ZVAL(z_var); - z_var->type = IS_STRING; - ZVAL_STRINGL(z_var,(char*)$1, $1_dim0, 1); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, sizeof(zval *), NULL); + zval z_var; + /* varinit char [ANY] */ + ZVAL_STRINGL(&z_var, $1, $1_dim0); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &z_var); } %typemap(varinit, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { + zval resource; void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - zval * resource; - MAKE_STD_ZVAL(resource); - ZEND_REGISTER_RESOURCE(resource, p, swig_member_ptr); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); + ZVAL_RES(&resource, zend_register_resource(p, swig_member_ptr)); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &resource); } %typemap(varin) int, unsigned int, short, unsigned short, long, unsigned long, signed char, unsigned char, enum SWIGTYPE { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_long_ex(z_var); - if ($1 != ($1_ltype)((*z_var)->value.lval)) { - $1 = Z_LVAL_PP(z_var); - } + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + $1 = zval_get_long(z_var); } %typemap(varin) bool { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_boolean_ex(z_var); - if ($1 != ($1_ltype)((*z_var)->value.lval)) { - $1 = Z_LVAL_PP(z_var); - } + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + convert_to_boolean(z_var); + $1 = (Z_TYPE_P(z_var) == IS_TRUE); } %typemap(varin) double,float { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_double_ex(z_var); - if ($1 != ($1_ltype)((*z_var)->value.dval)) { - $1 = Z_DVAL_PP(z_var); - } + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + $1 = zval_get_double(z_var); } %typemap(varin) char { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_string_ex(z_var); - if ($1 != *((*z_var)->value.str.val)) { - $1 = *((*z_var)->value.str.val); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + convert_to_string(z_var); + if ($1 != Z_STRVAL_P(z_var)[0]) { + $1 = Z_STRVAL_P(z_var)[0]; } } %typemap(varin) char * { - zval **z_var; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); char *s1; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - convert_to_string_ex(z_var); - s1 = Z_STRVAL_PP(z_var); + convert_to_string(z_var); + s1 = Z_STRVAL_P(z_var); if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { if (s1) $1 = estrdup(s1); @@ -181,11 +136,9 @@ %typemap(varin) SWIGTYPE [] { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); if($1) { - SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, $owner); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, $owner); } } @@ -194,8 +147,8 @@ zval **z_var; char *s1; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - s1 = Z_STRVAL_PP(z_var); + zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1, (void**)&z_var); + s1 = Z_STRVAL_P(z_var); if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { if (s1) strncpy($1, s1, $1_dim0); @@ -204,11 +157,11 @@ %typemap(varin) SWIGTYPE { - zval **z_var; + zval *z_var; $&1_ltype _temp; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if (SWIG_ConvertPtr(*z_var, (void**)&_temp, $&1_descriptor, 0) < 0) { + z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if (SWIG_ConvertPtr(z_var, (void**)&_temp, $&1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); } @@ -218,11 +171,11 @@ %typemap(varin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && { - zval **z_var; + zval *z_var; $1_ltype _temp; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if (SWIG_ConvertPtr(*z_var, (void **)&_temp, $1_descriptor, 0) < 0) { + z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if (SWIG_ConvertPtr(z_var, (void **)&_temp, $1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); } @@ -231,10 +184,8 @@ %typemap(varin, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - void * p = (void*)zend_fetch_resource(*z_var TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, swig_member_ptr); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + void * p = (void*)zend_fetch_resource_ex(z_var, SWIG_MEMBER_PTR, swig_member_ptr); memcpy(&$1, p, sizeof($1)); } @@ -248,114 +199,96 @@ unsigned char, enum SWIGTYPE { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != ($1_ltype)((*z_var)->value.lval)) { - (*z_var)->value.lval = (long)$1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if ($1 != ($1_ltype)Z_LVAL_P(z_var)) { + z_var->value.lval = (long)$1; } } //SAMFIX need to cast zval->type, what if zend-hash_find fails? etc? %typemap(varout) bool { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != ($1_ltype)((*z_var)->value.lval)) { - (*z_var)->value.lval = (long)$1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if ($1 != ($1_ltype)Z_LVAL_P(z_var)) { + z_var->value.lval = (long)$1; } } %typemap(varout) double, float { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != ($1_ltype)((*z_var)->value.dval)) { - (*z_var)->value.dval = (double)$1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + if ($1 != ($1_ltype)Z_DVAL_P(z_var)) { + z_var->value.dval = (double)$1; } } %typemap(varout) char { - zval **z_var; - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1 != *((*z_var)->value.str.val)) { - char c[2]; - efree((*z_var)->value.str.val); - c[0] = $1; - c[1] = 0; - (*z_var)->value.str.val = estrdup(c); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + char c = $1; + if ($1 != Z_STRVAL_P(z_val)[0]) { + ZVAL_STRING(z_var, &c); } } %typemap(varout) char * { - zval **z_var; - char *s1; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - s1 = Z_STRVAL_PP(z_var); - if((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { - if(s1) + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + const char *s1 = Z_STRVAL_P(z_var); + if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { + if (s1) efree(s1); - if($1) { - (*z_var)->value.str.val = estrdup($1); - (*z_var)->value.str.len = strlen($1) + 1; + if ($1) { + (z_var)->value.str.val = estrdup($1); + (z_var)->value.str.len = strlen($1) + 1; } else { - (*z_var)->value.str.val = 0; - (*z_var)->value.str.len = 0; + (z_var)->value.str.val = 0; + (z_var)->value.str.len = 0; } } } %typemap(varout) SWIGTYPE { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - SWIG_SetPointerZval(*z_var, (void*)&$1, $&1_descriptor, 0); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)&$1, $&1_descriptor, 0); } %typemap(varout) SWIGTYPE [] { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - if($1) - SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); + if($1) { + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); + } } %typemap(varout) char [ANY] { - zval **z_var; - char *s1; + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + const char *s1 = Z_STRVAL_P(z_var); deliberate error cos this code looks bogus to me - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - s1 = Z_STRVAL_PP(z_var); - if((s1 == NULL) || strcmp(s1, $1)) { - if($1) { - (*z_var)->value.str.val = estrdup($1); - (*z_var)->value.str.len = strlen($1) + 1; + if ((s1 == NULL) || strcmp(s1, $1)) { + if ($1) { + (z_var)->value.str.val = estrdup($1); + (z_var)->value.str.len = strlen($1) + 1; } else { - (*z_var)->value.str.val = 0; - (*z_var)->value.str.len = 0; + (z_var)->value.str.val = 0; + (z_var)->value.str.len = 0; } } } %typemap(varout) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && { - zval **z_var; - - zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); - SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); + zval *z_var = zend_hash_str_find(&EG(symbol_table), "$1", sizeof("$1") - 1); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); } %typemap(varout, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { + zval resource; void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - zval * resource; - MAKE_STD_ZVAL(resource); - ZEND_REGISTER_RESOURCE(resource, p, swig_member_ptr); - zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); + ZVAL_RES(&resource, zend_register_resource(p, swig_member_ptr)); + zend_hash_str_add(&EG(symbol_table), "$1", sizeof("$1") - 1, &resource); } diff --git a/Lib/php/php.swg b/Lib/php/php.swg index 535c7d347..c9b9a5217 100644 --- a/Lib/php/php.swg +++ b/Lib/php/php.swg @@ -71,72 +71,72 @@ // char array can be in/out, though the passed string may not be big enough... // so we have to size it %typemap(in) char[ANY] -{ - convert_to_string_ex($input); - $1 = ($1_ltype) Z_STRVAL_PP($input); -} +%{ + convert_to_string(&$input); + $1 = ($1_ltype) Z_STRVAL($input); +%} -%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) { - convert_to_string_ex($input); - $1 = ($1_ltype) Z_STRVAL_PP($input); - $2 = ($2_ltype) Z_STRLEN_PP($input); -} +%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) %{ + convert_to_string(&$input); + $1 = ($1_ltype) Z_STRVAL($input); + $2 = ($2_ltype) Z_STRLEN($input); +%} /* Object passed by value. Convert to a pointer */ %typemap(in) SWIGTYPE ($&1_ltype tmp) -{ - if(SWIG_ConvertPtr(*$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); } $1 = *tmp; -} +%} %typemap(directorout) SWIGTYPE ($&1_ltype tmp) -{ +%{ /* If exit was via exception, PHP NULL is returned so skip the conversion. */ if (!EG(exception)) { - if(SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) + if (SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); $result = *tmp; } -} +%} %typemap(in) SWIGTYPE *, SWIGTYPE [] -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(in) SWIGTYPE & -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(in) SWIGTYPE && -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); } -} +%} %typemap(in) SWIGTYPE *const& ($*ltype temp) -{ - if(SWIG_ConvertPtr(*$input, (void **) &temp, $*1_descriptor, 0) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &temp, $*1_descriptor, 0) < 0) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); } $1 = ($1_ltype)&temp; -} +%} %typemap(in) SWIGTYPE *DISOWN -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); } -} +%} %typemap(argout) SWIGTYPE *, SWIGTYPE [], @@ -144,14 +144,14 @@ SWIGTYPE &&; %typemap(in) void * -{ - if(SWIG_ConvertPtr(*$input, (void **) &$1, 0, 0) < 0) { +%{ + if (SWIG_ConvertPtr(&$input, (void **) &$1, 0, 0) < 0) { /* Allow NULL from php for void* */ - if ((*$input)->type==IS_NULL) $1=0; + if (Z_ISNULL($input)) $1=0; else SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); } -} +%} /* Special case when void* is passed by reference so it can be made to point to opaque api structs */ @@ -160,9 +160,9 @@ { /* If they pass NULL by reference, make it into a void* This bit should go in arginit if arginit support init-ing scripting args */ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ - if (!((*$input)->type==IS_NULL && PZVAL_IS_REF(*$input))) { + if (!(Z_ISREF($input) && Z_ISNULL_P(Z_REFVAL($input)))) { /* wasn't a pre/ref/thing, OR anything like an int thing */ SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); } @@ -181,11 +181,11 @@ } %typemap(argout) void **, void *& -{ +%{ if (force$argnum) { - SWIG_SetPointerZval( *$input, (void*) ptr$argnum, $*1_descriptor, 1); + SWIG_SetPointerZval(&$input, (void*) ptr$argnum, $*1_descriptor, 1); } -} +%} /* Typemap for output values */ @@ -199,35 +199,33 @@ unsigned char, bool, size_t -{ - ZVAL_LONG(return_value,$1); -} +%{ + RETVAL_LONG($1); +%} %typemap(out) enum SWIGTYPE -{ - ZVAL_LONG(return_value, (long)$1); -} +%{ + RETVAL_LONG((long)$1); +%} %typemap(out) long long %{ if ((long long)LONG_MIN <= $1 && $1 <= (long long)LONG_MAX) { - return_value->value.lval = (long)($1); - return_value->type = IS_LONG; + RETVAL_LONG((long)($1)); } else { char temp[256]; sprintf(temp, "%lld", (long long)$1); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} %typemap(out) unsigned long long %{ if ($1 <= (unsigned long long)LONG_MAX) { - return_value->value.lval = (long)($1); - return_value->type = IS_LONG; + RETVAL_LONG((long)($1)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)$1); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} @@ -241,40 +239,38 @@ const unsigned char &, const bool &, const size_t & -{ - ZVAL_LONG(return_value,*$1); -} +%{ + RETVAL_LONG(*$1); +%} %typemap(out) const enum SWIGTYPE & -{ - ZVAL_LONG(return_value, (long)*$1); -} +%{ + RETVAL_LONG((long)*$1); +%} %typemap(out) const enum SWIGTYPE && -{ - ZVAL_LONG(return_value, (long)*$1); -} +%{ + RETVAL_LONG((long)*$1); +%} %typemap(out) const long long & %{ if ((long long)LONG_MIN <= *$1 && *$1 <= (long long)LONG_MAX) { - return_value->value.lval = (long)(*$1); - return_value->type = IS_LONG; + RETVAL_LONG((long)(*$1)); } else { char temp[256]; sprintf(temp, "%lld", (long long)(*$1)); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} %typemap(out) const unsigned long long & %{ if (*$1 <= (unsigned long long)LONG_MAX) { - return_value->value.lval = (long)(*$1); - return_value->type = IS_LONG; + RETVAL_LONG((long)(*$1)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)(*$1)); - ZVAL_STRING(return_value, temp, 1); + RETVAL_STRING(temp); } %} @@ -288,85 +284,85 @@ unsigned char, size_t, enum SWIGTYPE -{ +%{ ZVAL_LONG($input,$1); -} +%} %typemap(directorin) enum SWIGTYPE -{ +%{ ZVAL_LONG($input, (long)$1_name); -} +%} %typemap(directorin) char *, char [] -{ +%{ if(!$1) { ZVAL_NULL($input); } else { - ZVAL_STRING($input, (char *)$1, 1); + ZVAL_STRING($input, (const char*)$1); } -} +%} %typemap(out) bool -{ - ZVAL_BOOL(return_value,($1)?1:0); -} +%{ + RETVAL_BOOL(($1) ? 1 : 0); +%} %typemap(out) const bool & -{ - ZVAL_BOOL(return_value,(*$1)?1:0); -} +%{ + RETVAL_BOOL((*$1) ? 1 : 0); +%} %typemap(directorin) bool -{ - ZVAL_BOOL($input,($1)?1:0); -} +%{ + ZVAL_BOOL($input, ($1) ? 1 : 0); +%} %typemap(out) float, double -{ - ZVAL_DOUBLE(return_value,$1); -} +%{ + RETVAL_DOUBLE($1); +%} %typemap(out) const float &, const double & -{ - ZVAL_DOUBLE(return_value,*$1); -} +%{ + RETVAL_DOUBLE(*$1); +%} %typemap(directorin) float, double -{ - ZVAL_DOUBLE($input,$1); -} +%{ + ZVAL_DOUBLE($input, $1); +%} %typemap(out) char -{ - ZVAL_STRINGL(return_value,&$1, 1, 1); -} +%{ + RETVAL_STRINGL(&$1, 1); +%} %typemap(out) const char & -{ - ZVAL_STRINGL(return_value,&*$1, 1, 1); -} +%{ + RETVAL_STRINGL(&*$1, 1); +%} %typemap(out) char *, char [] -{ - if(!$1) { - ZVAL_NULL(return_value); - } else { - ZVAL_STRING(return_value, (char *)$1, 1); - } -} +%{ + if (!$1) { + RETVAL_NULL(); + } else { + RETVAL_STRING((const char *)$1); + } +%} %typemap(out) char *& -{ - if(!*$1) { - ZVAL_NULL(return_value); - } else { - ZVAL_STRING(return_value, (char *)*$1, 1); - } -} +%{ + if (!*$1) { + RETVAL_NULL(); + } else { + RETVAL_STRING((const char *)*$1); + } +%} %typemap(out) SWIGTYPE *, SWIGTYPE [], @@ -393,12 +389,12 @@ { void * p = emalloc(sizeof($1)); memcpy(p, &$1, sizeof($1)); - ZEND_REGISTER_RESOURCE(return_value, p, swig_member_ptr); + RETVAL_RES(zend_register_resource(p, swig_member_ptr)); } %typemap(in, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) { - void * p = (void*)zend_fetch_resource($input TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, swig_member_ptr); + void * p = (void*)zend_fetch_resource_ex(&$input, SWIG_MEMBER_PTR, swig_member_ptr); memcpy(&$1, p, sizeof($1)); } @@ -424,9 +420,9 @@ #endif %typemap(directorin) SWIGTYPE -{ +%{ SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1|2); -} +%} %typemap(out) void ""; @@ -434,7 +430,7 @@ { int len = 0; while (len < $1_dim0 && $1[len]) ++len; - RETVAL_STRINGL($1, len, 1); + RETVAL_STRINGL($1, len); } // This typecheck does hard checking for proper argument type. If you want @@ -442,7 +438,13 @@ // it yourself before passing it (e.g. (string)4.7 or (int)"6"). %define %php_typecheck(_type,_prec,is) %typemap(typecheck,precedence=_prec) _type, const _type & - " $1 = (Z_TYPE_PP($input) == is); " + " $1 = (Z_TYPE($input) == is);" +%enddef + +// Like %php_typecheck but allows either of two values. +%define %php_typecheck2(_type,_prec,is1,is2) +%typemap(typecheck,precedence=_prec) _type, const _type & + " $1 = (Z_TYPE($input) == is1 || Z_TYPE($input) == is2);" %enddef %php_typecheck(int,SWIG_TYPECHECK_INTEGER,IS_LONG) @@ -457,18 +459,18 @@ %php_typecheck(unsigned char,SWIG_TYPECHECK_UINT8,IS_LONG) %php_typecheck(size_t,SWIG_TYPECHECK_SIZE,IS_LONG) %php_typecheck(enum SWIGTYPE,SWIG_TYPECHECK_INTEGER,IS_LONG) -%php_typecheck(bool,SWIG_TYPECHECK_BOOL,IS_BOOL) +%php_typecheck2(bool,SWIG_TYPECHECK_BOOL,IS_TRUE,IS_FALSE) %php_typecheck(float,SWIG_TYPECHECK_FLOAT,IS_DOUBLE) %php_typecheck(double,SWIG_TYPECHECK_DOUBLE,IS_DOUBLE) %php_typecheck(char,SWIG_TYPECHECK_CHAR,IS_STRING) %typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char *, char *&, char [] - " $1 = (Z_TYPE_PP($input) == IS_STRING); " + " $1 = (Z_TYPE($input) == IS_STRING); " %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void **)&tmp, $&1_descriptor, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void **)&tmp, $&1_descriptor, 0) >= 0); } %typecheck(SWIG_TYPECHECK_POINTER) @@ -479,19 +481,19 @@ SWIGTYPE *const& { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $1_descriptor, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void**)&tmp, $1_descriptor, 0) >= 0); } %typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *const& { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $*1_descriptor, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void**)&tmp, $*1_descriptor, 0) >= 0); } %typecheck(SWIG_TYPECHECK_VOIDPTR) void * { void *tmp; - _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, 0, 0) >= 0); + _v = (SWIG_ConvertPtr(&$input, (void**)&tmp, 0, 0) >= 0); } /* Exception handling */ @@ -501,19 +503,19 @@ short, unsigned int, unsigned long, - unsigned short { - zend_throw_exception(NULL, const_cast("C++ $1_type exception thrown"), $1 TSRMLS_CC); + unsigned short %{ + zend_throw_exception(NULL, "C++ $1_type exception thrown", $1); return; -} +%} %typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] %{ (void)$1; - zend_throw_exception(NULL, const_cast("C++ $1_type exception thrown"), 0 TSRMLS_CC); + zend_throw_exception(NULL, "C++ $1_type exception thrown", 0); return; %} %typemap(throws) char * %{ - zend_throw_exception(NULL, const_cast($1), 0 TSRMLS_CC); + zend_throw_exception(NULL, $1, 0); return; %} diff --git a/Lib/php/phpinit.swg b/Lib/php/phpinit.swg index 6e5cc29d2..7144f42a3 100644 --- a/Lib/php/phpinit.swg +++ b/Lib/php/phpinit.swg @@ -10,16 +10,16 @@ SWIG_InitializeModule(0); %} -%fragment("swig_php_init_member_ptr2", "header") { -#define SWIG_MEMBER_PTR ((char*)"CLASS::*") +%fragment("swig_php_init_member_ptr2", "header") %{ +#define SWIG_MEMBER_PTR "CLASS::*" -static void swig_member_ptr_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { - efree(rsrc->ptr); +static void swig_member_ptr_dtor(zend_resource *res) { + efree(res->ptr); } static int swig_member_ptr = 0; -} +%} -%fragment("swig_php_init_member_ptr", "init", fragment="swig_php_init_member_ptr2") { +%fragment("swig_php_init_member_ptr", "init", fragment="swig_php_init_member_ptr2") %{ swig_member_ptr = zend_register_list_destructors_ex(swig_member_ptr_dtor, NULL, SWIG_MEMBER_PTR, module_number); -} +%} diff --git a/Lib/php/phpkw.swg b/Lib/php/phpkw.swg index 36e535f52..db451f957 100644 --- a/Lib/php/phpkw.swg +++ b/Lib/php/phpkw.swg @@ -661,6 +661,21 @@ PHPCN(generator); // As of PHP 5.5 PHPCN(self); PHPCN(static); PHPCN(parent); +/* http://php.net/manual/en/migration70.incompatible.php#migration70.incompatible.other.classes */ +PHPCN(bool); // As of PHP 7.0 +PHPCN(int); // As of PHP 7.0 +PHPCN(float); // As of PHP 7.0 +PHPCN(string); // As of PHP 7.0 +PHPCN(NULL); // As of PHP 7.0 +PHPCN(TRUE); // As of PHP 7.0 +PHPCN(FALSE); // As of PHP 7.0 +PHPCN(resource); // As of PHP 7.0 (currently works but reserved) +PHPCN(object); // As of PHP 7.0 (currently works but reserved) +PHPCN(mixed); // As of PHP 7.0 (currently works but reserved) +PHPCN(numeric); // As of PHP 7.0 (currently works but reserved) +/* http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.invalid-class-names */ +PHPCN(iterable); // As of PHP 7.1 +PHPCN(void); // As of PHP 7.1 /* From extensions (which of these are actually predefined depends which * extensions are loaded by default). */ PHPCN(xmlwriter); diff --git a/Lib/php/phppointers.i b/Lib/php/phppointers.i index e50ada7ac..d79697b5e 100644 --- a/Lib/php/phppointers.i +++ b/Lib/php/phppointers.i @@ -3,19 +3,23 @@ TYPE &REF ($*1_ltype tmp) %{ /* First Check for SWIG wrapped type */ - if ( ZVAL_IS_NULL( *$input ) ) { + if (Z_ISNULL($input)) { $1 = 0; - } else if ( PZVAL_IS_REF( *$input ) ) { + } else if (Z_ISREF($input)) { /* Not swig wrapped type, so we check if it's a PHP reference type */ - CONVERT_IN( tmp, $*1_ltype, $input ); + CONVERT_IN(tmp, $*1_ltype, $input); $1 = &tmp; } else { - SWIG_PHP_Error( E_ERROR, SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference) ); + SWIG_PHP_Error(E_ERROR, SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference)); } %} %typemap(argout) TYPE *REF, TYPE &REF - "CONVERT_OUT(*$input, tmp$argnum );"; +%{ + if (Z_ISREF($input)) { + CONVERT_OUT(Z_REFVAL($input), tmp$argnum); + } +%} %enddef %pass_by_ref( size_t, CONVERT_INT_IN, ZVAL_LONG ); diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg index 0021a90e8..b697e2761 100644 --- a/Lib/php/phprun.swg +++ b/Lib/php/phprun.swg @@ -14,62 +14,22 @@ extern "C" { #include "ext/standard/php_string.h" #include /* for abort(), used in generated code. */ -#ifdef ZEND_RAW_FENTRY -/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */ -# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_RAW_FENTRY((char*)#ZN, N, A, 0) -#else -/* This causes warnings from GCC >= 4.2 (assigning a string literal to char*). - * But this seems to be unavoidable without directly assuming knowledge of - * the structure, which changed between PHP4 and PHP5. */ -# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) -#endif +/* This indirection is to work around const correctness issues in older PHP. + * FIXME: Remove for PHP7? Or might user code be using it? */ +#define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) -#ifndef ZEND_FE_END -# define ZEND_FE_END { NULL, NULL, NULL } -#endif - -#ifndef Z_SET_ISREF_P -/* For PHP < 5.3 */ -# define Z_SET_ISREF_P(z) (z)->is_ref = 1 -#endif -#ifndef Z_SET_REFCOUNT_P -/* For PHP < 5.3 */ -# define Z_SET_REFCOUNT_P(z, rc) (z)->refcount = (rc) -#endif - -#define SWIG_LONG_CONSTANT(N, V) zend_register_long_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) -#define SWIG_DOUBLE_CONSTANT(N, V) zend_register_double_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) -#define SWIG_STRING_CONSTANT(N, V) zend_register_stringl_constant((char*)#N, sizeof(#N), (char*)(V), strlen(V), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) +#define SWIG_LONG_CONSTANT(N, V) REGISTER_LONG_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) +#define SWIG_DOUBLE_CONSTANT(N, V) REGISTER_DOUBLE_CONSTANT(#N, V, CONST_CS | CONST_PERSISTENT) +#define SWIG_STRING_CONSTANT(N, V) REGISTER_STRING_CONSTANT(#N, (char*)V, CONST_CS | CONST_PERSISTENT) #define SWIG_CHAR_CONSTANT(N, V) do {\ - static char swig_char = (V);\ - zend_register_stringl_constant((char*)#N, sizeof(#N), &swig_char, 1, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);\ + char swig_char = (V);\ + REGISTER_STRINGL_CONSTANT(#N, &swig_char, 1, CONST_CS | CONST_PERSISTENT);\ } while (0) -/* These TSRMLS_ stuff should already be defined now, but with older php under - redhat are not... */ -#ifndef TSRMLS_D -#define TSRMLS_D -#endif -#ifndef TSRMLS_DC -#define TSRMLS_DC -#endif -#ifndef TSRMLS_C -#define TSRMLS_C -#endif -#ifndef TSRMLS_CC -#define TSRMLS_CC -#endif - #ifdef __cplusplus } #endif -/* But in fact SWIG_ConvertPtr is the native interface for getting typed - pointer values out of zvals. We need the TSRMLS_ macros for when we - make PHP type calls later as we handle php resources */ -#define SWIG_ConvertPtr(obj,pp,type,flags) SWIG_ZTS_ConvertPtr(obj,pp,type,flags TSRMLS_CC) - - #define SWIG_fail goto fail static const char *default_error_msg = "Unknown error occurred"; @@ -93,11 +53,10 @@ typedef struct { int newobject; } swig_object_wrapper; -#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC) #define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) static void -SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) { +SWIG_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject) { /* * First test for Null pointers. Return those as PHP native NULL */ @@ -114,19 +73,19 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject value->newobject=(newobject & 1); if ((newobject & 2) == 0) { /* Just register the pointer as a resource. */ - ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata)); + ZVAL_RES(z, zend_register_resource(value, *(int *)(type->clientdata))); } else { /* * Wrap the resource in an object, the resource will be accessible * via the "_cPtr" member. This is currently only used by * directorin typemaps. */ - zval *resource; - zend_class_entry **ce = NULL; + zval resource; + zend_class_entry *ce = NULL; const char *type_name = type->name+3; /* +3 so: _p_Foo -> Foo */ size_t type_name_len; - int result; const char * p; + HashTable * ht; /* Namespace__Foo -> Foo */ /* FIXME: ugly and goes wrong for classes with __ in their names. */ @@ -135,26 +94,27 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject } type_name_len = strlen(type_name); - MAKE_STD_ZVAL(resource); - ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata)); + ZVAL_RES(&resource, zend_register_resource(value, *(int *)(type->clientdata))); if (SWIG_PREFIX_LEN > 0) { - char * classname = (char*)emalloc(SWIG_PREFIX_LEN + type_name_len + 1); - strcpy(classname, SWIG_PREFIX); - strcpy(classname + SWIG_PREFIX_LEN, type_name); - result = zend_lookup_class(classname, SWIG_PREFIX_LEN + type_name_len, &ce TSRMLS_CC); - efree(classname); + zend_string * classname = zend_string_alloc(SWIG_PREFIX_LEN + type_name_len, 0); + memcpy(classname->val, SWIG_PREFIX, SWIG_PREFIX_LEN); + memcpy(classname->val + SWIG_PREFIX_LEN, type_name, type_name_len); + ce = zend_lookup_class(classname); + zend_string_release(classname); } else { - result = zend_lookup_class((char *)type_name, type_name_len, &ce TSRMLS_CC); + zend_string * classname = zend_string_init(type_name, type_name_len, 0); + ce = zend_lookup_class(classname); + zend_string_release(classname); } - if (result != SUCCESS) { + if (ce == NULL) { /* class does not exist */ - object_init(z); - } else { - object_init_ex(z, *ce); + ce = zend_standard_class_def; } - Z_SET_REFCOUNT_P(z, 1); - Z_SET_ISREF_P(z); - zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval*), NULL); + + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, 1, NULL, NULL, 0); + zend_hash_str_update(ht, "_cPtr", sizeof("_cPtr") - 1, &resource); + object_and_properties_init(z, ce, ht); } return; } @@ -170,11 +130,11 @@ SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject instance of a resource of the type id, so we have to pass type_name as well. The two functions which might call this are: - SWIG_ZTS_ConvertResourcePtr which gets the type name from the resource + SWIG_ConvertResourcePtr which gets the type name from the resource and the registered zend destructors for which we have one per type each with the type name hard wired in. */ static void * -SWIG_ZTS_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty TSRMLS_DC) { +SWIG_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty) { swig_cast_info *tc; void *result = 0; @@ -201,48 +161,53 @@ SWIG_ZTS_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty /* This function returns a pointer of type ty by extracting the pointer and type info from the resource in z. z must be a resource. If it fails, NULL is returned. - It uses SWIG_ZTS_ConvertResourceData to do the real work. */ + It uses SWIG_ConvertResourceData to do the real work. */ static void * -SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) { +SWIG_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags) { swig_object_wrapper *value; void *p; - int type; const char *type_name; - value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type); - if (type==-1) return NULL; + if (Z_RES_TYPE_P(z) == -1) return NULL; + value = (swig_object_wrapper *) Z_RES_VAL_P(z); if (flags & SWIG_POINTER_DISOWN) { value->newobject = 0; } p = value->ptr; - type_name=zend_rsrc_list_get_rsrc_type(z->value.lval TSRMLS_CC); + type_name=zend_rsrc_list_get_rsrc_type(Z_RES_P(z)); - return SWIG_ZTS_ConvertResourceData(p, type_name, ty TSRMLS_CC); + return SWIG_ConvertResourceData(p, type_name, ty); } /* We allow passing of a RESOURCE pointing to the object or an OBJECT whose _cPtr is a resource pointing to the object */ static int -SWIG_ZTS_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags TSRMLS_DC) { +SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) { if (z == NULL) { *ptr = 0; return 0; } - switch (z->type) { + switch (Z_TYPE_P(z)) { case IS_OBJECT: { - zval ** _cPtr; - if (zend_hash_find(HASH_OF(z),(char*)"_cPtr",sizeof("_cPtr"),(void**)&_cPtr)==SUCCESS) { - if ((*_cPtr)->type==IS_RESOURCE) { - *ptr = SWIG_ZTS_ConvertResourcePtr(*_cPtr, ty, flags TSRMLS_CC); - return (*ptr == NULL ? -1 : 0); - } + HashTable * ht = Z_OBJ_HT_P(z)->get_properties(z); + if (ht) { + zval * _cPtr = zend_hash_str_find(ht, "_cPtr", sizeof("_cPtr") - 1); + if (_cPtr) { + if (Z_TYPE_P(_cPtr) == IS_INDIRECT) { + _cPtr = Z_INDIRECT_P(_cPtr); + } + if (Z_TYPE_P(_cPtr) == IS_RESOURCE) { + *ptr = SWIG_ConvertResourcePtr(_cPtr, ty, flags); + return (*ptr == NULL ? -1 : 0); + } + } } break; } case IS_RESOURCE: - *ptr = SWIG_ZTS_ConvertResourcePtr(z, ty, flags TSRMLS_CC); + *ptr = SWIG_ConvertResourcePtr(z, ty, flags); return (*ptr == NULL ? -1 : 0); case IS_NULL: *ptr = 0; @@ -254,22 +219,15 @@ SWIG_ZTS_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags TSRMLS_DC static char const_name[] = "swig_runtime_data_type_pointer"; static swig_module_info *SWIG_Php_GetModule() { - zval *pointer; - swig_module_info *ret = 0; - TSRMLS_FETCH(); - - MAKE_STD_ZVAL(pointer); - - if (zend_get_constant(const_name, sizeof(const_name) - 1, pointer TSRMLS_CC)) { - if (pointer->type == IS_LONG) { - ret = (swig_module_info *) pointer->value.lval; + zval *pointer = zend_get_constant_str(const_name, sizeof(const_name) - 1); + if (pointer) { + if (Z_TYPE_P(pointer) == IS_LONG) { + return (swig_module_info *) pointer->value.lval; } } - FREE_ZVAL(pointer); - return ret; + return NULL; } static void SWIG_Php_SetModule(swig_module_info *pointer) { - TSRMLS_FETCH(); REGISTER_MAIN_LONG_CONSTANT(const_name, (long) pointer, 0); } diff --git a/Lib/php/std_string.i b/Lib/php/std_string.i index aaa5dc9cd..b55751f07 100644 --- a/Lib/php/std_string.i +++ b/Lib/php/std_string.i @@ -24,53 +24,68 @@ namespace std { class string; %typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) string, const string& %{ - $1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0; + $1 = (Z_TYPE($input) == IS_STRING) ? 1 : 0; %} %typemap(in) string %{ - convert_to_string_ex($input); - $1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); + convert_to_string(&$input); + $1.assign(Z_STRVAL($input), Z_STRLEN($input)); %} %typemap(directorout) string %{ - convert_to_string_ex(&$input); + if (!EG(exception)) { + convert_to_string($input); $result.assign(Z_STRVAL_P($input), Z_STRLEN_P($input)); + } %} %typemap(out) string %{ - ZVAL_STRINGL($result, const_cast($1.data()), $1.size(), 1); + ZVAL_STRINGL($result, $1.data(), $1.size()); %} %typemap(directorin) string, const string& %{ - ZVAL_STRINGL($input, const_cast($1.data()), $1.size(), 1); + ZVAL_STRINGL($input, $1.data(), $1.size()); %} %typemap(out) const string & %{ - ZVAL_STRINGL($result, const_cast($1->data()), $1->size(), 1); + ZVAL_STRINGL($result, $1->data(), $1->size()); %} %typemap(throws) string, const string& %{ - zend_throw_exception(NULL, const_cast($1.c_str()), 0 TSRMLS_CC); + zend_throw_exception(NULL, $1.c_str(), 0); return; %} + %typemap(in) const string & ($*1_ltype temp) %{ + convert_to_string(&$input); + temp.assign(Z_STRVAL($input), Z_STRLEN($input)); + $1 = &temp; + %} + /* These next two handle a function which takes a non-const reference to * a std::string and modifies the string. */ - %typemap(in) string & ($*1_ltype temp) %{ - convert_to_string_ex($input); - temp.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); - $1 = &temp; + %typemap(in,byref=1) string & ($*1_ltype temp) %{ + { + zval * p = Z_ISREF($input) ? Z_REFVAL($input) : &$input; + convert_to_string(p); + temp.assign(Z_STRVAL_P(p), Z_STRLEN_P(p)); + $1 = &temp; + } %} %typemap(directorout) string & ($*1_ltype *temp) %{ - convert_to_string_ex(&$input); + if (!EG(exception)) { + convert_to_string($input); temp = new $*1_ltype(Z_STRVAL_P($input), Z_STRLEN_P($input)); swig_acquire_ownership(temp); $result = temp; + } %} %typemap(argout) string & %{ - ZVAL_STRINGL(*($input), const_cast($1->data()), $1->size(), 1); + if (Z_ISREF($input)) { + ZVAL_STRINGL(Z_REFVAL($input), $1->data(), $1->size()); + } %} /* SWIG will apply the non-const typemap above to const string& without diff --git a/Lib/php/typemaps.i b/Lib/php/typemaps.i index faae0a6ac..c248a588e 100644 --- a/Lib/php/typemaps.i +++ b/Lib/php/typemaps.i @@ -27,87 +27,77 @@ %define BOOL_TYPEMAP(TYPE) %typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ - convert_to_boolean_ex($input); - temp = Z_LVAL_PP($input) ? true : false; + convert_to_boolean(&$input); + temp = (Z_TYPE($input) == IS_TRUE); $1 = &temp; %} %typemap(argout) TYPE *INPUT, TYPE &INPUT ""; %typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_BOOL(o,temp$argnum); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_BOOL(&o, temp$argnum); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) %{ - convert_to_boolean_ex($input); - lvalue = (*$input)->value.lval ? true : false; + convert_to_boolean($input); + lvalue = (Z_TYPE_P($input) == IS_TRUE); $1 = &lvalue; %} %typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE %{ - (*$arg)->value.lval = lvalue$argnum ? true : false; - (*$arg)->type = IS_BOOL; + ZVAL_BOOL(&$arg, lvalue$argnum ? true : false); %} %enddef %define DOUBLE_TYPEMAP(TYPE) %typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ - convert_to_double_ex($input); - temp = (TYPE) Z_DVAL_PP($input); + temp = (TYPE) zval_get_double(&$input); $1 = &temp; %} %typemap(argout) TYPE *INPUT, TYPE &INPUT ""; %typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_DOUBLE(o,temp$argnum); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_DOUBLE(&o, temp$argnum); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (TYPE dvalue), TYPE &REFERENCE (TYPE dvalue) %{ - convert_to_double_ex($input); - dvalue = (TYPE) (*$input)->value.dval; + dvalue = (TYPE) zval_get_double(&$input); $1 = &dvalue; %} %typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE %{ - $1->value.dval = (double)(lvalue$argnum); - $1->type = IS_DOUBLE; + ZVAL_DOUBLE(&$arg, (double)(lvalue$argnum)); %} %enddef %define INT_TYPEMAP(TYPE) %typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) %{ - convert_to_long_ex($input); - temp = (TYPE) Z_LVAL_PP($input); + temp = (TYPE) zval_get_long(&$input); $1 = &temp; %} %typemap(argout) TYPE *INPUT, TYPE &INPUT ""; %typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; %typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_LONG(o,temp$argnum); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_LONG(&o, temp$argnum); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) %{ - convert_to_long_ex($input); - lvalue = (TYPE) (*$input)->value.lval; + lvalue = (TYPE) zval_get_long(&$input); $1 = &lvalue; %} %typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE %{ - (*$arg)->value.lval = (long)(lvalue$argnum); - (*$arg)->type = IS_LONG; + ZVAL_LONG(&$arg, (long)(lvalue$argnum)); %} %enddef @@ -128,16 +118,15 @@ INT_TYPEMAP(signed char); INT_TYPEMAP(long long); %typemap(argout,fragment="t_output_helper") long long *OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); + zval o; if ((long long)LONG_MIN <= temp$argnum && temp$argnum <= (long long)LONG_MAX) { - ZVAL_LONG(o, temp$argnum); + ZVAL_LONG(&o, (long)temp$argnum); } else { char temp[256]; sprintf(temp, "%lld", (long long)temp$argnum); - ZVAL_STRING(o, temp, 1); + ZVAL_STRING(&o, temp); } - t_output_helper( &$result, o TSRMLS_CC ); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (long long lvalue) %{ @@ -147,38 +136,35 @@ INT_TYPEMAP(long long); %typemap(argout) long long *REFERENCE %{ if ((long long)LONG_MIN <= lvalue$argnum && lvalue$argnum <= (long long)LONG_MAX) { - (*$arg)->value.lval = (long)(lvalue$argnum); - (*$arg)->type = IS_LONG; + ZVAL_LONG(&$arg, (long)temp$argnum); } else { char temp[256]; sprintf(temp, "%lld", (long long)lvalue$argnum); - ZVAL_STRING((*$arg), temp, 1); + ZVAL_STRING(&$arg, temp); } %} %typemap(argout) long long &OUTPUT %{ if ((long long)LONG_MIN <= *arg$argnum && *arg$argnum <= (long long)LONG_MAX) { - ($result)->value.lval = (long)(*arg$argnum); - ($result)->type = IS_LONG; + ZVAL_LONG($result, (long)(*arg$argnum)); } else { char temp[256]; sprintf(temp, "%lld", (long long)(*arg$argnum)); - ZVAL_STRING($result, temp, 1); + ZVAL_STRING($result, temp); } %} INT_TYPEMAP(unsigned long long); %typemap(argout,fragment="t_output_helper") unsigned long long *OUTPUT { - zval *o; - MAKE_STD_ZVAL(o); + zval o; if (temp$argnum <= (unsigned long long)LONG_MAX) { - ZVAL_LONG(o, temp$argnum); + ZVAL_LONG(&o, temp$argnum); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)temp$argnum); - ZVAL_STRING(o, temp, 1); + ZVAL_STRING(&o, temp); } - t_output_helper( &$result, o TSRMLS_CC ); + t_output_helper($result, &o); } %typemap(in) TYPE *REFERENCE (unsigned long long lvalue) %{ @@ -188,23 +174,21 @@ INT_TYPEMAP(unsigned long long); %typemap(argout) unsigned long long *REFERENCE %{ if (lvalue$argnum <= (unsigned long long)LONG_MAX) { - (*$arg)->value.lval = (long)(lvalue$argnum); - (*$arg)->type = IS_LONG; + ZVAL_LONG($arg, (long)(lvalue$argnum)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)lvalue$argnum); - ZVAL_STRING((*$arg), temp, 1); + ZVAL_STRING((*$arg), temp); } %} %typemap(argout) unsigned long long &OUTPUT %{ if (*arg$argnum <= (unsigned long long)LONG_MAX) { - ($result)->value.lval = (long)(*arg$argnum); - ($result)->type = IS_LONG; + ZVAL_LONG($result, (long)(*arg$argnum)); } else { char temp[256]; sprintf(temp, "%llu", (unsigned long long)(*arg$argnum)); - ZVAL_STRING($result, temp, 1); + ZVAL_STRING($result, temp); } %} @@ -270,18 +254,17 @@ INT_TYPEMAP(unsigned long long); %typemap(in) char INPUT[ANY] ( char temp[$1_dim0] ) %{ - convert_to_string_ex($input); - strncpy(temp,Z_STRVAL_PP($input),$1_dim0); + convert_to_string(&$input); + strncpy(temp, Z_STRVAL($input), $1_dim0); $1 = temp; %} %typemap(in,numinputs=0) char OUTPUT[ANY] ( char temp[$1_dim0] ) "$1 = temp;"; %typemap(argout,fragment="t_output_helper") char OUTPUT[ANY] { - zval *o; - MAKE_STD_ZVAL(o); - ZVAL_STRINGL(o,temp$argnum,$1_dim0); - t_output_helper( &$result, o TSRMLS_CC ); + zval o; + ZVAL_STRINGL(&o, temp$argnum, $1_dim0); + t_output_helper($result, &o); } %typemap(in,numinputs=0) void **OUTPUT (int force), @@ -289,9 +272,9 @@ INT_TYPEMAP(unsigned long long); %{ /* If they pass NULL by reference, make it into a void* This bit should go in arginit if arginit support init-ing scripting args */ - if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + if (SWIG_ConvertPtr(&$input, (void **) &$1, $1_descriptor, 0) < 0) { /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ - if (!((*$input)->type==IS_NULL && PZVAL_IS_REF(*$input))) { + if (!(Z_ISREF($input) && Z_ISNULL_P(Z_REFVAL($input)))) { /* wasn't a pre/ref/thing, OR anything like an int thing */ SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); } @@ -313,7 +296,7 @@ INT_TYPEMAP(unsigned long long); void *&OUTPUT %{ if (force$argnum) { /* pass back arg$argnum through params ($arg) if we can */ - if (!PZVAL_IS_REF(*$arg)) { + if (!Z_ISREF($arg)) { SWIG_PHP_Error(E_WARNING, "Parameter $argnum of $symname wasn't passed by reference"); } else { SWIG_SetPointerZval(*$arg, (void *) ptr$argnum, $*1_descriptor, 1); diff --git a/Lib/php/utils.i b/Lib/php/utils.i index 408a3b366..8581646a2 100644 --- a/Lib/php/utils.i +++ b/Lib/php/utils.i @@ -1,70 +1,65 @@ %define CONVERT_BOOL_IN(lvar,t,invar) - convert_to_boolean_ex(invar); - lvar = (t) Z_LVAL_PP(invar); + lvar = (t) zval_is_true(&invar); %enddef %define CONVERT_INT_IN(lvar,t,invar) - convert_to_long_ex(invar); - lvar = (t) Z_LVAL_PP(invar); + lvar = (t) zval_get_long(&invar); %enddef %define CONVERT_LONG_LONG_IN(lvar,t,invar) - switch ((*(invar))->type) { + switch (Z_TYPE(invar)) { case IS_DOUBLE: - lvar = (t) (*(invar))->value.dval; + lvar = (t) Z_DVAL(invar); break; case IS_STRING: { char * endptr; errno = 0; - lvar = (t) strtoll((*(invar))->value.str.val, &endptr, 10); + lvar = (t) strtoll(Z_STRVAL(invar), &endptr, 10); if (*endptr && !errno) break; /* FALL THRU */ } default: - convert_to_long_ex(invar); - lvar = (t) (*(invar))->value.lval; + lvar = (t) zval_get_long(&invar); } %enddef %define CONVERT_UNSIGNED_LONG_LONG_IN(lvar,t,invar) - switch ((*(invar))->type) { + switch (Z_TYPE(invar)) { case IS_DOUBLE: - lvar = (t) (*(invar))->value.dval; + lvar = (t) Z_DVAL(invar); break; case IS_STRING: { char * endptr; errno = 0; - lvar = (t) strtoull((*(invar))->value.str.val, &endptr, 10); + lvar = (t) strtoull(Z_STRVAL(invar), &endptr, 10); if (*endptr && !errno) break; /* FALL THRU */ } default: - convert_to_long_ex(invar); - lvar = (t) (*(invar))->value.lval; + lvar = (t) zval_get_long(&invar); } %enddef %define CONVERT_INT_OUT(lvar,invar) - lvar = (t) Z_LVAL_PP(invar); + lvar = (t) zval_get_long(&invar); %enddef %define CONVERT_FLOAT_IN(lvar,t,invar) - convert_to_double_ex(invar); - lvar = (t) Z_DVAL_PP(invar); + lvar = (t) zval_get_double(&invar); %enddef %define CONVERT_CHAR_IN(lvar,t,invar) - convert_to_string_ex(invar); - lvar = (t) *Z_STRVAL_PP(invar); + convert_to_string(&invar); + lvar = (t) Z_STRVAL(invar)[0]; %enddef %define CONVERT_STRING_IN(lvar,t,invar) - if ((*invar)->type==IS_NULL) { + if (Z_ISNULL(invar)) { lvar = (t) 0; } else { - convert_to_string_ex(invar); - lvar = (t) Z_STRVAL_PP(invar); + convert_to_string(&invar); + lvar = (t) Z_STRVAL(invar); } %enddef @@ -80,35 +75,42 @@ %} %typemap(directorout) TYPE %{ - CONVERT_IN($result,$1_ltype,&$input); + if (!EG(exception)) { + CONVERT_IN($result, $1_ltype, *$input); + } else { + typedef $1_ltype swig_result_typedef; + $result = swig_result_typedef(); + } %} %typemap(directorout) const TYPE & ($*1_ltype temp) %{ - CONVERT_IN(temp,$*1_ltype,&$input); + if (!EG(exception)) { + CONVERT_IN(temp, $*1_ltype, *$input); + } else { + typedef $*1_ltype swig_result_typedef; + temp = swig_result_typedef(); + } $result = &temp; %} %enddef %fragment("t_output_helper","header") %{ static void -t_output_helper(zval **target, zval *o TSRMLS_DC) { - zval *tmp; - if ( (*target)->type == IS_ARRAY ) { +t_output_helper(zval *target, zval *o) { + zval tmp; + if (Z_TYPE_P(target) == IS_ARRAY) { /* it's already an array, just append */ - add_next_index_zval( *target, o ); + add_next_index_zval(target, o); return; } - if ( (*target)->type == IS_NULL ) { - REPLACE_ZVAL_VALUE(target,o,1); - FREE_ZVAL(o); + if (Z_TYPE_P(target) == IS_NULL) { + /* NULL isn't refcounted */ + ZVAL_COPY_VALUE(target, o); return; } - ALLOC_INIT_ZVAL(tmp); - *tmp = **target; - zval_copy_ctor(tmp); - array_init(*target); - add_next_index_zval( *target, tmp); - add_next_index_zval( *target, o); - + ZVAL_DUP(&tmp, target); + array_init(target); + add_next_index_zval(target, &tmp); + add_next_index_zval(target, o); } %} diff --git a/Lib/php5/const.i b/Lib/php5/const.i new file mode 100644 index 000000000..061ba99a2 --- /dev/null +++ b/Lib/php5/const.i @@ -0,0 +1,51 @@ +/* ----------------------------------------------------------------------------- + * const.i + * + * Typemaps for constants + * ----------------------------------------------------------------------------- */ + +%typemap(consttab) int, + unsigned int, + short, + unsigned short, + long, + unsigned long, + unsigned char, + signed char, + bool, + enum SWIGTYPE + "SWIG_LONG_CONSTANT($symname, ($1_type)$value);"; + +%typemap(consttab) float, + double + "SWIG_DOUBLE_CONSTANT($symname, $value);"; + +%typemap(consttab) char + "SWIG_CHAR_CONSTANT($symname, $value);"; + +%typemap(consttab) char *, + const char *, + char [], + const char [] + "SWIG_STRING_CONSTANT($symname, $value);"; + +%typemap(consttab) SWIGTYPE *, + SWIGTYPE &, + SWIGTYPE &&, + SWIGTYPE [] { + zval *z_var; + zend_constant c; + size_t len = sizeof("$symname") - 1; + MAKE_STD_ZVAL(z_var); + SWIG_SetPointerZval(z_var, (void*)$value, $1_descriptor, 0); + c.value = *z_var; + zval_copy_ctor(&c.value); + c.name = zend_strndup("$symname", len); + c.name_len = len+1; + c.flags = CONST_CS | CONST_PERSISTENT; + c.module_number = module_number; + zend_register_constant( &c TSRMLS_CC ); +} + +/* Handled as a global variable. */ +%typemap(consttab) SWIGTYPE (CLASS::*) ""; diff --git a/Lib/php5/director.swg b/Lib/php5/director.swg new file mode 100644 index 000000000..638a1697d --- /dev/null +++ b/Lib/php5/director.swg @@ -0,0 +1,170 @@ +/* ----------------------------------------------------------------------------- + * director.swg + * + * This file contains support for director classes so that PHP proxy + * methods can be called from C++. + * ----------------------------------------------------------------------------- */ + +#ifndef SWIG_DIRECTOR_PHP_HEADER_ +#define SWIG_DIRECTOR_PHP_HEADER_ + +#include +#include +#include + +namespace Swig { + + /* memory handler */ + struct GCItem { + virtual ~GCItem() { + } + + virtual int get_own() const { + return 0; + } + }; + + struct GCItem_var { + GCItem_var(GCItem *item = 0) : _item(item) { + } + + GCItem_var& operator=(GCItem *item) { + GCItem *tmp = _item; + _item = item; + delete tmp; + return *this; + } + + ~GCItem_var() { + delete _item; + } + + GCItem * operator->() const { + return _item; + } + + private: + GCItem *_item; + }; + + struct GCItem_Object : GCItem { + GCItem_Object(int own) : _own(own) { + } + + virtual ~GCItem_Object() { + } + + int get_own() const { + return _own; + } + + private: + int _own; + }; + + template + struct GCItem_T : GCItem { + GCItem_T(Type *ptr) : _ptr(ptr) { + } + + virtual ~GCItem_T() { + delete _ptr; + } + + private: + Type *_ptr; + }; + + class Director { + protected: + zval *swig_self; + typedef std::map swig_ownership_map; + mutable swig_ownership_map swig_owner; +#ifdef ZTS + // Store the ZTS context so it's available when C++ calls back to PHP. + void *** swig_zts_ctx; +#endif + public: + Director(zval *self TSRMLS_DC) : swig_self(self) { + TSRMLS_SET_CTX(swig_zts_ctx); + } + + static bool swig_is_overridden_method(char *cname, char *lc_fname TSRMLS_DC) { + zend_class_entry **ce; + zend_function *mptr; + + if (zend_lookup_class(cname, strlen(cname), &ce TSRMLS_CC) != SUCCESS) { + return false; + } + if (zend_hash_find(&(*ce)->function_table, lc_fname, strlen(lc_fname) + 1, (void **) &mptr) != SUCCESS) { + return false; + } + // common.scope points to the declaring class + return strcmp(mptr->common.scope->name, cname); + } + + template + void swig_acquire_ownership(Type *vptr) const { + if (vptr) { + swig_owner[vptr] = new GCItem_T(vptr); + } + } + }; + + /* base class for director exceptions */ + class DirectorException : public std::exception { + protected: + std::string swig_msg; + public: + DirectorException(int code, const char *hdr, const char *msg TSRMLS_DC) : swig_msg(hdr) { + if (msg[0]) { + swig_msg += " "; + swig_msg += msg; + } + SWIG_ErrorCode() = code; + SWIG_ErrorMsg() = swig_msg.c_str(); + } + + virtual ~DirectorException() throw() { + } + + const char *what() const throw() { + return swig_msg.c_str(); + } + + static void raise(int code, const char *hdr, const char *msg TSRMLS_DC) { + throw DirectorException(code, hdr, msg TSRMLS_CC); + } + }; + + /* attempt to call a pure virtual method via a director method */ + class DirectorPureVirtualException : public DirectorException { + public: + DirectorPureVirtualException(const char *msg TSRMLS_DC) + : DirectorException(E_ERROR, "SWIG director pure virtual method called", msg TSRMLS_CC) { + } + + static void raise(const char *msg TSRMLS_DC) { + throw DirectorPureVirtualException(msg TSRMLS_CC); + } + }; + + /* any php exception that occurs during a director method call */ + class DirectorMethodException : public DirectorException + { + public: + DirectorMethodException(const char *msg TSRMLS_DC) + : DirectorException(E_ERROR, "SWIG director method error", msg TSRMLS_CC) { + } + + static void raise(const char *msg TSRMLS_DC) { + throw DirectorMethodException(msg TSRMLS_CC); + } + }; +} + +// DirectorMethodException() is documented to be callable with no parameters +// so use a macro to insert TSRMLS_CC so any ZTS context gets passed. +#define DirectorMethodException() DirectorMethodException("" TSRMLS_CC) + +#endif diff --git a/Lib/php5/factory.i b/Lib/php5/factory.i new file mode 100644 index 000000000..c4e082dd2 --- /dev/null +++ b/Lib/php5/factory.i @@ -0,0 +1,109 @@ +/* + Implement a more natural wrap for factory methods, for example, if + you have: + + ---- geometry.h -------- + struct Geometry { + enum GeomType{ + POINT, + CIRCLE + }; + + virtual ~Geometry() {} + virtual int draw() = 0; + + // + // Factory method for all the Geometry objects + // + static Geometry *create(GeomType i); + }; + + struct Point : Geometry { + int draw() { return 1; } + double width() { return 1.0; } + }; + + struct Circle : Geometry { + int draw() { return 2; } + double radius() { return 1.5; } + }; + + // + // Factory method for all the Geometry objects + // + Geometry *Geometry::create(GeomType type) { + switch (type) { + case POINT: return new Point(); + case CIRCLE: return new Circle(); + default: return 0; + } + } + ---- geometry.h -------- + + + You can use the %factory with the Geometry::create method as follows: + + %newobject Geometry::create; + %factory(Geometry *Geometry::create, Point, Circle); + %include "geometry.h" + + and Geometry::create will return a 'Point' or 'Circle' instance + instead of the plain 'Geometry' type. For example, in python: + + circle = Geometry.create(Geometry.CIRCLE) + r = circle.radius() + + where circle is a Circle proxy instance. + + NOTES: remember to fully qualify all the type names and don't + use %factory inside a namespace declaration, ie, instead of + + namespace Foo { + %factory(Geometry *Geometry::create, Point, Circle); + } + + use + + %factory(Foo::Geometry *Foo::Geometry::create, Foo::Point, Foo::Circle); + + +*/ + +/* for loop for macro with one argument */ +%define %_formacro_1(macro, arg1,...)macro(arg1) +#if #__VA_ARGS__ != "__fordone__" +%_formacro_1(macro, __VA_ARGS__) +#endif +%enddef + +/* for loop for macro with one argument */ +%define %formacro_1(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef +%define %formacro(macro,...)%_formacro_1(macro,__VA_ARGS__,__fordone__)%enddef + +/* for loop for macro with two arguments */ +%define %_formacro_2(macro, arg1, arg2, ...)macro(arg1, arg2) +#if #__VA_ARGS__ != "__fordone__" +%_formacro_2(macro, __VA_ARGS__) +#endif +%enddef + +/* for loop for macro with two arguments */ +%define %formacro_2(macro,...)%_formacro_2(macro, __VA_ARGS__, __fordone__)%enddef + +%define %_factory_dispatch(Type) +if (!dcast) { + Type *dobj = dynamic_cast($1); + if (dobj) { + dcast = 1; + SWIG_SetPointerZval(return_value, SWIG_as_voidptr(dobj),$descriptor(Type *), $owner); + } +}%enddef + +%define %factory(Method,Types...) +%typemap(out) Method { + int dcast = 0; + %formacro(%_factory_dispatch, Types) + if (!dcast) { + SWIG_SetPointerZval(return_value, SWIG_as_voidptr($1),$descriptor, $owner); + } +}%enddef diff --git a/Lib/php5/globalvar.i b/Lib/php5/globalvar.i new file mode 100644 index 000000000..a3e99f510 --- /dev/null +++ b/Lib/php5/globalvar.i @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- + * globalvar.i + * + * Global variables - add the variable to PHP + * ----------------------------------------------------------------------------- */ + +%typemap(varinit) char * +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + z_var->type = IS_STRING; + if($1) { + z_var->value.str.val = estrdup($1); + z_var->value.str.len = strlen($1); + } else { + z_var->value.str.val = 0; + z_var->value.str.len = 0; + } + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); +} + +%typemap(varinit) char [] +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + z_var->type = IS_STRING; + z_var->value.str.val = estrdup($1); + z_var->value.str.len = strlen($1); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); +} + +%typemap(varinit) int, + unsigned int, + unsigned short, + short, + unsigned short, + long, + unsigned long, + signed char, + unsigned char, + enum SWIGTYPE +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + z_var->type = IS_LONG; + z_var->value.lval = (long)$1; + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); +} + +%typemap(varinit) bool +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + z_var->type = IS_BOOL; + z_var->value.lval = ($1)?1:0; + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, sizeof(zval *), NULL); +} + +%typemap(varinit) float, double +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + z_var->type = IS_DOUBLE; + z_var->value.dval = $1; + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, + sizeof(zval *), NULL); +} + +%typemap(varinit) char +{ + zval *z_var; + char c[2]; + MAKE_STD_ZVAL(z_var); + c[0] = $1; + c[1] = 0; + z_var->type = IS_STRING; + z_var->value.str.val = estrndup(c, 1); + z_var->value.str.len = 1; + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, + sizeof(zval *), NULL); +} + +%typemap(varinit) SWIGTYPE *, SWIGTYPE [] +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + SWIG_SetPointerZval(z_var, (void*)$1, $1_descriptor, 0); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void *)&z_var, + sizeof(zval *), NULL); +} + +%typemap(varinit) SWIGTYPE, SWIGTYPE &, SWIGTYPE && +{ + zval *z_var; + + MAKE_STD_ZVAL(z_var); + SWIG_SetPointerZval(z_var, (void*)&$1, $&1_descriptor, 0); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, + sizeof(zval *), NULL); +} + +%typemap(varinit) char [ANY] +{ + zval *z_var; + MAKE_STD_ZVAL(z_var); + z_var->type = IS_STRING; + ZVAL_STRINGL(z_var,(char*)$1, $1_dim0, 1); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&z_var, sizeof(zval *), NULL); +} + +%typemap(varinit, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +{ + void * p = emalloc(sizeof($1)); + memcpy(p, &$1, sizeof($1)); + zval * resource; + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, p, swig_member_ptr); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); +} + +%typemap(varin) int, unsigned int, short, unsigned short, long, unsigned long, signed char, unsigned char, enum SWIGTYPE +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + convert_to_long_ex(z_var); + if ($1 != ($1_ltype)((*z_var)->value.lval)) { + $1 = Z_LVAL_PP(z_var); + } +} + +%typemap(varin) bool +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + convert_to_boolean_ex(z_var); + if ($1 != ($1_ltype)((*z_var)->value.lval)) { + $1 = Z_LVAL_PP(z_var); + } +} + +%typemap(varin) double,float +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + convert_to_double_ex(z_var); + if ($1 != ($1_ltype)((*z_var)->value.dval)) { + $1 = Z_DVAL_PP(z_var); + } +} + +%typemap(varin) char +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + convert_to_string_ex(z_var); + if ($1 != *((*z_var)->value.str.val)) { + $1 = *((*z_var)->value.str.val); + } +} + +%typemap(varin) char * +{ + zval **z_var; + char *s1; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + convert_to_string_ex(z_var); + s1 = Z_STRVAL_PP(z_var); + if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { + if (s1) + $1 = estrdup(s1); + else + $1 = NULL; + } +} + + +%typemap(varin) SWIGTYPE [] +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if($1) { + SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, $owner); + } +} + +%typemap(varin) char [ANY] +{ + zval **z_var; + char *s1; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + s1 = Z_STRVAL_PP(z_var); + if ((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { + if (s1) + strncpy($1, s1, $1_dim0); + } +} + +%typemap(varin) SWIGTYPE +{ + zval **z_var; + $&1_ltype _temp; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if (SWIG_ConvertPtr(*z_var, (void**)&_temp, $&1_descriptor, 0) < 0) { + SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); + } + + $1 = *($&1_ltype)_temp; + +} + +%typemap(varin) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && +{ + zval **z_var; + $1_ltype _temp; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if (SWIG_ConvertPtr(*z_var, (void **)&_temp, $1_descriptor, 0) < 0) { + SWIG_PHP_Error(E_ERROR,"Type error in value of $symname. Expected $&1_descriptor"); + } + + $1 = ($1_ltype)_temp; +} + +%typemap(varin, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + void * p = (void*)zend_fetch_resource(*z_var TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, swig_member_ptr); + memcpy(&$1, p, sizeof($1)); +} + +%typemap(varout) int, + unsigned int, + unsigned short, + short, + long, + unsigned long, + signed char, + unsigned char, + enum SWIGTYPE +{ + zval **z_var; + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if($1 != ($1_ltype)((*z_var)->value.lval)) { + (*z_var)->value.lval = (long)$1; + } +} + +//SAMFIX need to cast zval->type, what if zend-hash_find fails? etc? +%typemap(varout) bool +{ + zval **z_var; + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if($1 != ($1_ltype)((*z_var)->value.lval)) { + (*z_var)->value.lval = (long)$1; + } +} + +%typemap(varout) double, float +{ + zval **z_var; + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if($1 != ($1_ltype)((*z_var)->value.dval)) { + (*z_var)->value.dval = (double)$1; + } +} + +%typemap(varout) char +{ + zval **z_var; + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if($1 != *((*z_var)->value.str.val)) { + char c[2]; + efree((*z_var)->value.str.val); + c[0] = $1; + c[1] = 0; + (*z_var)->value.str.val = estrdup(c); + } +} + +%typemap(varout) char * +{ + zval **z_var; + char *s1; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + s1 = Z_STRVAL_PP(z_var); + if((s1 == NULL) || ($1 == NULL) || strcmp(s1, $1)) { + if(s1) + efree(s1); + if($1) { + (*z_var)->value.str.val = estrdup($1); + (*z_var)->value.str.len = strlen($1) + 1; + } else { + (*z_var)->value.str.val = 0; + (*z_var)->value.str.len = 0; + } + } +} + +%typemap(varout) SWIGTYPE +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + SWIG_SetPointerZval(*z_var, (void*)&$1, $&1_descriptor, 0); +} + +%typemap(varout) SWIGTYPE [] +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + if($1) + SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); +} + +%typemap(varout) char [ANY] +{ + zval **z_var; + char *s1; +deliberate error cos this code looks bogus to me + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + s1 = Z_STRVAL_PP(z_var); + if((s1 == NULL) || strcmp(s1, $1)) { + if($1) { + (*z_var)->value.str.val = estrdup($1); + (*z_var)->value.str.len = strlen($1) + 1; + } else { + (*z_var)->value.str.val = 0; + (*z_var)->value.str.len = 0; + } + } +} + +%typemap(varout) SWIGTYPE *, SWIGTYPE &, SWIGTYPE && +{ + zval **z_var; + + zend_hash_find(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void**)&z_var); + SWIG_SetPointerZval(*z_var, (void*)$1, $1_descriptor, 0); +} + +%typemap(varout, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +{ + void * p = emalloc(sizeof($1)); + memcpy(p, &$1, sizeof($1)); + zval * resource; + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, p, swig_member_ptr); + zend_hash_add(&EG(symbol_table), (char*)"$1", sizeof("$1"), (void*)&resource, sizeof(zval *), NULL); +} diff --git a/Lib/php5/php.swg b/Lib/php5/php.swg new file mode 100644 index 000000000..535c7d347 --- /dev/null +++ b/Lib/php5/php.swg @@ -0,0 +1,529 @@ +/* ----------------------------------------------------------------------------- + * php.swg + * + * PHP configuration file + * ----------------------------------------------------------------------------- */ + +%runtime "swigrun.swg" // Common C API type-checking code +%runtime "phprun.swg" // PHP runtime functions + +%include // PHP initialization routine. + +%include // Global variables. +%include + +// use %init %{ "/*code goes here*/ " %} +// or %minit %{ "/* code goes here*/ " %} to +// insert code in the PHP_MINIT_FUNCTION +#define %minit %insert("init") + +// use %rinit %{ "/* code goes here*/ " %} to +// insert code in the PHP_RINIT_FUNCTION +#define %rinit %insert("rinit") + +// use %shutdown %{ " /*code goes here*/ " %} to +// insert code in the PHP_MSHUTDOWN_FUNCTION +#define %shutdown %insert("shutdown") +#define %mshutdown %insert("shutdown") + +// use %rshutdown %{ " /*code goes here*/" %} to +// insert code in the PHP_RSHUTDOWN_FUNCTION +#define %rshutdown %insert("rshutdown") + +/* Typemaps for input parameters by value */ + +%include + +%pass_by_val(bool,CONVERT_BOOL_IN); + +%pass_by_val(size_t, CONVERT_INT_IN); + +%pass_by_val(enum SWIGTYPE, CONVERT_INT_IN); + +%pass_by_val(signed int, CONVERT_INT_IN); +%pass_by_val(int,CONVERT_INT_IN); +%pass_by_val(unsigned int,CONVERT_INT_IN); + +%pass_by_val(signed short, CONVERT_INT_IN); +%pass_by_val(short,CONVERT_INT_IN); +%pass_by_val(unsigned short, CONVERT_INT_IN); + +%pass_by_val(signed long, CONVERT_INT_IN); +%pass_by_val(long, CONVERT_INT_IN); +%pass_by_val(unsigned long, CONVERT_INT_IN); + +%pass_by_val(signed long long, CONVERT_LONG_LONG_IN); +%pass_by_val(long long, CONVERT_LONG_LONG_IN); +%pass_by_val(unsigned long long, CONVERT_UNSIGNED_LONG_LONG_IN); + +%pass_by_val(signed char, CONVERT_INT_IN); +%pass_by_val(char, CONVERT_CHAR_IN); +%pass_by_val(unsigned char, CONVERT_INT_IN); + +%pass_by_val(float, CONVERT_FLOAT_IN); + +%pass_by_val(double, CONVERT_FLOAT_IN); + +%pass_by_val(char *, CONVERT_STRING_IN); +%typemap(in) char *& = const char *&; +%typemap(directorout) char *& = const char *&; + +// char array can be in/out, though the passed string may not be big enough... +// so we have to size it +%typemap(in) char[ANY] +{ + convert_to_string_ex($input); + $1 = ($1_ltype) Z_STRVAL_PP($input); +} + +%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) { + convert_to_string_ex($input); + $1 = ($1_ltype) Z_STRVAL_PP($input); + $2 = ($2_ltype) Z_STRLEN_PP($input); +} + +/* Object passed by value. Convert to a pointer */ +%typemap(in) SWIGTYPE ($&1_ltype tmp) +{ + if(SWIG_ConvertPtr(*$input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + } + $1 = *tmp; +} + +%typemap(directorout) SWIGTYPE ($&1_ltype tmp) +{ + /* If exit was via exception, PHP NULL is returned so skip the conversion. */ + if (!EG(exception)) { + if(SWIG_ConvertPtr($input, (void **) &tmp, $&1_descriptor, 0) < 0 || tmp == NULL) + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + $result = *tmp; + } +} + +%typemap(in) SWIGTYPE *, + SWIGTYPE [] +{ + if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + } +} + +%typemap(in) SWIGTYPE & +{ + if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + } +} + +%typemap(in) SWIGTYPE && +{ + if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0 || $1 == NULL) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $1_descriptor"); + } +} + +%typemap(in) SWIGTYPE *const& ($*ltype temp) +{ + if(SWIG_ConvertPtr(*$input, (void **) &temp, $*1_descriptor, 0) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $*1_descriptor"); + } + $1 = ($1_ltype)&temp; +} + +%typemap(in) SWIGTYPE *DISOWN +{ + if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, SWIG_POINTER_DISOWN ) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + } +} + +%typemap(argout) SWIGTYPE *, + SWIGTYPE [], + SWIGTYPE &, + SWIGTYPE &&; + +%typemap(in) void * +{ + if(SWIG_ConvertPtr(*$input, (void **) &$1, 0, 0) < 0) { + /* Allow NULL from php for void* */ + if ((*$input)->type==IS_NULL) $1=0; + else + SWIG_PHP_Error(E_ERROR, "Type error in argument $argnum of $symname. Expected $&1_descriptor"); + } +} + +/* Special case when void* is passed by reference so it can be made to point + to opaque api structs */ +%typemap(in) void ** ($*1_ltype ptr, int force), + void *& ($*1_ltype ptr, int force) +{ + /* If they pass NULL by reference, make it into a void* + This bit should go in arginit if arginit support init-ing scripting args */ + if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ + if (!((*$input)->type==IS_NULL && PZVAL_IS_REF(*$input))) { + /* wasn't a pre/ref/thing, OR anything like an int thing */ + SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); + } + } + force=0; + if (arg1==NULL) { +#ifdef __cplusplus + ptr=new $*1_ltype(); +#else + ptr=($*1_ltype) calloc(1,sizeof($*1_ltype)); +#endif + $1=&ptr; + /* have to passback arg$arg too */ + force=1; + } +} +%typemap(argout) void **, + void *& +{ + if (force$argnum) { + SWIG_SetPointerZval( *$input, (void*) ptr$argnum, $*1_descriptor, 1); + } +} + +/* Typemap for output values */ + +%typemap(out) int, + unsigned int, + short, + unsigned short, + long, + unsigned long, + signed char, + unsigned char, + bool, + size_t +{ + ZVAL_LONG(return_value,$1); +} + +%typemap(out) enum SWIGTYPE +{ + ZVAL_LONG(return_value, (long)$1); +} + +%typemap(out) long long +%{ + if ((long long)LONG_MIN <= $1 && $1 <= (long long)LONG_MAX) { + return_value->value.lval = (long)($1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", (long long)$1); + ZVAL_STRING(return_value, temp, 1); + } +%} +%typemap(out) unsigned long long +%{ + if ($1 <= (unsigned long long)LONG_MAX) { + return_value->value.lval = (long)($1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", (unsigned long long)$1); + ZVAL_STRING(return_value, temp, 1); + } +%} + +%typemap(out) const int &, + const unsigned int &, + const short &, + const unsigned short &, + const long &, + const unsigned long &, + const signed char &, + const unsigned char &, + const bool &, + const size_t & +{ + ZVAL_LONG(return_value,*$1); +} + +%typemap(out) const enum SWIGTYPE & +{ + ZVAL_LONG(return_value, (long)*$1); +} + +%typemap(out) const enum SWIGTYPE && +{ + ZVAL_LONG(return_value, (long)*$1); +} + +%typemap(out) const long long & +%{ + if ((long long)LONG_MIN <= *$1 && *$1 <= (long long)LONG_MAX) { + return_value->value.lval = (long)(*$1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", (long long)(*$1)); + ZVAL_STRING(return_value, temp, 1); + } +%} +%typemap(out) const unsigned long long & +%{ + if (*$1 <= (unsigned long long)LONG_MAX) { + return_value->value.lval = (long)(*$1); + return_value->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", (unsigned long long)(*$1)); + ZVAL_STRING(return_value, temp, 1); + } +%} + +%typemap(directorin) int, + unsigned int, + short, + unsigned short, + long, + unsigned long, + signed char, + unsigned char, + size_t, + enum SWIGTYPE +{ + ZVAL_LONG($input,$1); +} + +%typemap(directorin) enum SWIGTYPE +{ + ZVAL_LONG($input, (long)$1_name); +} + +%typemap(directorin) char *, char [] +{ + if(!$1) { + ZVAL_NULL($input); + } else { + ZVAL_STRING($input, (char *)$1, 1); + } +} + +%typemap(out) bool +{ + ZVAL_BOOL(return_value,($1)?1:0); +} + +%typemap(out) const bool & +{ + ZVAL_BOOL(return_value,(*$1)?1:0); +} + +%typemap(directorin) bool +{ + ZVAL_BOOL($input,($1)?1:0); +} + +%typemap(out) float, + double +{ + ZVAL_DOUBLE(return_value,$1); +} + +%typemap(out) const float &, + const double & +{ + ZVAL_DOUBLE(return_value,*$1); +} + +%typemap(directorin) float, + double +{ + ZVAL_DOUBLE($input,$1); +} + +%typemap(out) char +{ + ZVAL_STRINGL(return_value,&$1, 1, 1); +} + +%typemap(out) const char & +{ + ZVAL_STRINGL(return_value,&*$1, 1, 1); +} + +%typemap(out) char *, + char [] +{ + if(!$1) { + ZVAL_NULL(return_value); + } else { + ZVAL_STRING(return_value, (char *)$1, 1); + } +} + +%typemap(out) char *& +{ + if(!*$1) { + ZVAL_NULL(return_value); + } else { + ZVAL_STRING(return_value, (char *)*$1, 1); + } +} + +%typemap(out) SWIGTYPE *, + SWIGTYPE [], + SWIGTYPE &, + SWIGTYPE && +%{ + SWIG_SetPointerZval(return_value, (void *)$1, $1_descriptor, $owner); +%} + +%typemap(out) SWIGTYPE *const& +%{ + SWIG_SetPointerZval(return_value, (void *)*$1, $*1_descriptor, $owner); +%} + +%typemap(directorin) SWIGTYPE *, + SWIGTYPE [], + SWIGTYPE &, + SWIGTYPE && +%{ + SWIG_SetPointerZval($input, (void *)&$1, $1_descriptor, ($owner)|2); +%} + +%typemap(out, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +{ + void * p = emalloc(sizeof($1)); + memcpy(p, &$1, sizeof($1)); + ZEND_REGISTER_RESOURCE(return_value, p, swig_member_ptr); +} + +%typemap(in, fragment="swig_php_init_member_ptr") SWIGTYPE (CLASS::*) +{ + void * p = (void*)zend_fetch_resource($input TSRMLS_CC, -1, SWIG_MEMBER_PTR, NULL, 1, swig_member_ptr); + memcpy(&$1, p, sizeof($1)); +} + +%typemap(out) SWIGTYPE *DYNAMIC, + SWIGTYPE &DYNAMIC +{ + swig_type_info *ty = SWIG_TypeDynamicCast($1_descriptor, (void **) &$1); + SWIG_SetPointerZval(return_value, (void *)$1, ty, $owner); +} + +%typemap(out) SWIGTYPE +#ifdef __cplusplus +{ + $&1_ltype resultobj = new $1_ltype((const $1_ltype &) $1); + SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1); +} +#else +{ + $&1_ltype resultobj = ($&1_ltype) emalloc(sizeof($1_type)); + memcpy(resultobj, &$1, sizeof($1_type)); + SWIG_SetPointerZval(return_value, (void *)resultobj, $&1_descriptor, 1); +} +#endif + +%typemap(directorin) SWIGTYPE +{ + SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1|2); +} + +%typemap(out) void ""; + +%typemap(out) char [ANY] +{ + int len = 0; + while (len < $1_dim0 && $1[len]) ++len; + RETVAL_STRINGL($1, len, 1); +} + +// This typecheck does hard checking for proper argument type. If you want +// an argument to be converted from a different PHP type, you must convert +// it yourself before passing it (e.g. (string)4.7 or (int)"6"). +%define %php_typecheck(_type,_prec,is) +%typemap(typecheck,precedence=_prec) _type, const _type & + " $1 = (Z_TYPE_PP($input) == is); " +%enddef + +%php_typecheck(int,SWIG_TYPECHECK_INTEGER,IS_LONG) +%php_typecheck(unsigned int,SWIG_TYPECHECK_UINT32,IS_LONG) +%php_typecheck(short,SWIG_TYPECHECK_INT16,IS_LONG) +%php_typecheck(unsigned short,SWIG_TYPECHECK_UINT16,IS_LONG) +%php_typecheck(long,SWIG_TYPECHECK_INT32,IS_LONG) +%php_typecheck(unsigned long,SWIG_TYPECHECK_UINT32,IS_LONG) +%php_typecheck(long long,SWIG_TYPECHECK_INT64,IS_LONG) +%php_typecheck(unsigned long long,SWIG_TYPECHECK_UINT64,IS_LONG) +%php_typecheck(signed char,SWIG_TYPECHECK_INT8,IS_LONG) +%php_typecheck(unsigned char,SWIG_TYPECHECK_UINT8,IS_LONG) +%php_typecheck(size_t,SWIG_TYPECHECK_SIZE,IS_LONG) +%php_typecheck(enum SWIGTYPE,SWIG_TYPECHECK_INTEGER,IS_LONG) +%php_typecheck(bool,SWIG_TYPECHECK_BOOL,IS_BOOL) +%php_typecheck(float,SWIG_TYPECHECK_FLOAT,IS_DOUBLE) +%php_typecheck(double,SWIG_TYPECHECK_DOUBLE,IS_DOUBLE) +%php_typecheck(char,SWIG_TYPECHECK_CHAR,IS_STRING) + +%typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) char *, char *&, char [] + " $1 = (Z_TYPE_PP($input) == IS_STRING); " + +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE +{ + void *tmp; + _v = (SWIG_ConvertPtr(*$input, (void **)&tmp, $&1_descriptor, 0) >= 0); +} + +%typecheck(SWIG_TYPECHECK_POINTER) + SWIGTYPE *, + SWIGTYPE [], + SWIGTYPE &, + SWIGTYPE &&, + SWIGTYPE *const& +{ + void *tmp; + _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $1_descriptor, 0) >= 0); +} + +%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE *const& +{ + void *tmp; + _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, $*1_descriptor, 0) >= 0); +} + +%typecheck(SWIG_TYPECHECK_VOIDPTR) void * +{ + void *tmp; + _v = (SWIG_ConvertPtr(*$input, (void**)&tmp, 0, 0) >= 0); +} + +/* Exception handling */ + +%typemap(throws) int, + long, + short, + unsigned int, + unsigned long, + unsigned short { + zend_throw_exception(NULL, const_cast("C++ $1_type exception thrown"), $1 TSRMLS_CC); + return; +} + +%typemap(throws) SWIGTYPE, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE *, SWIGTYPE [], SWIGTYPE [ANY] %{ + (void)$1; + zend_throw_exception(NULL, const_cast("C++ $1_type exception thrown"), 0 TSRMLS_CC); + return; +%} + +%typemap(throws) char * %{ + zend_throw_exception(NULL, const_cast($1), 0 TSRMLS_CC); + return; +%} + +/* Array reference typemaps */ +%apply SWIGTYPE & { SWIGTYPE ((&)[ANY]) } +%apply SWIGTYPE && { SWIGTYPE ((&&)[ANY]) } + +/* const pointers */ +%apply SWIGTYPE * { SWIGTYPE *const } + + +/* php keywords */ +%include diff --git a/Lib/php5/phpinit.swg b/Lib/php5/phpinit.swg new file mode 100644 index 000000000..6e5cc29d2 --- /dev/null +++ b/Lib/php5/phpinit.swg @@ -0,0 +1,25 @@ + +/* ------------------------------------------------------------ + * The start of the PHP initialization function + * ------------------------------------------------------------ */ + +%insert(init) "swiginit.swg" + +%init %{ + SWIG_php_minit { + SWIG_InitializeModule(0); +%} + +%fragment("swig_php_init_member_ptr2", "header") { +#define SWIG_MEMBER_PTR ((char*)"CLASS::*") + +static void swig_member_ptr_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { + efree(rsrc->ptr); +} + +static int swig_member_ptr = 0; +} + +%fragment("swig_php_init_member_ptr", "init", fragment="swig_php_init_member_ptr2") { + swig_member_ptr = zend_register_list_destructors_ex(swig_member_ptr_dtor, NULL, SWIG_MEMBER_PTR, module_number); +} diff --git a/Lib/php5/phpkw.swg b/Lib/php5/phpkw.swg new file mode 100644 index 000000000..36e535f52 --- /dev/null +++ b/Lib/php5/phpkw.swg @@ -0,0 +1,866 @@ +/* ----------------------------------------------------------------------------- + * phpkw.swg + * ----------------------------------------------------------------------------- */ + +/* Keyword (case insensitive) */ +#define PHPKW(x) %keywordwarn("'" `x` "' is a PHP keyword, renaming to 'c_" `x` "'",sourcefmt="%(lower)s",rename="c_%s") `x` + +/* Class (case insensitive) */ +#define PHPCN(x) %keywordwarn("'" `x` "' is a PHP reserved class name, renaming to 'c_" `x` "'",%$isclass,sourcefmt="%(lower)s",rename="c_%s") `x` + +/* Constant (case insensitive) */ +#define PHPBN1a(x) %namewarn(%warningmsg(SWIGWARN_PARSE_BUILTIN_NAME, "enum conflicts with a built-in constant '"`x`"' in PHP"),%$isenumitem,sourcefmt="%(lower)s") `x` +#define PHPBN1b(x) %namewarn(%warningmsg(SWIGWARN_PARSE_BUILTIN_NAME, "constant conflicts with a built-in constant '"`x`"' in PHP"),%$isconstant,sourcefmt="%(lower)s") `x` +%define PHPBN1(X) + PHPBN1a(X); PHPBN1b(X) +%enddef + +/* Constant (case sensitive) */ +#define PHPBN2a(x) %namewarn(%warningmsg(SWIGWARN_PARSE_BUILTIN_NAME, "enum conflicts with a built-in constant '"`x`"' in PHP"),%$isenumitem) `x` +#define PHPBN2b(x) %namewarn(%warningmsg(SWIGWARN_PARSE_BUILTIN_NAME, "constant conflicts with a built-in constant '"`x`"' in PHP"),%$isconstant) `x` +%define PHPBN2(X) + PHPBN2a(X); PHPBN2b(X) +%enddef + +#define PHPFN(x) %keywordwarn("'" `x` "' is a PHP built-in function, renaming to 'c_" `x` "'",sourcefmt="%(lower)s",%$isfunction,%$not %$ismember,rename="c_%s") `x` + +/* From: http://php.net/manual/en/reserved.keywords.php + * "You cannot use any of the following words as constants, class names, + * function or method names. Using them as variable names is generally OK, but + * could lead to confusion." + */ +/* Check is case insensitive - these *MUST* be listed in lower case here */ +PHPKW(__halt_compiler); +PHPKW(abstract); +PHPKW(and); +PHPKW(array); +PHPKW(as); +PHPKW(break); +PHPKW(callable); // As of PHP 5.4 +PHPKW(case); +PHPKW(catch); +PHPKW(class); +PHPKW(clone); +PHPKW(const); +PHPKW(continue); +PHPKW(declare); +PHPKW(default); +PHPKW(die); // "Language construct" +PHPKW(do); +PHPKW(echo); // "Language construct" +PHPKW(else); +PHPKW(elseif); +PHPKW(empty); // "Language construct" +PHPKW(enddeclare); +PHPKW(endfor); +PHPKW(endforeach); +PHPKW(endif); +PHPKW(endswitch); +PHPKW(endwhile); +PHPKW(eval); // "Language construct" +PHPKW(exit); // "Language construct" +PHPKW(extends); +PHPKW(final); +PHPKW(finally); // As of PHP 5.5 +PHPKW(for); +PHPKW(foreach); +PHPKW(function); +PHPKW(global); +PHPKW(goto); // As of PHP 5.3 +PHPKW(if); +PHPKW(implements); +PHPKW(include); // "Language construct" +PHPKW(include_once); // "Language construct" +PHPKW(instanceof); +PHPKW(insteadof); // As of PHP 5.4 +PHPKW(interface); +PHPKW(isset); // "Language construct" +PHPKW(list); // "Language construct" +PHPKW(namespace); // As of PHP 5.3 +PHPKW(new); +PHPKW(or); +PHPKW(print); // "Language construct" +PHPKW(private); +PHPKW(protected); +PHPKW(public); +PHPKW(require); // "Language construct" +PHPKW(require_once); // "Language construct" +PHPKW(return); // "Language construct" +PHPKW(static); +PHPKW(switch); +PHPKW(throw); +PHPKW(trait); // As of PHP 5.4 +PHPKW(try); +PHPKW(unset); // "Language construct" +PHPKW(use); +PHPKW(var); +PHPKW(while); +PHPKW(xor); +PHPKW(yield); // As of PHP 5.5 + +// Compile-time "magic" constants +// From: http://php.net/manual/en/reserved.keywords.php +// also at: http://php.net/manual/en/language.constants.predefined.php +/* These *MUST* be listed in lower case here */ +PHPKW(__class__); +PHPKW(__dir__); // As of PHP 5.3 +PHPKW(__file__); +PHPKW(__function__); +PHPKW(__line__); +PHPKW(__method__); +PHPKW(__namespace__); // As of PHP 5.3 +PHPKW(__trait__); // As of PHP 5.4 + +/* We classify these as built-in names since they conflict, but PHP still runs */ + +/* Predefined case-insensitive constants */ +/* These *MUST* be listed in lower case here */ +PHPBN1(null); +PHPBN1(true); +PHPBN1(false); + +/* "Core Predefined Constants" from http://php.net/manual/en/reserved.constants.php */ +/* These are case sensitive */ +PHPBN2(PHP_VERSION); +PHPBN2(PHP_MAJOR_VERSION); // As of PHP 5.2.7 +PHPBN2(PHP_MINOR_VERSION); // As of PHP 5.2.7 +PHPBN2(PHP_RELEASE_VERSION); // As of PHP 5.2.7 +PHPBN2(PHP_VERSION_ID); // As of PHP 5.2.7 +PHPBN2(PHP_EXTRA_VERSION); // As of PHP 5.2.7 +PHPBN2(PHP_ZTS); // As of PHP 5.2.7 +PHPBN2(PHP_DEBUG); // As of PHP 5.2.7 +PHPBN2(PHP_MAXPATHLEN); // As of PHP 5.3.0 +PHPBN2(PHP_OS); +PHPBN2(PHP_SAPI); +PHPBN2(PHP_EOL); // As of PHP 5.0.2 +PHPBN2(PHP_INT_MAX); // As of PHP 5.0.5 +PHPBN2(PHP_INT_SIZE); // As of PHP 5.0.5 +PHPBN2(DEFAULT_INCLUDE_PATH); +PHPBN2(PEAR_INSTALL_DIR); +PHPBN2(PEAR_EXTENSION_DIR); +PHPBN2(PHP_EXTENSION_DIR); +PHPBN2(PHP_PREFIX); +PHPBN2(PHP_BINDIR); +PHPBN2(PHP_BINARY); // As of PHP 5.4 +PHPBN2(PHP_MANDIR); // As of PHP 5.3.7 +PHPBN2(PHP_LIBDIR); +PHPBN2(PHP_DATADIR); +PHPBN2(PHP_SYSCONFDIR); +PHPBN2(PHP_LOCALSTATEDIR); +PHPBN2(PHP_CONFIG_FILE_PATH); +PHPBN2(PHP_CONFIG_FILE_SCAN_DIR); +PHPBN2(PHP_SHLIB_SUFFIX); +PHPBN2(E_ERROR); +PHPBN2(E_WARNING); +PHPBN2(E_PARSE); +PHPBN2(E_NOTICE); +PHPBN2(E_CORE_ERROR); +PHPBN2(E_CORE_WARNING); +PHPBN2(E_COMPILE_ERROR); +PHPBN2(E_COMPILE_WARNING); +PHPBN2(E_USER_ERROR); +PHPBN2(E_USER_WARNING); +PHPBN2(E_USER_NOTICE); +PHPBN2(E_DEPRECATED); // As of PHP 5.3.0 +PHPBN2(E_USER_DEPRECATED); // As of PHP 5.3.0 +PHPBN2(E_ALL); +PHPBN2(E_STRICT); +PHPBN2(__COMPILER_HALT_OFFSET__); // As of PHP 5.1.0 +// TRUE, FALSE, NULL are listed on the same page, but are actually +// case-insensitive, whereas all the other constants listed there seem to be +// case-sensitive, so we handle TRUE, FALSE, NULL in PHPBN1. +PHPBN2(PHP_OUTPUT_HANDLER_START); +PHPBN2(PHP_OUTPUT_HANDLER_CONT); +PHPBN2(PHP_OUTPUT_HANDLER_END); +/* These don't actually seem to be set (tested on Linux, I guess they're + * Windows only?) */ +PHPBN2(PHP_WINDOWS_NT_DOMAIN_CONTROLLER); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_NT_SERVER); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_NT_WORKSTATION); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_BUILD); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_MAJOR); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_MINOR); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_PLATFORM); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_PRODUCTTYPE); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_SP_MAJOR); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_SP_MINOR); // As of PHP 5.3 +PHPBN2(PHP_WINDOWS_VERSION_SUITEMASK); // As of PHP 5.3 +/* "Standard Predefined Constants" from http://php.net/manual/en/reserved.constants.php */ +PHPBN2(EXTR_OVERWRITE); +PHPBN2(EXTR_SKIP); +PHPBN2(EXTR_PREFIX_SAME); +PHPBN2(EXTR_PREFIX_ALL); +PHPBN2(EXTR_PREFIX_INVALID); +PHPBN2(EXTR_PREFIX_IF_EXISTS); +PHPBN2(EXTR_IF_EXISTS); +PHPBN2(SORT_ASC); +PHPBN2(SORT_DESC); +PHPBN2(SORT_REGULAR); +PHPBN2(SORT_NUMERIC); +PHPBN2(SORT_STRING); +PHPBN2(CASE_LOWER); +PHPBN2(CASE_UPPER); +PHPBN2(COUNT_NORMAL); +PHPBN2(COUNT_RECURSIVE); +PHPBN2(ASSERT_ACTIVE); +PHPBN2(ASSERT_CALLBACK); +PHPBN2(ASSERT_BAIL); +PHPBN2(ASSERT_WARNING); +PHPBN2(ASSERT_QUIET_EVAL); +PHPBN2(CONNECTION_ABORTED); +PHPBN2(CONNECTION_NORMAL); +PHPBN2(CONNECTION_TIMEOUT); +PHPBN2(INI_USER); +PHPBN2(INI_PERDIR); +PHPBN2(INI_SYSTEM); +PHPBN2(INI_ALL); +PHPBN2(INI_SCANNER_NORMAL); // As of PHP 5.3 +PHPBN2(INI_SCANNER_RAW); // As of PHP 5.3 +PHPBN2(M_E); +PHPBN2(M_LOG2E); +PHPBN2(M_LOG10E); +PHPBN2(M_LN2); +PHPBN2(M_LN10); +PHPBN2(M_PI); +PHPBN2(M_PI_2); +PHPBN2(M_PI_4); +PHPBN2(M_1_PI); +PHPBN2(M_2_PI); +PHPBN2(M_2_SQRTPI); +PHPBN2(M_SQRT2); +PHPBN2(M_SQRT1_2); +PHPBN2(M_EULER); // As of PHP 5.2 +PHPBN2(M_LNPI); // As of PHP 5.2 +PHPBN2(M_SQRT3); // As of PHP 5.2 +PHPBN2(M_SQRTPI); // As of PHP 5.2 +PHPBN2(CRYPT_SALT_LENGTH); +PHPBN2(CRYPT_STD_DES); +PHPBN2(CRYPT_EXT_DES); +PHPBN2(CRYPT_MD5); +PHPBN2(CRYPT_BLOWFISH); +PHPBN2(DIRECTORY_SEPARATOR); +PHPBN2(SEEK_SET); +PHPBN2(SEEK_CUR); +PHPBN2(SEEK_END); +PHPBN2(LOCK_SH); +PHPBN2(LOCK_EX); +PHPBN2(LOCK_UN); +PHPBN2(LOCK_NB); +PHPBN2(HTML_SPECIALCHARS); +PHPBN2(HTML_ENTITIES); +PHPBN2(ENT_COMPAT); +PHPBN2(ENT_QUOTES); +PHPBN2(ENT_NOQUOTES); +PHPBN2(INFO_GENERAL); +PHPBN2(INFO_CREDITS); +PHPBN2(INFO_CONFIGURATION); +PHPBN2(INFO_MODULES); +PHPBN2(INFO_ENVIRONMENT); +PHPBN2(INFO_VARIABLES); +PHPBN2(INFO_LICENSE); +PHPBN2(INFO_ALL); +PHPBN2(CREDITS_GROUP); +PHPBN2(CREDITS_GENERAL); +PHPBN2(CREDITS_SAPI); +PHPBN2(CREDITS_MODULES); +PHPBN2(CREDITS_DOCS); +PHPBN2(CREDITS_FULLPAGE); +PHPBN2(CREDITS_QA); +PHPBN2(CREDITS_ALL); +PHPBN2(STR_PAD_LEFT); +PHPBN2(STR_PAD_RIGHT); +PHPBN2(STR_PAD_BOTH); +PHPBN2(PATHINFO_DIRNAME); +PHPBN2(PATHINFO_BASENAME); +PHPBN2(PATHINFO_EXTENSION); +PHPBN2(PATHINFO_FILENAME); // As of PHP 5.2 +PHPBN2(PATH_SEPARATOR); +PHPBN2(CHAR_MAX); +PHPBN2(LC_CTYPE); +PHPBN2(LC_NUMERIC); +PHPBN2(LC_TIME); +PHPBN2(LC_COLLATE); +PHPBN2(LC_MONETARY); +PHPBN2(LC_ALL); +PHPBN2(LC_MESSAGES); +PHPBN2(ABDAY_1); +PHPBN2(ABDAY_2); +PHPBN2(ABDAY_3); +PHPBN2(ABDAY_4); +PHPBN2(ABDAY_5); +PHPBN2(ABDAY_6); +PHPBN2(ABDAY_7); +PHPBN2(DAY_1); +PHPBN2(DAY_2); +PHPBN2(DAY_3); +PHPBN2(DAY_4); +PHPBN2(DAY_5); +PHPBN2(DAY_6); +PHPBN2(DAY_7); +PHPBN2(ABMON_1); +PHPBN2(ABMON_2); +PHPBN2(ABMON_3); +PHPBN2(ABMON_4); +PHPBN2(ABMON_5); +PHPBN2(ABMON_6); +PHPBN2(ABMON_7); +PHPBN2(ABMON_8); +PHPBN2(ABMON_9); +PHPBN2(ABMON_10); +PHPBN2(ABMON_11); +PHPBN2(ABMON_12); +PHPBN2(MON_1); +PHPBN2(MON_2); +PHPBN2(MON_3); +PHPBN2(MON_4); +PHPBN2(MON_5); +PHPBN2(MON_6); +PHPBN2(MON_7); +PHPBN2(MON_8); +PHPBN2(MON_9); +PHPBN2(MON_10); +PHPBN2(MON_11); +PHPBN2(MON_12); +PHPBN2(AM_STR); +PHPBN2(PM_STR); +PHPBN2(D_T_FMT); +PHPBN2(D_FMT); +PHPBN2(T_FMT); +PHPBN2(T_FMT_AMPM); +PHPBN2(ERA); +PHPBN2(ERA_YEAR); +PHPBN2(ERA_D_T_FMT); +PHPBN2(ERA_D_FMT); +PHPBN2(ERA_T_FMT); +PHPBN2(ALT_DIGITS); +PHPBN2(INT_CURR_SYMBOL); +PHPBN2(CURRENCY_SYMBOL); +PHPBN2(CRNCYSTR); +PHPBN2(MON_DECIMAL_POINT); +PHPBN2(MON_THOUSANDS_SEP); +PHPBN2(MON_GROUPING); +PHPBN2(POSITIVE_SIGN); +PHPBN2(NEGATIVE_SIGN); +PHPBN2(INT_FRAC_DIGITS); +PHPBN2(FRAC_DIGITS); +PHPBN2(P_CS_PRECEDES); +PHPBN2(P_SEP_BY_SPACE); +PHPBN2(N_CS_PRECEDES); +PHPBN2(N_SEP_BY_SPACE); +PHPBN2(P_SIGN_POSN); +PHPBN2(N_SIGN_POSN); +PHPBN2(DECIMAL_POINT); +PHPBN2(RADIXCHAR); +PHPBN2(THOUSANDS_SEP); +PHPBN2(THOUSEP); +PHPBN2(GROUPING); +PHPBN2(YESEXPR); +PHPBN2(NOEXPR); +PHPBN2(YESSTR); +PHPBN2(NOSTR); +PHPBN2(CODESET); +PHPBN2(LOG_EMERG); +PHPBN2(LOG_ALERT); +PHPBN2(LOG_CRIT); +PHPBN2(LOG_ERR); +PHPBN2(LOG_WARNING); +PHPBN2(LOG_NOTICE); +PHPBN2(LOG_INFO); +PHPBN2(LOG_DEBUG); +PHPBN2(LOG_KERN); +PHPBN2(LOG_USER); +PHPBN2(LOG_MAIL); +PHPBN2(LOG_DAEMON); +PHPBN2(LOG_AUTH); +PHPBN2(LOG_SYSLOG); +PHPBN2(LOG_LPR); +PHPBN2(LOG_NEWS); +PHPBN2(LOG_UUCP); +PHPBN2(LOG_CRON); +PHPBN2(LOG_AUTHPRIV); +PHPBN2(LOG_LOCAL0); +PHPBN2(LOG_LOCAL1); +PHPBN2(LOG_LOCAL2); +PHPBN2(LOG_LOCAL3); +PHPBN2(LOG_LOCAL4); +PHPBN2(LOG_LOCAL5); +PHPBN2(LOG_LOCAL6); +PHPBN2(LOG_LOCAL7); +PHPBN2(LOG_PID); +PHPBN2(LOG_CONS); +PHPBN2(LOG_ODELAY); +PHPBN2(LOG_NDELAY); +PHPBN2(LOG_NOWAIT); +PHPBN2(LOG_PERROR); + +/* Added in PHP 5.2 */ +PHPBN2(PREG_BACKTRACK_LIMIT_ERROR); +PHPBN2(PREG_BAD_UTF8_ERROR); +PHPBN2(PREG_INTERNAL_ERROR); +PHPBN2(PREG_NO_ERROR); +PHPBN2(PREG_RECURSION_LIMIT_ERROR); +PHPBN2(UPLOAD_ERR_EXTENSION); +PHPBN2(STREAM_SHUT_RD); +PHPBN2(STREAM_SHUT_WR); +PHPBN2(STREAM_SHUT_RDWR); +PHPBN2(CURLE_FILESIZE_EXCEEDED); +PHPBN2(CURLE_FTP_SSL_FAILED); +PHPBN2(CURLE_LDAP_INVALID_URL); +PHPBN2(CURLFTPAUTH_DEFAULT); +PHPBN2(CURLFTPAUTH_SSL); +PHPBN2(CURLFTPAUTH_TLS); +PHPBN2(CURLFTPSSL_ALL); +PHPBN2(CURLFTPSSL_CONTROL); +PHPBN2(CURLFTPSSL_NONE); +PHPBN2(CURLFTPSSL_TRY); +PHPBN2(CURLOPT_FTP_SSL); +PHPBN2(CURLOPT_FTPSSLAUTH); +PHPBN2(CURLOPT_TCP_NODELAY); // Added in PHP 5.2.1 +PHPBN2(CURLOPT_TIMEOUT_MS); // Added in PHP 5.2.3 +PHPBN2(CURLOPT_CONNECTTIMEOUT_MS); // Added in PHP 5.2.3 +PHPBN2(GMP_VERSION); // Added in PHP 5.2.2 +PHPBN2(SWFTEXTFIELD_USEFONT); +PHPBN2(SWFTEXTFIELD_AUTOSIZE); +PHPBN2(SWF_SOUND_NOT_COMPRESSED); +PHPBN2(SWF_SOUND_ADPCM_COMPRESSED); +PHPBN2(SWF_SOUND_MP3_COMPRESSED); +PHPBN2(SWF_SOUND_NOT_COMPRESSED_LE); +PHPBN2(SWF_SOUND_NELLY_COMPRESSED); +PHPBN2(SWF_SOUND_5KHZ); +PHPBN2(SWF_SOUND_11KHZ); +PHPBN2(SWF_SOUND_22KHZ); +PHPBN2(SWF_SOUND_44KHZ); +PHPBN2(SWF_SOUND_8BITS); +PHPBN2(SWF_SOUND_16BITS); +PHPBN2(SWF_SOUND_MONO); +PHPBN2(SWF_SOUND_STEREO); +PHPBN2(OPENSSL_VERSION_NUMBER); +PHPBN2(SNMP_OID_OUTPUT_FULL); +PHPBN2(SNMP_OID_OUTPUT_NUMERIC); +PHPBN2(MSG_EAGAIN); +PHPBN2(MSG_ENOMSG); + +/* Added in PHP 5.3 */ +PHPBN2(CURLOPT_PROGRESSFUNCTION); +PHPBN2(IMG_FILTER_PIXELATE); +PHPBN2(JSON_ERROR_CTRL_CHAR); +PHPBN2(JSON_ERROR_DEPTH); +PHPBN2(JSON_ERROR_NONE); +PHPBN2(JSON_ERROR_STATE_MISMATCH); +PHPBN2(JSON_ERROR_SYNTAX); +PHPBN2(JSON_FORCE_OBJECT); +PHPBN2(JSON_HEX_TAG); +PHPBN2(JSON_HEX_AMP); +PHPBN2(JSON_HEX_APOS); +PHPBN2(JSON_HEX_QUOT); +PHPBN2(LDAP_OPT_NETWORK_TIMEOUT); +PHPBN2(LIBXML_LOADED_VERSION); +PHPBN2(PREG_BAD_UTF8_OFFSET_ERROR); +PHPBN2(BUS_ADRALN); +PHPBN2(BUS_ADRERR); +PHPBN2(BUS_OBJERR); +PHPBN2(CLD_CONTIUNED); +PHPBN2(CLD_DUMPED); +PHPBN2(CLD_EXITED); +PHPBN2(CLD_KILLED); +PHPBN2(CLD_STOPPED); +PHPBN2(CLD_TRAPPED); +PHPBN2(FPE_FLTDIV); +PHPBN2(FPE_FLTINV); +PHPBN2(FPE_FLTOVF); +PHPBN2(FPE_FLTRES); +PHPBN2(FPE_FLTSUB); +PHPBN2(FPE_FLTUND); +PHPBN2(FPE_INTDIV); +PHPBN2(FPE_INTOVF); +PHPBN2(ILL_BADSTK); +PHPBN2(ILL_COPROC); +PHPBN2(ILL_ILLADR); +PHPBN2(ILL_ILLOPC); +PHPBN2(ILL_ILLOPN); +PHPBN2(ILL_ILLTRP); +PHPBN2(ILL_PRVOPC); +PHPBN2(ILL_PRVREG); +PHPBN2(POLL_ERR); +PHPBN2(POLL_HUP); +PHPBN2(POLL_IN); +PHPBN2(POLL_MSG); +PHPBN2(POLL_OUT); +PHPBN2(POLL_PRI); +PHPBN2(SEGV_ACCERR); +PHPBN2(SEGV_MAPERR); +PHPBN2(SI_ASYNCIO); +PHPBN2(SI_KERNEL); +PHPBN2(SI_MESGQ); +PHPBN2(SI_NOINFO); +PHPBN2(SI_QUEUE); +PHPBN2(SI_SIGIO); +PHPBN2(SI_TIMER); +PHPBN2(SI_TKILL); +PHPBN2(SI_USER); +PHPBN2(SIG_BLOCK); +PHPBN2(SIG_SETMASK); +PHPBN2(SIG_UNBLOCK); +PHPBN2(TRAP_BRKPT); +PHPBN2(TRAP_TRACE); + +/* Added in PHP 5.4 */ +PHPBN2(ENT_DISALLOWED); +PHPBN2(ENT_HTML401); +PHPBN2(ENT_HTML5); +PHPBN2(ENT_SUBSTITUTE); +PHPBN2(ENT_XML1); +PHPBN2(ENT_XHTML); +PHPBN2(IPPROTO_IP); +PHPBN2(IPPROTO_IPV6); +PHPBN2(IPV6_MULTICAST_HOPS); +PHPBN2(IPV6_MULTICAST_IF); +PHPBN2(IPV6_MULTICAST_LOOP); +PHPBN2(IP_MULTICAST_IF); +PHPBN2(IP_MULTICAST_LOOP); +PHPBN2(IP_MULTICAST_TTL); +PHPBN2(MCAST_JOIN_GROUP); +PHPBN2(MCAST_LEAVE_GROUP); +PHPBN2(MCAST_BLOCK_SOURCE); +PHPBN2(MCAST_UNBLOCK_SOURCE); +PHPBN2(MCAST_JOIN_SOURCE_GROUP); +PHPBN2(MCAST_LEAVE_SOURCE_GROUP); +PHPBN2(CURLOPT_MAX_RECV_SPEED_LARGE); +PHPBN2(CURLOPT_MAX_SEND_SPEED_LARGE); +PHPBN2(LIBXML_HTML_NODEFDTD); +PHPBN2(LIBXML_HTML_NOIMPLIED); +PHPBN2(LIBXML_PEDANTIC); +PHPBN2(OPENSSL_CIPHER_AES_128_CBC); +PHPBN2(OPENSSL_CIPHER_AES_192_CBC); +PHPBN2(OPENSSL_CIPHER_AES_256_CBC); +PHPBN2(OPENSSL_RAW_DATA); +PHPBN2(OPENSSL_ZERO_PADDING); +PHPBN2(PHP_OUTPUT_HANDLER_CLEAN); +PHPBN2(PHP_OUTPUT_HANDLER_CLEANABLE); +PHPBN2(PHP_OUTPUT_HANDLER_DISABLED); +PHPBN2(PHP_OUTPUT_HANDLER_FINAL); +PHPBN2(PHP_OUTPUT_HANDLER_FLUSH); +PHPBN2(PHP_OUTPUT_HANDLER_FLUSHABLE); +PHPBN2(PHP_OUTPUT_HANDLER_REMOVABLE); +PHPBN2(PHP_OUTPUT_HANDLER_STARTED); +PHPBN2(PHP_OUTPUT_HANDLER_STDFLAGS); +PHPBN2(PHP_OUTPUT_HANDLER_WRITE); +PHPBN2(PHP_SESSION_ACTIVE); +PHPBN2(PHP_SESSION_DISABLED); +PHPBN2(PHP_SESSION_NONE); +PHPBN2(STREAM_META_ACCESS); +PHPBN2(STREAM_META_GROUP); +PHPBN2(STREAM_META_GROUP_NAME); +PHPBN2(STREAM_META_OWNER); +PHPBN2(STREAM_META_OWNER_NAME); +PHPBN2(STREAM_META_TOUCH); +PHPBN2(ZLIB_ENCODING_DEFLATE); +PHPBN2(ZLIB_ENCODING_GZIP); +PHPBN2(ZLIB_ENCODING_RAW); +PHPBN2(U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR); +PHPBN2(IDNA_CHECK_BIDI); +PHPBN2(IDNA_CHECK_CONTEXTJ); +PHPBN2(IDNA_NONTRANSITIONAL_TO_ASCII); +PHPBN2(IDNA_NONTRANSITIONAL_TO_UNICODE); +PHPBN2(INTL_IDNA_VARIANT_2003); +PHPBN2(INTL_IDNA_VARIANT_UTS46); +PHPBN2(IDNA_ERROR_EMPTY_LABEL); +PHPBN2(IDNA_ERROR_LABEL_TOO_LONG); +PHPBN2(IDNA_ERROR_DOMAIN_NAME_TOO_LONG); +PHPBN2(IDNA_ERROR_LEADING_HYPHEN); +PHPBN2(IDNA_ERROR_TRAILING_HYPHEN); +PHPBN2(IDNA_ERROR_HYPHEN_3_4); +PHPBN2(IDNA_ERROR_LEADING_COMBINING_MARK); +PHPBN2(IDNA_ERROR_DISALLOWED); +PHPBN2(IDNA_ERROR_PUNYCODE); +PHPBN2(IDNA_ERROR_LABEL_HAS_DOT); +PHPBN2(IDNA_ERROR_INVALID_ACE_LABEL); +PHPBN2(IDNA_ERROR_BIDI); +PHPBN2(IDNA_ERROR_CONTEXTJ); +PHPBN2(JSON_PRETTY_PRINT); +PHPBN2(JSON_UNESCAPED_SLASHES); +PHPBN2(JSON_NUMERIC_CHECK); +PHPBN2(JSON_UNESCAPED_UNICODE); +PHPBN2(JSON_BIGINT_AS_STRING); + +/* Added in PHP 5.5 */ +PHPBN2(IMG_AFFINE_TRANSLATE); +PHPBN2(IMG_AFFINE_SCALE); +PHPBN2(IMG_AFFINE_ROTATE); +PHPBN2(IMG_AFFINE_SHEAR_HORIZONTAL); +PHPBN2(IMG_AFFINE_SHEAR_VERTICAL); +PHPBN2(IMG_CROP_DEFAULT); +PHPBN2(IMG_CROP_TRANSPARENT); +PHPBN2(IMG_CROP_BLACK); +PHPBN2(IMG_CROP_WHITE); +PHPBN2(IMG_CROP_SIDES); +PHPBN2(IMG_FLIP_BOTH); +PHPBN2(IMG_FLIP_HORIZONTAL); +PHPBN2(IMG_FLIP_VERTICAL); +PHPBN2(IMG_BELL); +PHPBN2(IMG_BESSEL); +PHPBN2(IMG_BICUBIC); +PHPBN2(IMG_BICUBIC_FIXED); +PHPBN2(IMG_BLACKMAN); +PHPBN2(IMG_BOX); +PHPBN2(IMG_BSPLINE); +PHPBN2(IMG_CATMULLROM); +PHPBN2(IMG_GAUSSIAN); +PHPBN2(IMG_GENERALIZED_CUBIC); +PHPBN2(IMG_HERMITE); +PHPBN2(IMG_HAMMING); +PHPBN2(IMG_HANNING); +PHPBN2(IMG_MITCHELL); +PHPBN2(IMG_POWER); +PHPBN2(IMG_QUADRATIC); +PHPBN2(IMG_SINC); +PHPBN2(IMG_NEAREST_NEIGHBOUR); +PHPBN2(IMG_WEIGHTED4); +PHPBN2(IMG_TRIANGLE); +PHPBN2(JSON_ERROR_RECURSION); +PHPBN2(JSON_ERROR_INF_OR_NAN); +PHPBN2(JSON_ERROR_UNSUPPORTED_TYPE); +PHPBN2(MYSQLI_SERVER_PUBLIC_KEY); + +/* Added in PHP 5.6 */ +PHPBN2(LDAP_ESCAPE_DN); +PHPBN2(LDAP_ESCAPE_FILTER); +PHPBN2(OPENSSL_DEFAULT_STREAM_CIPHERS); +PHPBN2(STREAM_CRYPTO_METHOD_ANY_CLIENT); +PHPBN2(STREAM_CRYPTO_METHOD_ANY_SERVER); +PHPBN2(STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT); +PHPBN2(STREAM_CRYPTO_METHOD_TLSv1_0_SERVER); +PHPBN2(STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT); +PHPBN2(STREAM_CRYPTO_METHOD_TLSv1_1_SERVER); +PHPBN2(STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT); +PHPBN2(STREAM_CRYPTO_METHOD_TLSv1_2_SERVER); +PHPBN2(PGSQL_CONNECT_ASYNC); +PHPBN2(PGSQL_CONNECTION_AUTH_OK); +PHPBN2(PGSQL_CONNECTION_AWAITING_RESPONSE); +PHPBN2(PGSQL_CONNECTION_MADE); +PHPBN2(PGSQL_CONNECTION_SETENV); +PHPBN2(PGSQL_CONNECTION_SSL_STARTUP); +PHPBN2(PGSQL_CONNECTION_STARTED); +PHPBN2(PGSQL_DML_ESCAPE); +PHPBN2(PGSQL_POLLING_ACTIVE); +PHPBN2(PGSQL_POLLING_FAILED); +PHPBN2(PGSQL_POLLING_OK); +PHPBN2(PGSQL_POLLING_READING); +PHPBN2(PGSQL_POLLING_WRITING); + +/* Class names reserved by PHP (case insensitive) */ +PHPCN(directory); +PHPCN(stdclass); +PHPCN(__php_incomplete_class); +/* Added in PHP5. */ +PHPCN(exception); +PHPCN(errorexception); // As of PHP 5.1 +PHPCN(php_user_filter); +PHPCN(closure); // As of PHP 5.3 +PHPCN(generator); // As of PHP 5.5 +PHPCN(self); +PHPCN(static); +PHPCN(parent); +/* From extensions (which of these are actually predefined depends which + * extensions are loaded by default). */ +PHPCN(xmlwriter); +PHPCN(libxmlerror); +PHPCN(simplexmlelement); +PHPCN(soapclient); +PHPCN(soapvar); +PHPCN(soapserver); +PHPCN(soapfault); +PHPCN(soapparam); +PHPCN(soapheader); +PHPCN(recursiveiteratoriterator); +PHPCN(filteriterator); +PHPCN(recursivefilteriterator); +PHPCN(parentiterator); +PHPCN(limititerator); +PHPCN(cachingiterator); +PHPCN(recursivecachingiterator); +PHPCN(iteratoriterator); +PHPCN(norewinditerator); +PHPCN(appenditerator); +PHPCN(infiniteiterator); +PHPCN(emptyiterator); +PHPCN(arrayobject); +PHPCN(arrayiterator); +PHPCN(recursivearrayiterator); +PHPCN(splfileinfo); +PHPCN(directoryiterator); +PHPCN(recursivedirectoryiterator); +PHPCN(splfileobject); +PHPCN(spltempfileobject); +PHPCN(simplexmliterator); +PHPCN(logicexception); +PHPCN(badfunctioncallexception); +PHPCN(badmethodcallexception); +PHPCN(domainexception); +PHPCN(invalidargumentexception); +PHPCN(lengthexception); +PHPCN(outofrangeexception); +PHPCN(runtimeexception); +PHPCN(outofboundsexception); +PHPCN(overflowexception); +PHPCN(rangeexception); +PHPCN(underflowexception); +PHPCN(unexpectedvalueexception); +PHPCN(splobjectstorage); +PHPCN(reflectionexception); +PHPCN(reflection); +PHPCN(reflectionfunction); +PHPCN(reflectionparameter); +PHPCN(reflectionmethod); +PHPCN(reflectionclass); +PHPCN(reflectionobject); +PHPCN(reflectionproperty); +PHPCN(reflectionextension); +PHPCN(domexception); +PHPCN(domstringlist); +PHPCN(domnamelist); +PHPCN(domimplementationlist); +PHPCN(domimplementationsource); +PHPCN(domimplementation); +PHPCN(domnode); +PHPCN(domnamespacenode); +PHPCN(domdocumentfragment); +PHPCN(domdocument); +PHPCN(domnodelist); +PHPCN(domnamednodemap); +PHPCN(domcharacterdata); +PHPCN(domattr); +PHPCN(domelement); +PHPCN(domtext); +PHPCN(domcomment); +PHPCN(domtypeinfo); +PHPCN(domuserdatahandler); +PHPCN(domdomerror); +PHPCN(domerrorhandler); +PHPCN(domlocator); +PHPCN(domconfiguration); +PHPCN(domcdatasection); +PHPCN(domdocumenttype); +PHPCN(domnotation); +PHPCN(domentity); +PHPCN(domentityreference); +PHPCN(domprocessinginstruction); +PHPCN(domstringextend); +PHPCN(domxpath); +PHPCN(xmlreader); +PHPCN(sqlitedatabase); +PHPCN(sqliteresult); +PHPCN(sqliteunbuffered); +PHPCN(sqliteexception); +PHPCN(datetime); + +/* Built-in PHP functions (incomplete). */ +/* Includes Array Functions - http://php.net/manual/en/ref.array.php */ +/* Check is case insensitive - these *MUST* be listed in lower case here */ +PHPFN(acos); +PHPFN(array_change_key_case); +PHPFN(array_chunk); +PHPFN(array_column); +PHPFN(array_combine); +PHPFN(array_count_values); +PHPFN(array_diff); +PHPFN(array_diff_assoc); +PHPFN(array_diff_key); +PHPFN(array_diff_uassoc); +PHPFN(array_diff_ukey); +PHPFN(array_fill); +PHPFN(array_fill_keys); +PHPFN(array_filter); +PHPFN(array_flip); +PHPFN(array_intersect); +PHPFN(array_intersect_assoc); +PHPFN(array_intersect_key); +PHPFN(array_intersect_uassoc); +PHPFN(array_intersect_ukey); +PHPFN(array_key_exists); +PHPFN(array_keys); +PHPFN(array_map); +PHPFN(array_merge); +PHPFN(array_merge_recursive); +PHPFN(array_multisort); +PHPFN(array_pad); +PHPFN(array_pop); +PHPFN(array_product); +PHPFN(array_push); +PHPFN(array_rand); +PHPFN(array_reduce); +PHPFN(array_replace); +PHPFN(array_replace_recursive); +PHPFN(array_reverse); +PHPFN(array_search); +PHPFN(array_shift); +PHPFN(array_slice); +PHPFN(array_splice); +PHPFN(array_sum); +PHPFN(array_udiff); +PHPFN(array_udiff_assoc); +PHPFN(array_udiff_uassoc); +PHPFN(array_uintersect); +PHPFN(array_uintersect_assoc); +PHPFN(array_uintersect_uassoc); +PHPFN(array_unique); +PHPFN(array_unshift); +PHPFN(array_values); +PHPFN(array_walk); +PHPFN(array_walk_recursive); +PHPFN(arsort); +PHPFN(asin); +PHPFN(asort); +PHPFN(atan); +PHPFN(atan2); +PHPFN(ceil); +PHPFN(compact); +PHPFN(cos); +PHPFN(cosh); +PHPFN(count); +PHPFN(current); +PHPFN(each); +PHPFN(end); +PHPFN(exp); +PHPFN(extract); +PHPFN(floor); +PHPFN(fmod); +PHPFN(in_array); +PHPFN(key); +PHPFN(key_exists); +PHPFN(krsort); +PHPFN(ksort); +PHPFN(log); +PHPFN(log10); +PHPFN(max); +PHPFN(min); +PHPFN(natcasesort); +PHPFN(natsort); +PHPFN(next); +PHPFN(pos); +PHPFN(pow); +PHPFN(prev); +PHPFN(range); +PHPFN(reset); +PHPFN(rsort); +PHPFN(shuffle); +PHPFN(sin); +PHPFN(sinh); +PHPFN(sizeof); +PHPFN(sort); +PHPFN(sqrt); +PHPFN(tan); +PHPFN(tanh); +PHPFN(uasort); +PHPFN(uksort); +PHPFN(usort); + +#undef PHPKW +#undef PHPBN1a +#undef PHPBN1b +#undef PHPBN1 +#undef PHPBN2a +#undef PHPBN2b +#undef PHPBN2 +#undef PHPCN +#undef PHPFN diff --git a/Lib/php5/phppointers.i b/Lib/php5/phppointers.i new file mode 100644 index 000000000..e50ada7ac --- /dev/null +++ b/Lib/php5/phppointers.i @@ -0,0 +1,42 @@ +%define %pass_by_ref( TYPE, CONVERT_IN, CONVERT_OUT ) +%typemap(in, byref=1) TYPE *REF ($*1_ltype tmp), + TYPE &REF ($*1_ltype tmp) +%{ + /* First Check for SWIG wrapped type */ + if ( ZVAL_IS_NULL( *$input ) ) { + $1 = 0; + } else if ( PZVAL_IS_REF( *$input ) ) { + /* Not swig wrapped type, so we check if it's a PHP reference type */ + CONVERT_IN( tmp, $*1_ltype, $input ); + $1 = &tmp; + } else { + SWIG_PHP_Error( E_ERROR, SWIG_PHP_Arg_Error_Msg($argnum, Expected a reference) ); + } +%} +%typemap(argout) TYPE *REF, + TYPE &REF + "CONVERT_OUT(*$input, tmp$argnum );"; +%enddef + +%pass_by_ref( size_t, CONVERT_INT_IN, ZVAL_LONG ); + +%pass_by_ref( signed int, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( int, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( unsigned int, CONVERT_INT_IN, ZVAL_LONG ); + +%pass_by_ref( signed short, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( short, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( unsigned short, CONVERT_INT_IN, ZVAL_LONG ); + +%pass_by_ref( signed long, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( long, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( unsigned long, CONVERT_INT_IN, ZVAL_LONG ); + +%pass_by_ref( signed char, CONVERT_INT_IN, ZVAL_LONG ); +%pass_by_ref( char, CONVERT_CHAR_IN, ZVAL_STRING ); +%pass_by_ref( unsigned char, CONVERT_INT_IN, ZVAL_LONG ); + +%pass_by_ref( float, CONVERT_FLOAT_IN, ZVAL_DOUBLE ); +%pass_by_ref( double, CONVERT_FLOAT_IN, ZVAL_DOUBLE ); + +%pass_by_ref( char *, CONVERT_CHAR_IN, ZVAL_STRING ); diff --git a/Lib/php5/phprun.swg b/Lib/php5/phprun.swg new file mode 100644 index 000000000..0021a90e8 --- /dev/null +++ b/Lib/php5/phprun.swg @@ -0,0 +1,275 @@ +/* ----------------------------------------------------------------------------- + * phprun.swg + * + * PHP runtime library + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif +#include "zend.h" +#include "zend_API.h" +#include "zend_exceptions.h" +#include "php.h" +#include "ext/standard/php_string.h" +#include /* for abort(), used in generated code. */ + +#ifdef ZEND_RAW_FENTRY +/* ZEND_RAW_FENTRY was added somewhere between 5.2.0 and 5.2.3 */ +# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_RAW_FENTRY((char*)#ZN, N, A, 0) +#else +/* This causes warnings from GCC >= 4.2 (assigning a string literal to char*). + * But this seems to be unavoidable without directly assuming knowledge of + * the structure, which changed between PHP4 and PHP5. */ +# define SWIG_ZEND_NAMED_FE(ZN, N, A) ZEND_NAMED_FE(ZN, N, A) +#endif + +#ifndef ZEND_FE_END +# define ZEND_FE_END { NULL, NULL, NULL } +#endif + +#ifndef Z_SET_ISREF_P +/* For PHP < 5.3 */ +# define Z_SET_ISREF_P(z) (z)->is_ref = 1 +#endif +#ifndef Z_SET_REFCOUNT_P +/* For PHP < 5.3 */ +# define Z_SET_REFCOUNT_P(z, rc) (z)->refcount = (rc) +#endif + +#define SWIG_LONG_CONSTANT(N, V) zend_register_long_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) +#define SWIG_DOUBLE_CONSTANT(N, V) zend_register_double_constant((char*)#N, sizeof(#N), V, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) +#define SWIG_STRING_CONSTANT(N, V) zend_register_stringl_constant((char*)#N, sizeof(#N), (char*)(V), strlen(V), CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC) +#define SWIG_CHAR_CONSTANT(N, V) do {\ + static char swig_char = (V);\ + zend_register_stringl_constant((char*)#N, sizeof(#N), &swig_char, 1, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);\ +} while (0) + +/* These TSRMLS_ stuff should already be defined now, but with older php under + redhat are not... */ +#ifndef TSRMLS_D +#define TSRMLS_D +#endif +#ifndef TSRMLS_DC +#define TSRMLS_DC +#endif +#ifndef TSRMLS_C +#define TSRMLS_C +#endif +#ifndef TSRMLS_CC +#define TSRMLS_CC +#endif + +#ifdef __cplusplus +} +#endif + +/* But in fact SWIG_ConvertPtr is the native interface for getting typed + pointer values out of zvals. We need the TSRMLS_ macros for when we + make PHP type calls later as we handle php resources */ +#define SWIG_ConvertPtr(obj,pp,type,flags) SWIG_ZTS_ConvertPtr(obj,pp,type,flags TSRMLS_CC) + + +#define SWIG_fail goto fail + +static const char *default_error_msg = "Unknown error occurred"; +static int default_error_code = E_ERROR; + +#define SWIG_PHP_Arg_Error_Msg(argnum,extramsg) "Error in argument " #argnum " "#extramsg + +#define SWIG_PHP_Error(code,msg) do { SWIG_ErrorCode() = code; SWIG_ErrorMsg() = msg; SWIG_fail; } while (0) + +#define SWIG_contract_assert(expr,msg) \ + if (!(expr) ) { zend_printf("Contract Assert Failed %s\n",msg ); } else + +/* Standard SWIG API */ +#define SWIG_GetModule(clientdata) SWIG_Php_GetModule() +#define SWIG_SetModule(clientdata, pointer) SWIG_Php_SetModule(pointer) + +/* used to wrap returned objects in so we know whether they are newobject + and need freeing, or not */ +typedef struct { + void * ptr; + int newobject; +} swig_object_wrapper; + +#define SWIG_SetPointerZval(a,b,c,d) SWIG_ZTS_SetPointerZval(a,b,c,d TSRMLS_CC) +#define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a)) + +static void +SWIG_ZTS_SetPointerZval(zval *z, void *ptr, swig_type_info *type, int newobject TSRMLS_DC) { + /* + * First test for Null pointers. Return those as PHP native NULL + */ + if (!ptr ) { + ZVAL_NULL(z); + return; + } + if (type->clientdata) { + swig_object_wrapper *value; + if (! (*(int *)(type->clientdata))) + zend_error(E_ERROR, "Type: %s failed to register with zend",type->name); + value=(swig_object_wrapper *)emalloc(sizeof(swig_object_wrapper)); + value->ptr=ptr; + value->newobject=(newobject & 1); + if ((newobject & 2) == 0) { + /* Just register the pointer as a resource. */ + ZEND_REGISTER_RESOURCE(z, value, *(int *)(type->clientdata)); + } else { + /* + * Wrap the resource in an object, the resource will be accessible + * via the "_cPtr" member. This is currently only used by + * directorin typemaps. + */ + zval *resource; + zend_class_entry **ce = NULL; + const char *type_name = type->name+3; /* +3 so: _p_Foo -> Foo */ + size_t type_name_len; + int result; + const char * p; + + /* Namespace__Foo -> Foo */ + /* FIXME: ugly and goes wrong for classes with __ in their names. */ + while ((p = strstr(type_name, "__")) != NULL) { + type_name = p + 2; + } + type_name_len = strlen(type_name); + + MAKE_STD_ZVAL(resource); + ZEND_REGISTER_RESOURCE(resource, value, *(int *)(type->clientdata)); + if (SWIG_PREFIX_LEN > 0) { + char * classname = (char*)emalloc(SWIG_PREFIX_LEN + type_name_len + 1); + strcpy(classname, SWIG_PREFIX); + strcpy(classname + SWIG_PREFIX_LEN, type_name); + result = zend_lookup_class(classname, SWIG_PREFIX_LEN + type_name_len, &ce TSRMLS_CC); + efree(classname); + } else { + result = zend_lookup_class((char *)type_name, type_name_len, &ce TSRMLS_CC); + } + if (result != SUCCESS) { + /* class does not exist */ + object_init(z); + } else { + object_init_ex(z, *ce); + } + Z_SET_REFCOUNT_P(z, 1); + Z_SET_ISREF_P(z); + zend_hash_update(HASH_OF(z), (char*)"_cPtr", sizeof("_cPtr"), (void*)&resource, sizeof(zval*), NULL); + } + return; + } + zend_error(E_ERROR, "Type: %s not registered with zend",type->name); +} + +/* This pointer conversion routine takes the native pointer p (along with + its type name) and converts it by calling appropriate casting functions + according to ty. The resultant pointer is returned, or NULL is returned + if the pointer can't be cast. + + Sadly PHP has no API to find a type name from a type id, only from an + instance of a resource of the type id, so we have to pass type_name as well. + + The two functions which might call this are: + SWIG_ZTS_ConvertResourcePtr which gets the type name from the resource + and the registered zend destructors for which we have one per type each + with the type name hard wired in. */ +static void * +SWIG_ZTS_ConvertResourceData(void * p, const char *type_name, swig_type_info *ty TSRMLS_DC) { + swig_cast_info *tc; + void *result = 0; + + if (!ty) { + /* They don't care about the target type, so just pass on the pointer! */ + return p; + } + + if (! type_name) { + /* can't convert p to ptr type ty if we don't know what type p is */ + return NULL; + } + + /* convert and cast p from type_name to ptr as ty. */ + tc = SWIG_TypeCheck(type_name, ty); + if (tc) { + int newmemory = 0; + result = SWIG_TypeCast(tc, p, &newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } + return result; +} + +/* This function returns a pointer of type ty by extracting the pointer + and type info from the resource in z. z must be a resource. + If it fails, NULL is returned. + It uses SWIG_ZTS_ConvertResourceData to do the real work. */ +static void * +SWIG_ZTS_ConvertResourcePtr(zval *z, swig_type_info *ty, int flags TSRMLS_DC) { + swig_object_wrapper *value; + void *p; + int type; + const char *type_name; + + value = (swig_object_wrapper *) zend_list_find(z->value.lval, &type); + if (type==-1) return NULL; + if (flags & SWIG_POINTER_DISOWN) { + value->newobject = 0; + } + p = value->ptr; + + type_name=zend_rsrc_list_get_rsrc_type(z->value.lval TSRMLS_CC); + + return SWIG_ZTS_ConvertResourceData(p, type_name, ty TSRMLS_CC); +} + +/* We allow passing of a RESOURCE pointing to the object or an OBJECT whose + _cPtr is a resource pointing to the object */ +static int +SWIG_ZTS_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags TSRMLS_DC) { + if (z == NULL) { + *ptr = 0; + return 0; + } + + switch (z->type) { + case IS_OBJECT: { + zval ** _cPtr; + if (zend_hash_find(HASH_OF(z),(char*)"_cPtr",sizeof("_cPtr"),(void**)&_cPtr)==SUCCESS) { + if ((*_cPtr)->type==IS_RESOURCE) { + *ptr = SWIG_ZTS_ConvertResourcePtr(*_cPtr, ty, flags TSRMLS_CC); + return (*ptr == NULL ? -1 : 0); + } + } + break; + } + case IS_RESOURCE: + *ptr = SWIG_ZTS_ConvertResourcePtr(z, ty, flags TSRMLS_CC); + return (*ptr == NULL ? -1 : 0); + case IS_NULL: + *ptr = 0; + return 0; + } + + return -1; +} + +static char const_name[] = "swig_runtime_data_type_pointer"; +static swig_module_info *SWIG_Php_GetModule() { + zval *pointer; + swig_module_info *ret = 0; + TSRMLS_FETCH(); + + MAKE_STD_ZVAL(pointer); + + if (zend_get_constant(const_name, sizeof(const_name) - 1, pointer TSRMLS_CC)) { + if (pointer->type == IS_LONG) { + ret = (swig_module_info *) pointer->value.lval; + } + } + FREE_ZVAL(pointer); + return ret; +} + +static void SWIG_Php_SetModule(swig_module_info *pointer) { + TSRMLS_FETCH(); + REGISTER_MAIN_LONG_CONSTANT(const_name, (long) pointer, 0); +} diff --git a/Lib/php5/std_common.i b/Lib/php5/std_common.i new file mode 100644 index 000000000..092bf012b --- /dev/null +++ b/Lib/php5/std_common.i @@ -0,0 +1,10 @@ +/* ----------------------------------------------------------------------------- + * std_common.i + * + * SWIG typemaps for STL - common utilities + * ----------------------------------------------------------------------------- */ + +%include + +%apply size_t { std::size_t }; + diff --git a/Lib/php5/std_deque.i b/Lib/php5/std_deque.i new file mode 100644 index 000000000..cb98f6c2f --- /dev/null +++ b/Lib/php5/std_deque.i @@ -0,0 +1 @@ +%include diff --git a/Lib/php5/std_map.i b/Lib/php5/std_map.i new file mode 100644 index 000000000..6d5e3db13 --- /dev/null +++ b/Lib/php5/std_map.i @@ -0,0 +1,76 @@ +/* ----------------------------------------------------------------------------- + * 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; + 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(); + } + bool is_empty() const { + return self->empty(); + } + } + }; + +// 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/php5/std_pair.i b/Lib/php5/std_pair.i new file mode 100644 index 000000000..fe45ee676 --- /dev/null +++ b/Lib/php5/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/php5/std_string.i b/Lib/php5/std_string.i new file mode 100644 index 000000000..aaa5dc9cd --- /dev/null +++ b/Lib/php5/std_string.i @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------- + * std_string.i + * + * SWIG typemaps for std::string types + * ----------------------------------------------------------------------------- */ + +// ------------------------------------------------------------------------ +// std::string is typemapped by value +// This can prevent exporting methods which return a string +// in order for the user to modify it. +// However, I think I'll wait until someone asks for it... +// ------------------------------------------------------------------------ + +%include + +%{ +#include +%} + +namespace std { + + %naturalvar string; + + class string; + + %typemap(typecheck,precedence=SWIG_TYPECHECK_STRING) string, const string& %{ + $1 = ( Z_TYPE_PP($input) == IS_STRING ) ? 1 : 0; + %} + + %typemap(in) string %{ + convert_to_string_ex($input); + $1.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); + %} + + %typemap(directorout) string %{ + convert_to_string_ex(&$input); + $result.assign(Z_STRVAL_P($input), Z_STRLEN_P($input)); + %} + + %typemap(out) string %{ + ZVAL_STRINGL($result, const_cast($1.data()), $1.size(), 1); + %} + + %typemap(directorin) string, const string& %{ + ZVAL_STRINGL($input, const_cast($1.data()), $1.size(), 1); + %} + + %typemap(out) const string & %{ + ZVAL_STRINGL($result, const_cast($1->data()), $1->size(), 1); + %} + + %typemap(throws) string, const string& %{ + zend_throw_exception(NULL, const_cast($1.c_str()), 0 TSRMLS_CC); + return; + %} + + /* These next two handle a function which takes a non-const reference to + * a std::string and modifies the string. */ + %typemap(in) string & ($*1_ltype temp) %{ + convert_to_string_ex($input); + temp.assign(Z_STRVAL_PP($input), Z_STRLEN_PP($input)); + $1 = &temp; + %} + + %typemap(directorout) string & ($*1_ltype *temp) %{ + convert_to_string_ex(&$input); + temp = new $*1_ltype(Z_STRVAL_P($input), Z_STRLEN_P($input)); + swig_acquire_ownership(temp); + $result = temp; + %} + + %typemap(argout) string & %{ + ZVAL_STRINGL(*($input), const_cast($1->data()), $1->size(), 1); + %} + + /* SWIG will apply the non-const typemap above to const string& without + * this more specific typemap. */ + %typemap(argout) const string & ""; +} diff --git a/Lib/php5/std_vector.i b/Lib/php5/std_vector.i new file mode 100644 index 000000000..9cc1486ef --- /dev/null +++ b/Lib/php5/std_vector.i @@ -0,0 +1,102 @@ +/* ----------------------------------------------------------------------------- + * 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); + void clear(); + %rename(push) push_back; + void push_back(const value_type& x); + %extend { + bool is_empty() const { + return $self->empty(); + } + T pop() throw (std::out_of_range) { + if (self->size() == 0) + throw std::out_of_range("pop from empty vector"); + T x = self->back(); + self->pop_back(); + return x; + } + 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); + void clear(); + %rename(push) push_back; + void push_back(const value_type& x); + %extend { + bool is_empty() const { + return $self->empty(); + } + bool pop() throw (std::out_of_range) { + if (self->size() == 0) + throw std::out_of_range("pop from empty vector"); + bool x = self->back(); + self->pop_back(); + return x; + } + bool 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/php5/typemaps.i b/Lib/php5/typemaps.i new file mode 100644 index 000000000..faae0a6ac --- /dev/null +++ b/Lib/php5/typemaps.i @@ -0,0 +1,322 @@ +/* ----------------------------------------------------------------------------- + * typemaps.i. + * + * SWIG Typemap library for PHP. + * + * This library provides standard typemaps for modifying SWIG's behavior. + * With enough entries in this file, I hope that very few people actually + * ever need to write a typemap. + * + * Define macros to define the following typemaps: + * + * TYPE *INPUT. Argument is passed in as native variable by value. + * TYPE *OUTPUT. Argument is returned as an array from the function call. + * TYPE *INOUT. Argument is passed in by value, and out as part of returned list + * TYPE *REFERENCE. Argument is passed in as native variable with value + * semantics. Variable value is changed with result. + * Use like this: + * int foo(int *REFERENCE); + * + * $a = 0; + * $rc = foo($a); + * + * Even though $a looks like it's passed by value, + * its value can be changed by foo(). + * ----------------------------------------------------------------------------- */ + +%define BOOL_TYPEMAP(TYPE) +%typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) +%{ + convert_to_boolean_ex($input); + temp = Z_LVAL_PP($input) ? true : false; + $1 = &temp; +%} +%typemap(argout) TYPE *INPUT, TYPE &INPUT ""; +%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; +%typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT +{ + zval *o; + MAKE_STD_ZVAL(o); + ZVAL_BOOL(o,temp$argnum); + t_output_helper( &$result, o TSRMLS_CC ); +} +%typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) +%{ + convert_to_boolean_ex($input); + lvalue = (*$input)->value.lval ? true : false; + $1 = &lvalue; +%} +%typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE +%{ + (*$arg)->value.lval = lvalue$argnum ? true : false; + (*$arg)->type = IS_BOOL; +%} +%enddef + +%define DOUBLE_TYPEMAP(TYPE) +%typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) +%{ + convert_to_double_ex($input); + temp = (TYPE) Z_DVAL_PP($input); + $1 = &temp; +%} +%typemap(argout) TYPE *INPUT, TYPE &INPUT ""; +%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; +%typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT +{ + zval *o; + MAKE_STD_ZVAL(o); + ZVAL_DOUBLE(o,temp$argnum); + t_output_helper( &$result, o TSRMLS_CC ); +} +%typemap(in) TYPE *REFERENCE (TYPE dvalue), TYPE &REFERENCE (TYPE dvalue) +%{ + convert_to_double_ex($input); + dvalue = (TYPE) (*$input)->value.dval; + $1 = &dvalue; +%} +%typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE +%{ + $1->value.dval = (double)(lvalue$argnum); + $1->type = IS_DOUBLE; +%} +%enddef + +%define INT_TYPEMAP(TYPE) +%typemap(in) TYPE *INPUT(TYPE temp), TYPE &INPUT(TYPE temp) +%{ + convert_to_long_ex($input); + temp = (TYPE) Z_LVAL_PP($input); + $1 = &temp; +%} +%typemap(argout) TYPE *INPUT, TYPE &INPUT ""; +%typemap(in,numinputs=0) TYPE *OUTPUT(TYPE temp), TYPE &OUTPUT(TYPE temp) "$1 = &temp;"; +%typemap(argout,fragment="t_output_helper") TYPE *OUTPUT, TYPE &OUTPUT +{ + zval *o; + MAKE_STD_ZVAL(o); + ZVAL_LONG(o,temp$argnum); + t_output_helper( &$result, o TSRMLS_CC ); +} +%typemap(in) TYPE *REFERENCE (TYPE lvalue), TYPE &REFERENCE (TYPE lvalue) +%{ + convert_to_long_ex($input); + lvalue = (TYPE) (*$input)->value.lval; + $1 = &lvalue; +%} +%typemap(argout) TYPE *REFERENCE, TYPE &REFERENCE +%{ + (*$arg)->value.lval = (long)(lvalue$argnum); + (*$arg)->type = IS_LONG; +%} +%enddef + +BOOL_TYPEMAP(bool); + +DOUBLE_TYPEMAP(float); +DOUBLE_TYPEMAP(double); + +INT_TYPEMAP(int); +INT_TYPEMAP(short); +INT_TYPEMAP(long); +INT_TYPEMAP(unsigned int); +INT_TYPEMAP(unsigned short); +INT_TYPEMAP(unsigned long); +INT_TYPEMAP(unsigned char); +INT_TYPEMAP(signed char); + +INT_TYPEMAP(long long); +%typemap(argout,fragment="t_output_helper") long long *OUTPUT +{ + zval *o; + MAKE_STD_ZVAL(o); + if ((long long)LONG_MIN <= temp$argnum && temp$argnum <= (long long)LONG_MAX) { + ZVAL_LONG(o, temp$argnum); + } else { + char temp[256]; + sprintf(temp, "%lld", (long long)temp$argnum); + ZVAL_STRING(o, temp, 1); + } + t_output_helper( &$result, o TSRMLS_CC ); +} +%typemap(in) TYPE *REFERENCE (long long lvalue) +%{ + CONVERT_LONG_LONG_IN(lvalue, long long, $input) + $1 = &lvalue; +%} +%typemap(argout) long long *REFERENCE +%{ + if ((long long)LONG_MIN <= lvalue$argnum && lvalue$argnum <= (long long)LONG_MAX) { + (*$arg)->value.lval = (long)(lvalue$argnum); + (*$arg)->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", (long long)lvalue$argnum); + ZVAL_STRING((*$arg), temp, 1); + } +%} +%typemap(argout) long long &OUTPUT +%{ + if ((long long)LONG_MIN <= *arg$argnum && *arg$argnum <= (long long)LONG_MAX) { + ($result)->value.lval = (long)(*arg$argnum); + ($result)->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%lld", (long long)(*arg$argnum)); + ZVAL_STRING($result, temp, 1); + } +%} +INT_TYPEMAP(unsigned long long); +%typemap(argout,fragment="t_output_helper") unsigned long long *OUTPUT +{ + zval *o; + MAKE_STD_ZVAL(o); + if (temp$argnum <= (unsigned long long)LONG_MAX) { + ZVAL_LONG(o, temp$argnum); + } else { + char temp[256]; + sprintf(temp, "%llu", (unsigned long long)temp$argnum); + ZVAL_STRING(o, temp, 1); + } + t_output_helper( &$result, o TSRMLS_CC ); +} +%typemap(in) TYPE *REFERENCE (unsigned long long lvalue) +%{ + CONVERT_UNSIGNED_LONG_LONG_IN(lvalue, unsigned long long, $input) + $1 = &lvalue; +%} +%typemap(argout) unsigned long long *REFERENCE +%{ + if (lvalue$argnum <= (unsigned long long)LONG_MAX) { + (*$arg)->value.lval = (long)(lvalue$argnum); + (*$arg)->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", (unsigned long long)lvalue$argnum); + ZVAL_STRING((*$arg), temp, 1); + } +%} +%typemap(argout) unsigned long long &OUTPUT +%{ + if (*arg$argnum <= (unsigned long long)LONG_MAX) { + ($result)->value.lval = (long)(*arg$argnum); + ($result)->type = IS_LONG; + } else { + char temp[256]; + sprintf(temp, "%llu", (unsigned long long)(*arg$argnum)); + ZVAL_STRING($result, temp, 1); + } +%} + +%typemap(in) bool *INOUT = bool *INPUT; +%typemap(in) float *INOUT = float *INPUT; +%typemap(in) double *INOUT = double *INPUT; + +%typemap(in) int *INOUT = int *INPUT; +%typemap(in) short *INOUT = short *INPUT; +%typemap(in) long *INOUT = long *INPUT; +%typemap(in) long long *INOUT = long long *INPUT; +%typemap(in) unsigned *INOUT = unsigned *INPUT; +%typemap(in) unsigned short *INOUT = unsigned short *INPUT; +%typemap(in) unsigned long *INOUT = unsigned long *INPUT; +%typemap(in) unsigned char *INOUT = unsigned char *INPUT; +%typemap(in) unsigned long long *INOUT = unsigned long long *INPUT; +%typemap(in) signed char *INOUT = signed char *INPUT; + +%typemap(in) bool &INOUT = bool *INPUT; +%typemap(in) float &INOUT = float *INPUT; +%typemap(in) double &INOUT = double *INPUT; + +%typemap(in) int &INOUT = int *INPUT; +%typemap(in) short &INOUT = short *INPUT; +%typemap(in) long &INOUT = long *INPUT; +%typemap(in) long long &INOUT = long long *INPUT; +%typemap(in) long long &INPUT = long long *INPUT; +%typemap(in) unsigned &INOUT = unsigned *INPUT; +%typemap(in) unsigned short &INOUT = unsigned short *INPUT; +%typemap(in) unsigned long &INOUT = unsigned long *INPUT; +%typemap(in) unsigned char &INOUT = unsigned char *INPUT; +%typemap(in) unsigned long long &INOUT = unsigned long long *INPUT; +%typemap(in) unsigned long long &INPUT = unsigned long long *INPUT; +%typemap(in) signed char &INOUT = signed char *INPUT; + +%typemap(argout) bool *INOUT = bool *OUTPUT; +%typemap(argout) float *INOUT = float *OUTPUT; +%typemap(argout) double *INOUT= double *OUTPUT; + +%typemap(argout) int *INOUT = int *OUTPUT; +%typemap(argout) short *INOUT = short *OUTPUT; +%typemap(argout) long *INOUT= long *OUTPUT; +%typemap(argout) long long *INOUT= long long *OUTPUT; +%typemap(argout) unsigned short *INOUT= unsigned short *OUTPUT; +%typemap(argout) unsigned long *INOUT = unsigned long *OUTPUT; +%typemap(argout) unsigned char *INOUT = unsigned char *OUTPUT; +%typemap(argout) unsigned long long *INOUT = unsigned long long *OUTPUT; +%typemap(argout) signed char *INOUT = signed char *OUTPUT; + +%typemap(argout) bool &INOUT = bool *OUTPUT; +%typemap(argout) float &INOUT = float *OUTPUT; +%typemap(argout) double &INOUT= double *OUTPUT; + +%typemap(argout) int &INOUT = int *OUTPUT; +%typemap(argout) short &INOUT = short *OUTPUT; +%typemap(argout) long &INOUT= long *OUTPUT; +%typemap(argout) long long &INOUT= long long *OUTPUT; +%typemap(argout) unsigned short &INOUT= unsigned short *OUTPUT; +%typemap(argout) unsigned long &INOUT = unsigned long *OUTPUT; +%typemap(argout) unsigned char &INOUT = unsigned char *OUTPUT; +%typemap(argout) unsigned long long &INOUT = unsigned long long *OUTPUT; +%typemap(argout) signed char &INOUT = signed char *OUTPUT; + +%typemap(in) char INPUT[ANY] ( char temp[$1_dim0] ) +%{ + convert_to_string_ex($input); + strncpy(temp,Z_STRVAL_PP($input),$1_dim0); + $1 = temp; +%} +%typemap(in,numinputs=0) char OUTPUT[ANY] ( char temp[$1_dim0] ) + "$1 = temp;"; +%typemap(argout,fragment="t_output_helper") char OUTPUT[ANY] +{ + zval *o; + MAKE_STD_ZVAL(o); + ZVAL_STRINGL(o,temp$argnum,$1_dim0); + t_output_helper( &$result, o TSRMLS_CC ); +} + +%typemap(in,numinputs=0) void **OUTPUT (int force), + void *&OUTPUT (int force) +%{ + /* If they pass NULL by reference, make it into a void* + This bit should go in arginit if arginit support init-ing scripting args */ + if(SWIG_ConvertPtr(*$input, (void **) &$1, $1_descriptor, 0) < 0) { + /* So... we didn't get a ref or ptr, but we'll accept NULL by reference */ + if (!((*$input)->type==IS_NULL && PZVAL_IS_REF(*$input))) { + /* wasn't a pre/ref/thing, OR anything like an int thing */ + SWIG_PHP_Error(E_ERROR, "Type error in argument $arg of $symname."); + } + } + force=0; + if (arg1==NULL) { +#ifdef __cplusplus + ptr=new $*1_ltype(); +#else + ptr=($*1_ltype) calloc(1,sizeof($*1_ltype)); +#endif + $1=&ptr; + /* have to passback arg$arg too */ + force=1; + } +%} + +%typemap(argout) void **OUTPUT, + void *&OUTPUT +%{ + if (force$argnum) { /* pass back arg$argnum through params ($arg) if we can */ + if (!PZVAL_IS_REF(*$arg)) { + SWIG_PHP_Error(E_WARNING, "Parameter $argnum of $symname wasn't passed by reference"); + } else { + SWIG_SetPointerZval(*$arg, (void *) ptr$argnum, $*1_descriptor, 1); + } + } +%} diff --git a/Lib/php5/utils.i b/Lib/php5/utils.i new file mode 100644 index 000000000..408a3b366 --- /dev/null +++ b/Lib/php5/utils.i @@ -0,0 +1,114 @@ + +%define CONVERT_BOOL_IN(lvar,t,invar) + convert_to_boolean_ex(invar); + lvar = (t) Z_LVAL_PP(invar); +%enddef + +%define CONVERT_INT_IN(lvar,t,invar) + convert_to_long_ex(invar); + lvar = (t) Z_LVAL_PP(invar); +%enddef + +%define CONVERT_LONG_LONG_IN(lvar,t,invar) + switch ((*(invar))->type) { + case IS_DOUBLE: + lvar = (t) (*(invar))->value.dval; + break; + case IS_STRING: { + char * endptr; + errno = 0; + lvar = (t) strtoll((*(invar))->value.str.val, &endptr, 10); + if (*endptr && !errno) break; + /* FALL THRU */ + } + default: + convert_to_long_ex(invar); + lvar = (t) (*(invar))->value.lval; + } +%enddef + +%define CONVERT_UNSIGNED_LONG_LONG_IN(lvar,t,invar) + switch ((*(invar))->type) { + case IS_DOUBLE: + lvar = (t) (*(invar))->value.dval; + break; + case IS_STRING: { + char * endptr; + errno = 0; + lvar = (t) strtoull((*(invar))->value.str.val, &endptr, 10); + if (*endptr && !errno) break; + /* FALL THRU */ + } + default: + convert_to_long_ex(invar); + lvar = (t) (*(invar))->value.lval; + } +%enddef + +%define CONVERT_INT_OUT(lvar,invar) + lvar = (t) Z_LVAL_PP(invar); +%enddef + +%define CONVERT_FLOAT_IN(lvar,t,invar) + convert_to_double_ex(invar); + lvar = (t) Z_DVAL_PP(invar); +%enddef + +%define CONVERT_CHAR_IN(lvar,t,invar) + convert_to_string_ex(invar); + lvar = (t) *Z_STRVAL_PP(invar); +%enddef + +%define CONVERT_STRING_IN(lvar,t,invar) + if ((*invar)->type==IS_NULL) { + lvar = (t) 0; + } else { + convert_to_string_ex(invar); + lvar = (t) Z_STRVAL_PP(invar); + } +%enddef + +%define %pass_by_val( TYPE, CONVERT_IN ) +%typemap(in) TYPE +%{ + CONVERT_IN($1,$1_ltype,$input); +%} +%typemap(in) const TYPE & ($*1_ltype temp) +%{ + CONVERT_IN(temp,$*1_ltype,$input); + $1 = &temp; +%} +%typemap(directorout) TYPE +%{ + CONVERT_IN($result,$1_ltype,&$input); +%} +%typemap(directorout) const TYPE & ($*1_ltype temp) +%{ + CONVERT_IN(temp,$*1_ltype,&$input); + $result = &temp; +%} +%enddef + +%fragment("t_output_helper","header") %{ +static void +t_output_helper(zval **target, zval *o TSRMLS_DC) { + zval *tmp; + if ( (*target)->type == IS_ARRAY ) { + /* it's already an array, just append */ + add_next_index_zval( *target, o ); + return; + } + if ( (*target)->type == IS_NULL ) { + REPLACE_ZVAL_VALUE(target,o,1); + FREE_ZVAL(o); + return; + } + ALLOC_INIT_ZVAL(tmp); + *tmp = **target; + zval_copy_ctor(tmp); + array_init(*target); + add_next_index_zval( *target, tmp); + add_next_index_zval( *target, o); + +} +%} diff --git a/Makefile.in b/Makefile.in index c79e83815..df882ce34 100644 --- a/Makefile.in +++ b/Makefile.in @@ -67,6 +67,7 @@ skip-guile = test -n "@SKIP_GUILE@" skip-mzscheme = test -n "@SKIP_MZSCHEME@" skip-ruby = test -n "@SKIP_RUBY@" skip-php = test -n "@SKIP_PHP@" +skip-php5 = test -n "@SKIP_PHP5@" skip-ocaml = test -n "@SKIP_OCAML@" skip-octave = test -n "@SKIP_OCTAVE@" skip-pike = test -n "@SKIP_PIKE@" @@ -117,7 +118,8 @@ check-aliveness: @$(skip-ruby) || ./$(TARGET) -ruby -help @$(skip-ocaml) || ./$(TARGET) -ocaml -help @$(skip-octave) || ./$(TARGET) -octave -help - @$(skip-php) || ./$(TARGET) -php -help + @$(skip-php) || ./$(TARGET) -php7 -help + @$(skip-php5) || ./$(TARGET) -php5 -help @$(skip-pike) || ./$(TARGET) -pike -help @$(skip-chicken) || ./$(TARGET) -chicken -help @$(skip-csharp) || ./$(TARGET) -csharp -help @@ -150,6 +152,7 @@ check-versions: \ check-ocaml-version \ check-octave-version \ check-php-version \ + check-php5-version \ check-pike-version \ check-chicken-version \ check-csharp-version \ @@ -190,6 +193,7 @@ check-examples: \ check-ocaml-examples \ check-octave-examples \ check-php-examples \ + check-php5-examples \ check-pike-examples \ check-chicken-examples \ check-csharp-examples \ @@ -216,6 +220,7 @@ ruby_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ruby/check.list) ocaml_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/ocaml/check.list) octave_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/octave/check.list) php_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/php/check.list) +php5_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/php5/check.list) pike_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/pike/check.list) chicken_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/chicken/check.list) csharp_examples :=$(shell sed '/^\#/d' $(srcdir)/Examples/csharp/check.list) @@ -274,6 +279,7 @@ check-test-suite: \ check-ocaml-test-suite \ check-octave-test-suite \ check-php-test-suite \ + check-php5-test-suite \ check-pike-test-suite \ check-csharp-test-suite \ check-modula3-test-suite \ @@ -328,6 +334,7 @@ all-test-suite: \ all-ocaml-test-suite \ all-octave-test-suite \ all-php-test-suite \ + all-php5-test-suite \ all-pike-test-suite \ all-csharp-test-suite \ all-modula3-test-suite \ @@ -358,6 +365,7 @@ broken-test-suite: \ broken-ocaml-test-suite \ broken-octave-test-suite \ broken-php-test-suite \ + broken-php5-test-suite \ broken-pike-test-suite \ broken-csharp-test-suite \ broken-modula3-test-suite \ @@ -502,7 +510,7 @@ install-main: @echo "Installing $(DESTDIR)$(BIN_DIR)/`echo $(TARGET_NOEXE) | sed '$(transform)'`@EXEEXT@" @$(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 \ +lib-languages = gcj typemaps tcl perl5 python guile java mzscheme ruby php php5 ocaml octave \ pike chicken csharp modula3 allegrocl clisp lua cffi uffi r go d javascript javascript/jsc \ javascript/v8 scilab diff --git a/Source/Makefile.am b/Source/Makefile.am index b04e3542f..efa3ac1e4 100644 --- a/Source/Makefile.am +++ b/Source/Makefile.am @@ -62,6 +62,7 @@ eswig_SOURCES = CParse/cscanner.c \ Modules/overload.cxx \ Modules/perl5.cxx \ Modules/php.cxx \ + Modules/php5.cxx \ Modules/pike.cxx \ Modules/python.cxx \ Modules/r.cxx \ diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index ee78c6d0a..f86a0755d 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -43,7 +43,7 @@ #include static const char *usage = "\ -PHP Options (available with -php)\n\ +PHP Options (available with -php7)\n\ -noproxy - Don't generate proxy classes.\n\ -prefix - Prepend to all class names in PHP wrappers\n\ \n"; @@ -152,14 +152,14 @@ static void SwigPHP_emit_resource_registrations() { human_name = Getattr(class_node, "name"); // Do we have a known destructor for this type? if (destructor) { - Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key); + Printf(s_wrappers, " %s(res, SWIGTYPE%s->name);\n", destructor, key); } else { Printf(s_wrappers, " /* No destructor for class %s */\n", human_name); - Printf(s_wrappers, " efree(rsrc->ptr);\n"); + Printf(s_wrappers, " efree(res->ptr);\n"); } } else { Printf(s_wrappers, " /* No destructor for simple type %s */\n", key); - Printf(s_wrappers, " efree(rsrc->ptr);\n"); + Printf(s_wrappers, " efree(res->ptr);\n"); } // close function @@ -170,7 +170,7 @@ static void SwigPHP_emit_resource_registrations() { // register with php Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" - "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key); + "(_wrap_destroy%s, NULL, SWIGTYPE%s->name, module_number);\n", key, key, key); // store php type in class struct Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key); @@ -180,23 +180,6 @@ static void SwigPHP_emit_resource_registrations() { } class PHP : public Language { - String *emit_action(Node *n) { - // Adjust wrap:action to add TSRMLS_CC. - String * action = Getattr(n, "wrap:action"); - if (action) { - char * p = Strstr(action, "Swig::DirectorPureVirtualException::raise(\""); - if (p) { - p += strlen("Swig::DirectorPureVirtualException::raise(\""); - p = strchr(p, '"'); - if (p) { - ++p; - Insert(action, (int)(p - Char(action)), " TSRMLS_CC"); - } - } - } - return ::emit_action(n); - } - public: PHP() { director_language = 1; @@ -225,25 +208,11 @@ public: Swig_mark_arg(i); } else if (strcmp(argv[i], "-help") == 0) { fputs(usage, stdout); - } else if (strcmp(argv[i], "-make") == 0 || - strcmp(argv[i], "-withc") == 0 || - strcmp(argv[i], "-withcxx") == 0) { - Printf(stderr, "*** %s is no longer supported.\n", argv[i]); - SWIG_exit(EXIT_FAILURE); - } else if (strcmp(argv[i], "-phpfull") == 0 || - strcmp(argv[i], "-withlibs") == 0 || - strcmp(argv[i], "-withincs") == 0) { - Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]); - SWIG_exit(EXIT_FAILURE); - } else if (strcmp(argv[i], "-dlname") == 0) { - Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n"); - SWIG_exit(EXIT_FAILURE); } } Preprocessor_define("SWIGPHP 1", 0); - // SWIGPHP5 is deprecated, and no longer documented. - Preprocessor_define("SWIGPHP5 1", 0); + Preprocessor_define("SWIGPHP7 1", 0); SWIG_typemap_lang("php"); SWIG_config_file("php.swg"); allow_overloading(); @@ -267,7 +236,7 @@ public: } /* Set comparison with null for ConstructorToFunction */ - setSubclassInstanceCheck(NewString("$arg->type != IS_NULL")); + setSubclassInstanceCheck(NewString("Z_TYPE_P($arg) != IS_NULL")); /* Initialize all of the output files */ String *outfile = Getattr(n, "outfile"); @@ -402,9 +371,9 @@ public: * which has to be dynamically generated as it depends on the module name. */ Append(s_header, "#ifdef __GNUC__\n"); - Append(s_header, "static void SWIG_FAIL(TSRMLS_D) __attribute__ ((__noreturn__));\n"); + Append(s_header, "static void SWIG_FAIL(void) __attribute__ ((__noreturn__));\n"); Append(s_header, "#endif\n\n"); - Append(s_header, "static void SWIG_FAIL(TSRMLS_D) {\n"); + Append(s_header, "static void SWIG_FAIL(void) {\n"); Append(s_header, " zend_error(SWIG_ErrorCode(), \"%s\", SWIG_ErrorMsg());\n"); // zend_error() should never return with the parameters we pass, but if it // does, we really don't want to let SWIG_FAIL() return. This also avoids @@ -420,38 +389,36 @@ public: Printf(s_header, "static void %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module); Printf(s_header, "\n"); - Printf(s_header, "static void SWIG_ResetError(TSRMLS_D) {\n"); + Printf(s_header, "static void SWIG_ResetError(void) {\n"); Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n"); Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n"); Printf(s_header, "}\n"); Append(s_header, "\n"); Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module); - Append(s_header, " zval **args[2];\n"); + Append(s_header, " zval args[2];\n"); Append(s_header, " swig_object_wrapper *value;\n"); - Append(s_header, " int type;\n"); Append(s_header, "\n"); - Append(s_header, " SWIG_ResetError(TSRMLS_C);\n"); + Append(s_header, " SWIG_ResetError();\n"); Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n"); Append(s_header, " WRONG_PARAM_COUNT;\n"); Append(s_header, " }\n"); Append(s_header, "\n"); - Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); - Append(s_header, " value->newobject = zval_is_true(*args[1]);\n"); + Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n"); + Append(s_header, " value->newobject = zval_is_true(&args[1]);\n"); Append(s_header, "\n"); Append(s_header, " return;\n"); Append(s_header, "}\n"); Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module); - Append(s_header, " zval **args[1];\n"); + Append(s_header, " zval args[1];\n"); Append(s_header, " swig_object_wrapper *value;\n"); - Append(s_header, " int type;\n"); Append(s_header, "\n"); - Append(s_header, " SWIG_ResetError(TSRMLS_C);\n"); + Append(s_header, " SWIG_ResetError();\n"); Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); Append(s_header, " WRONG_PARAM_COUNT;\n"); Append(s_header, " }\n"); Append(s_header, "\n"); - Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); + Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n"); Append(s_header, " RETVAL_LONG(value->newobject);\n"); Append(s_header, "\n"); Append(s_header, " return;\n"); @@ -525,7 +492,7 @@ public: Append(s_init, "#endif\n"); Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL); Printf(s_init, " STANDARD_MODULE_HEADER,\n"); - Printf(s_init, " (char*)\"%s\",\n", module); + Printf(s_init, " \"%s\",\n", module); Printf(s_init, " %s_functions,\n", module); Printf(s_init, " PHP_MINIT(%s),\n", module); Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module); @@ -710,12 +677,12 @@ public: Wrapper_add_local(f, "argc", "int argc"); - Printf(tmp, "zval **argv[%d]", maxargs); + Printf(tmp, "zval argv[%d]", maxargs); Wrapper_add_local(f, "argv", tmp); Printf(f->code, "argc = ZEND_NUM_ARGS();\n"); - Printf(f->code, "zend_get_parameters_array_ex(argc,argv);\n"); + Printf(f->code, "zend_get_parameters_array_ex(argc, argv);\n"); Replaceall(dispatch, "$args", "self,args"); @@ -723,7 +690,7 @@ public: Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n"); Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname); - Printv(f->code, "SWIG_FAIL(TSRMLS_C);\n", NIL); + Printv(f->code, "SWIG_FAIL();\n", NIL); Printv(f->code, "}\n", NIL); Wrapper_print(f, s_wrappers); @@ -819,8 +786,8 @@ public: if (num_arguments > 0) { String *args = NewStringEmpty(); if (wrapperType == directorconstructor) - Wrapper_add_local(f, "arg0", "zval *arg0"); - Printf(args, "zval **args[%d]", num_arguments); + Wrapper_add_local(f, "arg0", "zval * arg0"); + Printf(args, "zval args[%d]", num_arguments); Wrapper_add_local(f, "args", args); Delete(args); args = NULL; @@ -834,7 +801,7 @@ public: // NOTE: possible we ignore this_ptr as a param for native constructor - Printf(f->code, "SWIG_ResetError(TSRMLS_C);\n"); + Printf(f->code, "SWIG_ResetError();\n"); if (numopt > 0) { // membervariable wrappers do not have optional args Wrapper_add_local(f, "arg_count", "int arg_count"); @@ -851,7 +818,7 @@ public: Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n"); } if (wrapperType == directorconstructor) - Printf(f->code, "arg0 = *args[0];\n \n"); + Printf(f->code, "arg0 = &args[0];\n \n"); /* Now convert from PHP to C variables */ // At this point, argcount if used is the number of deliberately passed args @@ -891,7 +858,7 @@ public: } if ((tm = Getattr(p, "tmap:in"))) { - Replaceall(tm, "$source", source); + Replaceall(tm, "$source", &source); Replaceall(tm, "$target", ln); Replaceall(tm, "$input", source); Setattr(p, "emit:input", source); @@ -915,7 +882,7 @@ public: if (is_member_director(n)) { Wrapper_add_local(f, "upcall", "bool upcall = false"); - Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method((char *)\"%s%s\", (char *)\"%s\" TSRMLS_CC);\n", + Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method(\"%s%s\", \"%s\");\n", prefix, Swig_class_name(Swig_methodclass(n)), name); } @@ -1006,7 +973,7 @@ public: /* Error handling code */ Printf(f->code, "fail:\n"); Printv(f->code, cleanup, NIL); - Append(f->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(f->code, "SWIG_FAIL();\n"); Printf(f->code, "}\n"); @@ -1056,6 +1023,7 @@ public: bool handle_as_overload = false; String **arg_names; String **arg_values; + unsigned char * byref; // Method or static method or plain function. const char *methodname = 0; String *output = s_oowrappers; @@ -1196,7 +1164,8 @@ public: } arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *)); - if (!arg_values) { + byref = (unsigned char *) malloc(max_num_of_arguments); + if (!arg_values || !byref) { /* FIXME: How should this be handled? The rest of SWIG just seems * to not bother checking for malloc failing! */ fprintf(stderr, "Malloc failed!\n"); @@ -1204,6 +1173,7 @@ public: } for (i = 0; i < max_num_of_arguments; ++i) { arg_values[i] = NULL; + byref[i] = false; } Node *o; @@ -1223,6 +1193,7 @@ public: continue; } assert(0 <= argno && argno < max_num_of_arguments); + byref[argno] = GetFlag(p, "tmap:in:byref"); String *&pname = arg_names[argno]; const char *pname_cstr = GetChar(p, "name"); // Just get rid of the C++ namespace part for now. @@ -1471,6 +1442,7 @@ public: Printf(args, ","); if (i || wrapperType == memberfn) Printf(invoke, ","); + if (byref[i]) Printf(args, "&"); String *value = arg_values[i]; if (value) { const char *v = Char(value); @@ -2290,15 +2262,15 @@ done: Delete(director_ctor_code); director_ctor_code = NewStringEmpty(); director_prot_ctor_code = NewStringEmpty(); - Printf(director_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); - Printf(director_prot_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); + Printf(director_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n"); + Printf(director_prot_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n"); Printf(director_ctor_code, " %s = (%s *)new %s(%s);\n", Swig_cresult_name(), ctype, ctype, args); Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args); if (i) { Insert(args, 0, ", "); } - Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0 TSRMLS_CC%s);\n}\n", Swig_cresult_name(), ctype, sname, args); - Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0 TSRMLS_CC%s);\n}\n", Swig_cresult_name(), ctype, sname, args); + Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args); + Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args); Delete(args); wrapperType = directorconstructor; @@ -2328,9 +2300,9 @@ done: Wrapper *f = NewWrapper(); Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n"); Printf(f->def, "/* to typecast and do the actual destruction */\n"); - Printf(f->def, "static void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname); + Printf(f->def, "static void %s(zend_resource *res, const char *type_name) {\n", destructorname); - Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); + Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) res->ptr", NIL); Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL); Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL); @@ -2348,7 +2320,7 @@ done: Printf(f->code, " efree(value);\n"); Printf(f->code, " if (! newobject) return; /* can't delete it! */\n"); - Printf(f->code, " arg1 = (%s)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); + Printf(f->code, " arg1 = (%s)SWIG_ConvertResourceData(ptr, type_name, SWIGTYPE%s);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name)); Setattr(n, "wrap:name", destructorname); @@ -2360,7 +2332,7 @@ done: Printf(f->code, "thrown:\n"); Append(f->code, "return;\n"); Append(f->code, "fail:\n"); - Append(f->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(f->code, "SWIG_FAIL();\n"); Printf(f->code, "}\n"); Wrapper_print(f, s_wrappers); @@ -2420,16 +2392,9 @@ done: String *call; String *basetype = Getattr(parent, "classtype"); - // We put TSRMLS_DC after the self parameter in order to cope with - // any default parameters. String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); - const char * p = Char(target); - const char * comma = strchr(p, ','); - int ins = comma ? (int)(comma - p) : Len(target) - 1; - Insert(target, ins, " TSRMLS_DC"); - call = Swig_csuperclass_call(0, basetype, superparms); - Printf(w->def, "%s::%s: %s, Swig::Director(self TSRMLS_CC) {", classname, target, call); + Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call); Append(w->def, "}"); Delete(target); Wrapper_print(w, f_directors); @@ -2439,14 +2404,7 @@ done: /* constructor header */ { - // We put TSRMLS_DC after the self parameter in order to cope with - // any default parameters. String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); - const char * p = Char(target); - const char * comma = strchr(p, ','); - int ins = comma ? (int)(comma - p) : Len(target) - 1; - Insert(target, ins, " TSRMLS_DC"); - Printf(f_directors_h, " %s;\n", target); Delete(target); } @@ -2531,8 +2489,6 @@ done: Append(w->def, " {"); Append(declaration, ";\n"); - Printf(w->code, "TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);\n"); - /* declare method return value * if the return value is a reference or const reference, a specialized typemap must * handle it, including declaration of c_result ($result). @@ -2553,7 +2509,7 @@ done: Printf(w->code, "%s;\n", super_call); Delete(super_call); } else { - Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\" TSRMLS_CC);\n", SwigType_namestr(c_classname), + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); } } else { @@ -2568,7 +2524,6 @@ done: Swig_typemap_attach_parms("directorargout", l, w); Parm *p; - char source[256]; int outputs = 0; if (!is_void) @@ -2592,16 +2547,11 @@ done: if ((tm = Getattr(p, "tmap:directorin")) != 0) { String *parse = Getattr(p, "tmap:directorin:parse"); if (!parse) { - sprintf(source, "obj%d", idx++); - String *input = NewStringf("&%s", source); + String *input = NewStringf("&args[%d]", idx++); Setattr(p, "emit:directorinput", input); Replaceall(tm, "$input", input); Delete(input); Replaceall(tm, "$owner", "0"); - Printv(wrap_args, "zval ", source, ";\n", NIL); - Printf(wrap_args, "args[%d] = &%s;\n", idx - 1, source); - Printv(wrap_args, "INIT_ZVAL(", source, ");\n", NIL); - Printv(wrap_args, tm, "\n", NIL); Putc('O', parse_args); } else { @@ -2644,17 +2594,17 @@ done: } if (!idx) { - Printf(w->code, "zval **args = NULL;\n"); + Printf(w->code, "zval *args = NULL;\n"); } else { - Printf(w->code, "zval *args[%d];\n", idx); + Printf(w->code, "zval args[%d];\n", idx); } - Printf(w->code, "zval *%s, funcname;\n", Swig_cresult_name()); - Append(w->code, "if (!swig_self) {\n"); - Append(w->code, " SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");"); - Append(w->code, "}\n\n"); - Printf(w->code, "MAKE_STD_ZVAL(%s);\n", Swig_cresult_name()); + // typemap_directorout testcase requires that 0 can be assigned to the + // variable named after the result of Swig_cresult_name(), so that can't + // be a zval - make it a pointer to one instead. + Printf(w->code, "zval swig_zval_result, swig_funcname;\n", Swig_cresult_name()); + Printf(w->code, "zval *%s = &swig_zval_result;\n", Swig_cresult_name()); const char * funcname = GetChar(n, "sym:name"); - Printf(w->code, "ZVAL_STRINGL(&funcname, (char *)\"%s\", %d, 0);\n", funcname, strlen(funcname)); + Printf(w->code, "ZVAL_STRINGL(&swig_funcname, \"%s\", %d);\n", funcname, strlen(funcname)); /* wrap complex arguments to zvals */ Printv(w->code, wrap_args, NIL); @@ -2662,8 +2612,8 @@ done: if (error_used_in_typemap) { Append(w->code, "error = "); } - Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,"); - Printf(w->code, " %s, %d, args TSRMLS_CC);\n", Swig_cresult_name(), idx); + Append(w->code, "call_user_function(EG(function_table), &swig_self, &swig_funcname,"); + Printf(w->code, " &swig_zval_result, %d, args);\n", idx); if (tm) { Printv(w->code, Str(tm), "\n", NIL); @@ -2715,8 +2665,6 @@ done: } } - Printf(w->code, "FREE_ZVAL(%s);\n", Swig_cresult_name()); - Delete(parse_args); Delete(cleanup); Delete(outarg); @@ -2738,7 +2686,7 @@ done: } Append(w->code, "fail:\n"); - Append(w->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(w->code, "SWIG_FAIL();\n"); Append(w->code, "}\n"); // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method @@ -2783,7 +2731,8 @@ static PHP *maininstance = 0; // We use this function to be able to write out zend_register_list_destructor_ex // lines for most things in the type table // NOTE: it's a function NOT A PHP::METHOD -extern "C" void typetrace(const SwigType *ty, String *mangled, String *clientdata) { +extern "C" { +static void typetrace(const SwigType *ty, String *mangled, String *clientdata) { Node *class_node; if (!zend_types) { zend_types = NewHash(); @@ -2803,6 +2752,7 @@ extern "C" void typetrace(const SwigType *ty, String *mangled, String *clientdat if (r_prevtracefunc) (*r_prevtracefunc) (ty, mangled, (String *) clientdata); } +} /* ----------------------------------------------------------------------------- * new_swig_php() - Instantiate module @@ -2819,13 +2769,6 @@ static Language *new_swig_php() { return maininstance; } -extern "C" Language *swig_php4(void) { - Printf(stderr, "*** -php4 is no longer supported.\n" - "*** Either upgrade to PHP5 or use SWIG 1.3.36 or earlier.\n"); - SWIG_exit(EXIT_FAILURE); - return NULL; // To avoid compiler warnings. -} - extern "C" Language *swig_php(void) { return new_swig_php(); } diff --git a/Source/Modules/php5.cxx b/Source/Modules/php5.cxx new file mode 100644 index 000000000..dff5fa47f --- /dev/null +++ b/Source/Modules/php5.cxx @@ -0,0 +1,2833 @@ +/* ----------------------------------------------------------------------------- + * 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. + * + * php5.cxx + * + * PHP5 language module for SWIG. + * ----------------------------------------------------------------------------- + */ + +/* FIXME: PHP5 OO wrapping TODO list: + * + * Medium term: + * + * Handle default parameters on overloaded methods in PHP where possible. + * (Mostly done - just need to handle cases of overloaded methods with + * default parameters...) + * This is an optimisation - we could handle this case using a PHP + * default value, but currently we treat it as we would for a default + * value which is a compound C++ expression (i.e. as if we had a + * method with two overloaded forms instead of a single method with + * a default parameter value). + * + * Long term: + * + * Sort out locale-dependent behaviour of strtod() - it's harmless unless + * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably + * OK currently at least. + */ + +/* + * TODO: Replace remaining stderr messages with Swig_error or Swig_warning + * (may need to add more WARN_PHP_xxx codes...) + */ + +#include "swigmod.h" + +#include +#include + +static const char *usage = "\ +PHP5 Options (available with -php5)\n\ + -noproxy - Don't generate proxy classes.\n\ + -prefix - Prepend to all class names in PHP wrappers\n\ +\n"; + +/* The original class wrappers for PHP stored the pointer to the C++ class in + * the object property _cPtr. If we use the same name for the member variable + * which we put the pointer to the C++ class in, then the flat function + * wrappers will automatically pull it out without any changes being required. + * FIXME: Isn't using a leading underscore a bit suspect here? + */ +#define SWIG_PTR "_cPtr" + +/* This is the name of the hash where the variables existing only in PHP + * classes are stored. + */ +#define SWIG_DATA "_pData" + +static int constructors = 0; +static String *NOTCLASS = NewString("Not a class"); +static Node *classnode = 0; +static String *module = 0; +static String *cap_module = 0; +static String *prefix = 0; + +static String *shadow_classname = 0; + +static File *f_begin = 0; +static File *f_runtime = 0; +static File *f_runtime_h = 0; +static File *f_h = 0; +static File *f_phpcode = 0; +static File *f_directors = 0; +static File *f_directors_h = 0; +static String *phpfilename = 0; + +static String *s_header; +static String *s_wrappers; +static String *s_init; +static String *r_init; // RINIT user code +static String *s_shutdown; // MSHUTDOWN user code +static String *r_shutdown; // RSHUTDOWN user code +static String *s_vinit; // varinit initialization code. +static String *s_vdecl; +static String *s_cinit; // consttab initialization code. +static String *s_oinit; +static String *s_arginfo; +static String *s_entry; +static String *cs_entry; +static String *all_cs_entry; +static String *pragma_incl; +static String *pragma_code; +static String *pragma_phpinfo; +static String *s_oowrappers; +static String *s_fakeoowrappers; +static String *s_phpclasses; + +/* Variables for using PHP classes */ +static Node *current_class = 0; + +static Hash *shadow_get_vars; +static Hash *shadow_set_vars; +static Hash *zend_types = 0; + +static int shadow = 1; + +static bool class_has_ctor = false; +static String *wrapping_member_constant = NULL; + +// These static variables are used to pass some state from Handlers into functionWrapper +static enum { + standard = 0, + memberfn, + staticmemberfn, + membervar, + staticmembervar, + constructor, + directorconstructor +} wrapperType = standard; + +extern "C" { + static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0; +} + +static void SwigPHP_emit_resource_registrations() { + Iterator ki; + + if (!zend_types) + return; + + ki = First(zend_types); + if (ki.key) + Printf(s_oinit, "\n/* Register resource destructors for pointer types */\n"); + while (ki.key) { + DOH *key = ki.key; + Node *class_node = ki.item; + String *human_name = key; + + // Write out destructor function header + Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key); + + // write out body + if (class_node != NOTCLASS) { + String *destructor = Getattr(class_node, "destructor"); + human_name = Getattr(class_node, "sym:name"); + if (!human_name) + human_name = Getattr(class_node, "name"); + // Do we have a known destructor for this type? + if (destructor) { + Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key); + } else { + Printf(s_wrappers, " /* No destructor for class %s */\n", human_name); + Printf(s_wrappers, " efree(rsrc->ptr);\n"); + } + } else { + Printf(s_wrappers, " /* No destructor for simple type %s */\n", key); + Printf(s_wrappers, " efree(rsrc->ptr);\n"); + } + + // close function + Printf(s_wrappers, "}\n"); + + // declare le_swig_ to store php registration + Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name); + + // register with php + Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" + "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key); + + // store php type in class struct + Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key); + + ki = Next(ki); + } +} + +class PHP5 : public Language { + String *emit_action(Node *n) { + // Adjust wrap:action to add TSRMLS_CC. + String * action = Getattr(n, "wrap:action"); + if (action) { + char * p = Strstr(action, "Swig::DirectorPureVirtualException::raise(\""); + if (p) { + p += strlen("Swig::DirectorPureVirtualException::raise(\""); + p = strchr(p, '"'); + if (p) { + ++p; + Insert(action, (int)(p - Char(action)), " TSRMLS_CC"); + } + } + } + return ::emit_action(n); + } + +public: + PHP5() { + director_language = 1; + } + + /* ------------------------------------------------------------ + * main() + * ------------------------------------------------------------ */ + + virtual void main(int argc, char *argv[]) { + SWIG_library_directory("php5"); + SWIG_config_cppext("cpp"); + + for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-prefix") == 0) { + if (argv[i + 1]) { + prefix = NewString(argv[i + 1]); + Swig_mark_arg(i); + Swig_mark_arg(i + 1); + i++; + } else { + Swig_arg_error(); + } + } else if ((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) { + shadow = 0; + Swig_mark_arg(i); + } else if (strcmp(argv[i], "-help") == 0) { + fputs(usage, stdout); + } else if (strcmp(argv[i], "-make") == 0 || + strcmp(argv[i], "-withc") == 0 || + strcmp(argv[i], "-withcxx") == 0) { + Printf(stderr, "*** %s is no longer supported.\n", argv[i]); + SWIG_exit(EXIT_FAILURE); + } else if (strcmp(argv[i], "-phpfull") == 0 || + strcmp(argv[i], "-withlibs") == 0 || + strcmp(argv[i], "-withincs") == 0) { + Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]); + SWIG_exit(EXIT_FAILURE); + } else if (strcmp(argv[i], "-dlname") == 0) { + Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n"); + SWIG_exit(EXIT_FAILURE); + } + } + + Preprocessor_define("SWIGPHP 1", 0); + // SWIGPHP5 is deprecated, and no longer documented. + Preprocessor_define("SWIGPHP5 1", 0); + SWIG_typemap_lang("php"); + SWIG_config_file("php.swg"); + allow_overloading(); + } + + /* ------------------------------------------------------------ + * top() + * ------------------------------------------------------------ */ + + virtual int top(Node *n) { + + String *filen; + + /* Check if directors are enabled for this module. */ + Node *mod = Getattr(n, "module"); + if (mod) { + Node *options = Getattr(mod, "options"); + if (options && Getattr(options, "directors")) { + allow_directors(); + } + } + + /* Set comparison with null for ConstructorToFunction */ + setSubclassInstanceCheck(NewString("$arg->type != IS_NULL")); + + /* Initialize all of the output files */ + String *outfile = Getattr(n, "outfile"); + String *outfile_h = Getattr(n, "outfile_h"); + + /* main output file */ + f_begin = NewFile(outfile, "w", SWIG_output_files()); + if (!f_begin) { + FileErrorDisplay(outfile); + SWIG_exit(EXIT_FAILURE); + } + f_runtime = NewStringEmpty(); + + /* sections of the output file */ + s_init = NewString("/* init section */\n"); + r_init = NewString("/* rinit section */\n"); + s_shutdown = NewString("/* shutdown section */\n"); + r_shutdown = NewString("/* rshutdown section */\n"); + s_header = NewString("/* header section */\n"); + s_wrappers = NewString("/* wrapper section */\n"); + /* subsections of the init section */ + s_vinit = NewString("/* vinit subsection */\n"); + s_vdecl = NewString("/* vdecl subsection */\n"); + s_cinit = NewString("/* cinit subsection */\n"); + s_oinit = NewString("/* oinit subsection */\n"); + pragma_phpinfo = NewStringEmpty(); + s_phpclasses = NewString("/* PHP Proxy Classes */\n"); + f_directors_h = NewStringEmpty(); + f_directors = NewStringEmpty(); + + if (directorsEnabled()) { + f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); + if (!f_runtime_h) { + FileErrorDisplay(outfile_h); + SWIG_exit(EXIT_FAILURE); + } + } + + /* Register file targets with the SWIG file handler */ + Swig_register_filebyname("begin", f_begin); + Swig_register_filebyname("runtime", f_runtime); + Swig_register_filebyname("init", s_init); + Swig_register_filebyname("rinit", r_init); + Swig_register_filebyname("shutdown", s_shutdown); + Swig_register_filebyname("rshutdown", r_shutdown); + Swig_register_filebyname("header", s_header); + Swig_register_filebyname("wrapper", s_wrappers); + Swig_register_filebyname("director", f_directors); + Swig_register_filebyname("director_h", f_directors_h); + + Swig_banner(f_begin); + + Printf(f_runtime, "\n\n#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n"); + + if (directorsEnabled()) { + Printf(f_runtime, "#define SWIG_DIRECTORS\n"); + } + + /* Set the module name */ + module = Copy(Getattr(n, "name")); + cap_module = NewStringf("%(upper)s", module); + if (!prefix) + prefix = NewStringEmpty(); + + Printf(f_runtime, "#define SWIG_PREFIX \"%s\"\n", prefix); + Printf(f_runtime, "#define SWIG_PREFIX_LEN %lu\n", (unsigned long)Len(prefix)); + + if (directorsEnabled()) { + Swig_banner(f_directors_h); + Printf(f_directors_h, "\n"); + Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module); + Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module); + + String *filename = Swig_file_filename(outfile_h); + Printf(f_directors, "\n#include \"%s\"\n\n", filename); + Delete(filename); + } + + /* PHP module file */ + filen = NewStringEmpty(); + Printv(filen, SWIG_output_directory(), module, ".php", NIL); + phpfilename = NewString(filen); + + f_phpcode = NewFile(filen, "w", SWIG_output_files()); + if (!f_phpcode) { + FileErrorDisplay(filen); + SWIG_exit(EXIT_FAILURE); + } + + Printf(f_phpcode, "error_msg = default_error_msg;\n"); + Printf(s_header, " globals->error_code = default_error_code;\n"); + Printf(s_header, "}\n"); + + Printf(s_header, "static void %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module); + + Printf(s_header, "\n"); + Printf(s_header, "static void SWIG_ResetError(TSRMLS_D) {\n"); + Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n"); + Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n"); + Printf(s_header, "}\n"); + + Append(s_header, "\n"); + Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module); + Append(s_header, " zval **args[2];\n"); + Append(s_header, " swig_object_wrapper *value;\n"); + Append(s_header, " int type;\n"); + Append(s_header, "\n"); + Append(s_header, " SWIG_ResetError(TSRMLS_C);\n"); + Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n"); + Append(s_header, " WRONG_PARAM_COUNT;\n"); + Append(s_header, " }\n"); + Append(s_header, "\n"); + Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); + Append(s_header, " value->newobject = zval_is_true(*args[1]);\n"); + Append(s_header, "\n"); + Append(s_header, " return;\n"); + Append(s_header, "}\n"); + Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module); + Append(s_header, " zval **args[1];\n"); + Append(s_header, " swig_object_wrapper *value;\n"); + Append(s_header, " int type;\n"); + Append(s_header, "\n"); + Append(s_header, " SWIG_ResetError(TSRMLS_C);\n"); + Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); + Append(s_header, " WRONG_PARAM_COUNT;\n"); + Append(s_header, " }\n"); + Append(s_header, "\n"); + Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); + Append(s_header, " RETVAL_LONG(value->newobject);\n"); + Append(s_header, "\n"); + Append(s_header, " return;\n"); + Append(s_header, "}\n"); + + Printf(s_header, "#define SWIG_name \"%s\"\n", module); + Printf(s_header, "#ifdef __cplusplus\n"); + Printf(s_header, "extern \"C\" {\n"); + Printf(s_header, "#endif\n"); + Printf(s_header, "#include \"php.h\"\n"); + Printf(s_header, "#include \"php_ini.h\"\n"); + Printf(s_header, "#include \"ext/standard/info.h\"\n"); + Printf(s_header, "#include \"php_%s.h\"\n", module); + Printf(s_header, "#ifdef __cplusplus\n"); + Printf(s_header, "}\n"); + Printf(s_header, "#endif\n\n"); + + if (directorsEnabled()) { + // Insert director runtime + Swig_insert_file("director_common.swg", s_header); + Swig_insert_file("director.swg", s_header); + } + + /* Create the .h file too */ + filen = NewStringEmpty(); + Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL); + f_h = NewFile(filen, "w", SWIG_output_files()); + if (!f_h) { + FileErrorDisplay(filen); + SWIG_exit(EXIT_FAILURE); + } + + Swig_banner(f_h); + + Printf(f_h, "\n"); + Printf(f_h, "#ifndef PHP_%s_H\n", cap_module); + Printf(f_h, "#define PHP_%s_H\n\n", cap_module); + Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module); + Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module); + Printf(f_h, "#ifdef PHP_WIN32\n"); + Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module); + Printf(f_h, "#else\n"); + Printf(f_h, "# define PHP_%s_API\n", cap_module); + Printf(f_h, "#endif\n\n"); + Printf(f_h, "#ifdef ZTS\n"); + Printf(f_h, "#include \"TSRM.h\"\n"); + Printf(f_h, "#endif\n\n"); + Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module); + Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module); + Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module); + Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module); + Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n\n", module); + + /* start the arginfo section */ + s_arginfo = NewString("/* arginfo subsection */\n"); + + /* start the function entry section */ + s_entry = NewString("/* entry subsection */\n"); + + /* holds all the per-class function entry sections */ + all_cs_entry = NewString("/* class entry subsection */\n"); + cs_entry = NULL; + + Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n"); + Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module); + + /* start the init section */ + Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n"); + Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n"); + Append(s_init, "#define ZEND_MODULE_BUILD_ID (char*)\"API\" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA\n"); + Append(s_init, "#endif\n"); + Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL); + Printf(s_init, " STANDARD_MODULE_HEADER,\n"); + Printf(s_init, " (char*)\"%s\",\n", module); + Printf(s_init, " %s_functions,\n", module); + Printf(s_init, " PHP_MINIT(%s),\n", module); + Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module); + Printf(s_init, " PHP_RINIT(%s),\n", module); + Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module); + Printf(s_init, " PHP_MINFO(%s),\n", module); + Printf(s_init, " NO_VERSION_YET,\n"); + Printf(s_init, " STANDARD_MODULE_PROPERTIES\n"); + Printf(s_init, "};\n"); + Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module); + + Printf(s_init, "#ifdef __cplusplus\n"); + Printf(s_init, "extern \"C\" {\n"); + Printf(s_init, "#endif\n"); + // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE + // in PHP5 has "extern "C" { ... }" around it so we can't do that. + Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module); + Printf(s_init, "#ifdef __cplusplus\n"); + Printf(s_init, "}\n"); + Printf(s_init, "#endif\n\n"); + + /* We have to register the constants before they are (possibly) used + * by the pointer typemaps. This all needs re-arranging really as + * things are being called in the wrong order + */ + Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module); + + /* Emit all of the code */ + Language::top(n); + + SwigPHP_emit_resource_registrations(); + // Printv(s_init,s_resourcetypes,NIL); + /* We need this after all classes written out by ::top */ + Printf(s_oinit, "CG(active_class_entry) = NULL;\n"); + Printf(s_oinit, "/* end oinit subsection */\n"); + Printf(s_init, "%s\n", s_oinit); + + /* Constants generated during top call */ + Printf(s_cinit, "/* end cinit subsection */\n"); + Printf(s_init, "%s\n", s_cinit); + Clear(s_cinit); + Delete(s_cinit); + + Printf(s_init, " return SUCCESS;\n"); + Printf(s_init, "}\n\n"); + + // Now do REQUEST init which holds any user specified %rinit, and also vinit + Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module); + Printf(s_init, "%s\n", r_init); + + /* finish our init section which will have been used by class wrappers */ + Printf(s_vinit, "/* end vinit subsection */\n"); + Printf(s_init, "%s\n", s_vinit); + Clear(s_vinit); + Delete(s_vinit); + + Printf(s_init, " return SUCCESS;\n"); + Printf(s_init, "}\n\n"); + + Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n" + "{\n", + s_shutdown, + "#ifdef ZTS\n" + " ts_free_id(", module, "_globals_id);\n" + "#endif\n" + " return SUCCESS;\n" + "}\n\n", NIL); + + Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module); + Printf(s_init, "%s\n", r_shutdown); + Printf(s_init, " return SUCCESS;\n"); + Printf(s_init, "}\n\n"); + + Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module); + Printf(s_init, "%s", pragma_phpinfo); + Printf(s_init, "}\n"); + Printf(s_init, "/* end init section */\n"); + + Printf(f_h, "#endif /* PHP_%s_H */\n", cap_module); + + Delete(f_h); + + String *type_table = NewStringEmpty(); + SwigType_emit_type_table(f_runtime, type_table); + Printf(s_header, "%s", type_table); + Delete(type_table); + + /* Oh dear, more things being called in the wrong order. This whole + * function really needs totally redoing. + */ + + if (directorsEnabled()) { + Dump(f_directors_h, f_runtime_h); + Printf(f_runtime_h, "\n"); + Printf(f_runtime_h, "#endif\n"); + Delete(f_runtime_h); + } + + Printf(s_header, "/* end header section */\n"); + Printf(s_wrappers, "/* end wrapper section */\n"); + Printf(s_vdecl, "/* end vdecl subsection */\n"); + + Dump(f_runtime, f_begin); + Printv(f_begin, s_header, NIL); + if (directorsEnabled()) { + Dump(f_directors, f_begin); + } + Printv(f_begin, s_vdecl, s_wrappers, NIL); + Printv(f_begin, all_cs_entry, "\n\n", s_arginfo, "\n\n", s_entry, + " SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n" + " SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n" + " ZEND_FE_END\n};\n\n", NIL); + Printv(f_begin, s_init, NIL); + Delete(s_header); + Delete(s_wrappers); + Delete(s_init); + Delete(s_vdecl); + Delete(all_cs_entry); + Delete(s_entry); + Delete(s_arginfo); + Delete(f_runtime); + Delete(f_begin); + + Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code); + if (s_fakeoowrappers) { + Printf(f_phpcode, "abstract class %s {", Len(prefix) ? prefix : module); + Printf(f_phpcode, "%s", s_fakeoowrappers); + Printf(f_phpcode, "}\n\n"); + Delete(s_fakeoowrappers); + s_fakeoowrappers = NULL; + } + Printf(f_phpcode, "%s\n?>\n", s_phpclasses); + Delete(f_phpcode); + + return SWIG_OK; + } + + /* Just need to append function names to function table to register with PHP. */ + void create_command(String *cname, String *iname, Node *n) { + // This is for the single main zend_function_entry record + Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname); + String * s = cs_entry; + if (!s) s = s_entry; + Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%(lower)s)\n", cname, iname, cname); + + // This is the above referenced arginfo structure. + ParmList *l = Getattr(n, "parms"); + Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%(lower)s, 0, 0, 0)\n", cname); + for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) { + /* Ignored parameters */ + if (checkAttribute(p, "tmap:in:numinputs", "0")) { + continue; + } + int byref = GetFlag(p, "tmap:in:byref"); + Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%d)\n", byref); + } + Printf(s_arginfo, "ZEND_END_ARG_INFO()\n"); + } + + /* ------------------------------------------------------------ + * dispatchFunction() + * ------------------------------------------------------------ */ + void dispatchFunction(Node *n) { + /* Last node in overloaded chain */ + + int maxargs; + String *tmp = NewStringEmpty(); + if (Swig_directorclass(n) && wrapperType == directorconstructor) { + /* We have an extra 'this' parameter. */ + SetFlag(n, "wrap:this"); + } + String *dispatch = Swig_overload_dispatch(n, "%s(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;", &maxargs); + + /* Generate a dispatch wrapper for all overloaded functions */ + + Wrapper *f = NewWrapper(); + String *symname = Getattr(n, "sym:name"); + String *wname = Swig_name_wrapper(symname); + + create_command(symname, wname, n); + Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); + + Wrapper_add_local(f, "argc", "int argc"); + + Printf(tmp, "zval **argv[%d]", maxargs); + Wrapper_add_local(f, "argv", tmp); + + Printf(f->code, "argc = ZEND_NUM_ARGS();\n"); + + Printf(f->code, "zend_get_parameters_array_ex(argc,argv);\n"); + + Replaceall(dispatch, "$args", "self,args"); + + Printv(f->code, dispatch, "\n", NIL); + + Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n"); + Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname); + Printv(f->code, "SWIG_FAIL(TSRMLS_C);\n", NIL); + + Printv(f->code, "}\n", NIL); + Wrapper_print(f, s_wrappers); + + DelWrapper(f); + Delete(dispatch); + Delete(tmp); + Delete(wname); + } + + /* ------------------------------------------------------------ + * functionWrapper() + * ------------------------------------------------------------ */ + + /* Helper method for PHP5::functionWrapper */ + bool is_class(SwigType *t) { + Node *n = classLookup(t); + if (n) { + String *r = Getattr(n, "php:proxy"); // Set by classDeclaration() + if (!r) + r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name + if (r) + return true; + } + return false; + } + + virtual int functionWrapper(Node *n) { + String *name = GetChar(n, "name"); + String *iname = GetChar(n, "sym:name"); + SwigType *d = Getattr(n, "type"); + ParmList *l = Getattr(n, "parms"); + String *nodeType = Getattr(n, "nodeType"); + int newobject = GetFlag(n, "feature:new"); + int constructor = (Cmp(nodeType, "constructor") == 0); + + Parm *p; + int i; + int numopt; + String *tm; + Wrapper *f; + + String *wname; + int overloaded = 0; + String *overname = 0; + + if (Cmp(nodeType, "destructor") == 0) { + // We just generate the Zend List Destructor and let Zend manage the + // reference counting. There's no explicit destructor, but the user can + // just do `$obj = null;' to remove a reference to an object. + return CreateZendListDestructor(n); + } + // Test for overloading; + if (Getattr(n, "sym:overloaded")) { + overloaded = 1; + overname = Getattr(n, "sym:overname"); + } else { + if (!addSymbol(iname, n)) + return SWIG_ERROR; + } + + wname = Swig_name_wrapper(iname); + if (overname) { + Printf(wname, "%s", overname); + } + + f = NewWrapper(); + + String *outarg = NewStringEmpty(); + String *cleanup = NewStringEmpty(); + + Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); + + emit_parameter_variables(l, f); + /* Attach standard typemaps */ + + emit_attach_parmmaps(l, f); + // Not issued for overloaded functions. + if (!overloaded) { + create_command(iname, wname, n); + } + + // wrap:parms is used by overload resolution. + Setattr(n, "wrap:parms", l); + + int num_arguments = emit_num_arguments(l); + int num_required = emit_num_required(l); + numopt = num_arguments - num_required; + + if (wrapperType == directorconstructor) + num_arguments++; + + if (num_arguments > 0) { + String *args = NewStringEmpty(); + if (wrapperType == directorconstructor) + Wrapper_add_local(f, "arg0", "zval *arg0"); + Printf(args, "zval **args[%d]", num_arguments); + Wrapper_add_local(f, "args", args); + Delete(args); + args = NULL; + } + + // This generated code may be called: + // 1) as an object method, or + // 2) as a class-method/function (without a "this_ptr") + // Option (1) has "this_ptr" for "this", option (2) needs it as + // first parameter + + // NOTE: possible we ignore this_ptr as a param for native constructor + + Printf(f->code, "SWIG_ResetError(TSRMLS_C);\n"); + + if (numopt > 0) { // membervariable wrappers do not have optional args + Wrapper_add_local(f, "arg_count", "int arg_count"); + Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n"); + Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments); + Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n"); + Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n"); + } else { + if (num_arguments == 0) { + Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n"); + } else { + Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments); + } + Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n"); + } + if (wrapperType == directorconstructor) + Printf(f->code, "arg0 = *args[0];\n \n"); + + /* Now convert from PHP to C variables */ + // At this point, argcount if used is the number of deliberately passed args + // not including this_ptr even if it is used. + // It means error messages may be out by argbase with error + // reports. We can either take argbase into account when raising + // errors, or find a better way of dealing with _thisptr. + // I would like, if objects are wrapped, to assume _thisptr is always + // _this and not the first argument. + // This may mean looking at Language::memberfunctionHandler + + int limit = num_arguments; + if (wrapperType == directorconstructor) + limit--; + for (i = 0, p = l; i < limit; i++) { + String *source; + + /* Skip ignored arguments */ + //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");} + while (checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + } + + SwigType *pt = Getattr(p, "type"); + + if (wrapperType == directorconstructor) { + source = NewStringf("args[%d]", i+1); + } else { + source = NewStringf("args[%d]", i); + } + + String *ln = Getattr(p, "lname"); + + /* Check if optional */ + if (i >= num_required) { + Printf(f->code, "\tif(arg_count > %d) {\n", i); + } + + if ((tm = Getattr(p, "tmap:in"))) { + Replaceall(tm, "$source", source); + Replaceall(tm, "$target", ln); + Replaceall(tm, "$input", source); + Setattr(p, "emit:input", source); + Printf(f->code, "%s\n", tm); + if (i == 0 && Getattr(p, "self")) { + Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n"); + } + p = Getattr(p, "tmap:in:next"); + if (i >= num_required) { + Printf(f->code, "}\n"); + } + continue; + } else { + Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); + } + if (i >= num_required) { + Printf(f->code, "\t}\n"); + } + Delete(source); + } + + if (is_member_director(n)) { + Wrapper_add_local(f, "upcall", "bool upcall = false"); + Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method((char *)\"%s%s\", (char *)\"%s\" TSRMLS_CC);\n", + prefix, Swig_class_name(Swig_methodclass(n)), name); + } + + Swig_director_emit_dynamic_cast(n, f); + + /* Insert constraint checking code */ + for (p = l; p;) { + if ((tm = Getattr(p, "tmap:check"))) { + Replaceall(tm, "$target", Getattr(p, "lname")); + Printv(f->code, tm, "\n", NIL); + p = Getattr(p, "tmap:check:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert cleanup code */ + for (i = 0, p = l; p; i++) { + if ((tm = Getattr(p, "tmap:freearg"))) { + Replaceall(tm, "$source", Getattr(p, "lname")); + Printv(cleanup, tm, "\n", NIL); + p = Getattr(p, "tmap:freearg:next"); + } else { + p = nextSibling(p); + } + } + + /* Insert argument output code */ + bool hasargout = false; + for (i = 0, p = l; p; i++) { + if ((tm = Getattr(p, "tmap:argout"))) { + hasargout = true; + Replaceall(tm, "$source", Getattr(p, "lname")); + // Replaceall(tm,"$input",Getattr(p,"lname")); + Replaceall(tm, "$target", "return_value"); + Replaceall(tm, "$result", "return_value"); + Replaceall(tm, "$arg", Getattr(p, "emit:input")); + Replaceall(tm, "$input", Getattr(p, "emit:input")); + Printv(outarg, tm, "\n", NIL); + p = Getattr(p, "tmap:argout:next"); + } else { + p = nextSibling(p); + } + } + + Setattr(n, "wrap:name", wname); + + /* emit function call */ + String *actioncode = emit_action(n); + + if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { + Replaceall(tm, "$input", Swig_cresult_name()); + Replaceall(tm, "$source", Swig_cresult_name()); + Replaceall(tm, "$target", "return_value"); + Replaceall(tm, "$result", "return_value"); + Replaceall(tm, "$owner", newobject ? "1" : "0"); + Printf(f->code, "%s\n", tm); + } else { + Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name); + } + emit_return_variable(n, d, f); + + if (outarg) { + Printv(f->code, outarg, NIL); + } + + if (cleanup) { + Printv(f->code, cleanup, NIL); + } + + /* Look to see if there is any newfree cleanup code */ + if (GetFlag(n, "feature:new")) { + if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) { + Printf(f->code, "%s\n", tm); + Delete(tm); + } + } + + /* See if there is any return cleanup code */ + if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { + Printf(f->code, "%s\n", tm); + Delete(tm); + } + + Printf(f->code, "thrown:\n"); + Printf(f->code, "return;\n"); + + /* Error handling code */ + Printf(f->code, "fail:\n"); + Printv(f->code, cleanup, NIL); + Append(f->code, "SWIG_FAIL(TSRMLS_C);\n"); + + Printf(f->code, "}\n"); + + Replaceall(f->code, "$cleanup", cleanup); + Replaceall(f->code, "$symname", iname); + + Wrapper_print(f, s_wrappers); + DelWrapper(f); + f = NULL; + + if (overloaded && !Getattr(n, "sym:nextSibling")) { + dispatchFunction(n); + } + + Delete(wname); + wname = NULL; + + if (!shadow) { + return SWIG_OK; + } + + // Handle getters and setters. + if (wrapperType == membervar) { + const char *p = Char(iname); + if (strlen(p) > 4) { + p += strlen(p) - 4; + String *varname = Getattr(n, "membervariableHandler:sym:name"); + if (strcmp(p, "_get") == 0) { + Setattr(shadow_get_vars, varname, Getattr(n, "type")); + } else if (strcmp(p, "_set") == 0) { + Setattr(shadow_set_vars, varname, iname); + } + } + return SWIG_OK; + } + + // Only look at non-overloaded methods and the last entry in each overload + // chain (we check the last so that wrap:parms and wrap:name have been set + // for them all). + if (overloaded && Getattr(n, "sym:nextSibling") != 0) + return SWIG_OK; + + if (!s_oowrappers) + s_oowrappers = NewStringEmpty(); + + if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard || wrapperType == staticmembervar) { + bool handle_as_overload = false; + String **arg_names; + String **arg_values; + // Method or static method or plain function. + const char *methodname = 0; + String *output = s_oowrappers; + if (constructor) { + class_has_ctor = true; + // Skip the Foo:: prefix. + char *ptr = strrchr(GetChar(Swig_methodclass(n), "sym:name"), ':'); + if (ptr) { + ptr++; + } else { + ptr = GetChar(Swig_methodclass(n), "sym:name"); + } + if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) { + methodname = "__construct"; + } else { + // The class has multiple constructors and this one is + // renamed, so this will be a static factory function + methodname = GetChar(n, "constructorHandler:sym:name"); + } + } else if (wrapperType == memberfn) { + methodname = Char(Getattr(n, "memberfunctionHandler:sym:name")); + } else if (wrapperType == staticmemberfn) { + methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name")); + } else if (wrapperType == staticmembervar) { + // Static member variable, wrapped as a function due to PHP limitations. + methodname = Char(Getattr(n, "staticmembervariableHandler:sym:name")); + } else { // wrapperType == standard + methodname = Char(iname); + if (!s_fakeoowrappers) + s_fakeoowrappers = NewStringEmpty(); + output = s_fakeoowrappers; + } + + bool really_overloaded = overloaded ? true : false; + int min_num_of_arguments = emit_num_required(l); + int max_num_of_arguments = emit_num_arguments(l); + + Hash *ret_types = NewHash(); + Setattr(ret_types, d, d); + + bool non_void_return = (Cmp(d, "void") != 0); + + if (overloaded) { + // Look at all the overloaded versions of this method in turn to + // decide if it's really an overloaded method, or just one where some + // parameters have default values. + Node *o = Getattr(n, "sym:overloaded"); + while (o) { + if (o == n) { + o = Getattr(o, "sym:nextSibling"); + continue; + } + + SwigType *d2 = Getattr(o, "type"); + if (!d2) { + assert(constructor); + } else if (!Getattr(ret_types, d2)) { + Setattr(ret_types, d2, d2); + non_void_return = non_void_return || (Cmp(d2, "void") != 0); + } + + ParmList *l2 = Getattr(o, "wrap:parms"); + int num_arguments = emit_num_arguments(l2); + int num_required = emit_num_required(l2); + if (num_required < min_num_of_arguments) + min_num_of_arguments = num_required; + + if (num_arguments > max_num_of_arguments) { + max_num_of_arguments = num_arguments; + } + o = Getattr(o, "sym:nextSibling"); + } + + o = Getattr(n, "sym:overloaded"); + while (o) { + if (o == n) { + o = Getattr(o, "sym:nextSibling"); + continue; + } + + ParmList *l2 = Getattr(o, "wrap:parms"); + Parm *p = l, *p2 = l2; + if (wrapperType == memberfn) { + p = nextSibling(p); + p2 = nextSibling(p2); + } + while (p && p2) { + if (Cmp(Getattr(p, "type"), Getattr(p2, "type")) != 0) + break; + if (Cmp(Getattr(p, "name"), Getattr(p2, "name")) != 0) + break; + String *value = Getattr(p, "value"); + String *value2 = Getattr(p2, "value"); + if (value && !value2) + break; + if (!value && value2) + break; + if (value) { + if (Cmp(value, value2) != 0) + break; + } + p = nextSibling(p); + p2 = nextSibling(p2); + } + if (p && p2) + break; + // One parameter list is a prefix of the other, so check that all + // remaining parameters of the longer list are optional. + if (p2) + p = p2; + while (p && Getattr(p, "value")) + p = nextSibling(p); + if (p) + break; + o = Getattr(o, "sym:nextSibling"); + } + if (!o) { + // This "overloaded method" is really just one with default args. + really_overloaded = false; + } + } + + if (wrapperType == memberfn) { + // Allow for the "this" pointer. + --min_num_of_arguments; + --max_num_of_arguments; + } + + arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *)); + if (!arg_names) { + /* FIXME: How should this be handled? The rest of SWIG just seems + * to not bother checking for malloc failing! */ + fprintf(stderr, "Malloc failed!\n"); + exit(1); + } + for (i = 0; i < max_num_of_arguments; ++i) { + arg_names[i] = NULL; + } + + arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *)); + if (!arg_values) { + /* FIXME: How should this be handled? The rest of SWIG just seems + * to not bother checking for malloc failing! */ + fprintf(stderr, "Malloc failed!\n"); + exit(1); + } + for (i = 0; i < max_num_of_arguments; ++i) { + arg_values[i] = NULL; + } + + Node *o; + if (overloaded) { + o = Getattr(n, "sym:overloaded"); + } else { + o = n; + } + while (o) { + int argno = 0; + Parm *p = Getattr(o, "wrap:parms"); + if (wrapperType == memberfn) + p = nextSibling(p); + while (p) { + if (GetInt(p, "tmap:in:numinputs") == 0) { + p = nextSibling(p); + continue; + } + assert(0 <= argno && argno < max_num_of_arguments); + String *&pname = arg_names[argno]; + const char *pname_cstr = GetChar(p, "name"); + // Just get rid of the C++ namespace part for now. + const char *ptr = NULL; + if (pname_cstr && (ptr = strrchr(pname_cstr, ':'))) { + pname_cstr = ptr + 1; + } + if (!pname_cstr) { + // Unnamed parameter, e.g. int foo(int); + } else if (!pname) { + pname = NewString(pname_cstr); + } else { + size_t len = strlen(pname_cstr); + size_t spc = 0; + size_t len_pname = strlen(Char(pname)); + while (spc + len <= len_pname) { + if (strncmp(pname_cstr, Char(pname) + spc, len) == 0) { + char ch = ((char *) Char(pname))[spc + len]; + if (ch == '\0' || ch == ' ') { + // Already have this pname_cstr. + pname_cstr = NULL; + break; + } + } + char *p = strchr(Char(pname) + spc, ' '); + if (!p) + break; + spc = (p + 4) - Char(pname); + } + if (pname_cstr) { + Printf(pname, " or_%s", pname_cstr); + } + } + String *value = NewString(Getattr(p, "value")); + if (Len(value)) { + /* Check that value is a valid constant in PHP (and adjust it if + * necessary, or replace it with "?" if it's just not valid). */ + SwigType *type = Getattr(p, "type"); + switch (SwigType_type(type)) { + case T_BOOL: { + if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0) + break; + char *p; + errno = 0; + long n = strtol(Char(value), &p, 0); + Clear(value); + if (errno || *p) { + Append(value, "?"); + } else if (n) { + Append(value, "true"); + } else { + Append(value, "false"); + } + break; + } + case T_CHAR: + case T_SCHAR: + case T_SHORT: + case T_INT: + case T_LONG: + case T_LONGLONG: { + char *p; + errno = 0; + long n = strtol(Char(value), &p, 0); + (void) n; + if (errno || *p) { + Clear(value); + Append(value, "?"); + } + break; + } + case T_UCHAR: + case T_USHORT: + case T_UINT: + case T_ULONG: + case T_ULONGLONG: { + char *p; + errno = 0; + unsigned int n = strtoul(Char(value), &p, 0); + (void) n; + if (errno || *p) { + Clear(value); + Append(value, "?"); + } + break; + } + case T_FLOAT: + case T_DOUBLE: + case T_LONGDOUBLE: { + char *p; + errno = 0; + /* FIXME: strtod is locale dependent... */ + double val = strtod(Char(value), &p); + if (errno || *p) { + Clear(value); + Append(value, "?"); + } else if (strchr(Char(value), '.') == 0) { + // Ensure value is a double constant, not an integer one. + Append(value, ".0"); + double val2 = strtod(Char(value), &p); + if (errno || *p || val != val2) { + Clear(value); + Append(value, "?"); + } + } + break; + } + case T_STRING: + if (Len(value) < 2) { + // How can a string (including "" be less than 2 characters?) + Clear(value); + Append(value, "?"); + } else { + const char *v = Char(value); + if (v[0] != '"' || v[Len(value) - 1] != '"') { + Clear(value); + Append(value, "?"); + } + // Strings containing "$" require special handling, but we do + // that later. + } + break; + case T_VOID: + assert(false); + break; + case T_POINTER: { + const char *v = Char(value); + if (v[0] == '(') { + // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc. + v += strcspn(v + 1, "*()") + 1; + if (*v == '*') { + do { + v++; + v += strspn(v, " \t"); + } while (*v == '*'); + if (*v++ == ')') { + v += strspn(v, " \t"); + String * old = value; + value = NewString(v); + Delete(old); + } + } + } + if (Strcmp(value, "NULL") == 0 || + Strcmp(value, "nullptr") == 0 || + Strcmp(value, "0") == 0 || + Strcmp(value, "0L") == 0) { + Clear(value); + Append(value, "null"); + } else { + Clear(value); + Append(value, "?"); + } + break; + } + default: + /* Safe default */ + Clear(value); + Append(value, "?"); + break; + } + + if (!arg_values[argno]) { + arg_values[argno] = value; + value = NULL; + } else if (Cmp(arg_values[argno], value) != 0) { + // If a parameter has two different default values in + // different overloaded forms of the function, we can't + // set its default in PHP. Flag this by setting its + // default to `?'. + Delete(arg_values[argno]); + arg_values[argno] = NewString("?"); + } + } else if (arg_values[argno]) { + // This argument already has a default value in another overloaded + // form, but doesn't in this form. So don't try to do anything + // clever, just let the C wrappers resolve the overload and set the + // default values. + // + // This handling is safe, but I'm wondering if it may be overly + // conservative (FIXME) in some cases. It seems it's only bad when + // there's an overloaded form with the appropriate number of + // parameters which doesn't want the default value, but I need to + // think about this more. + Delete(arg_values[argno]); + arg_values[argno] = NewString("?"); + } + Delete(value); + p = nextSibling(p); + ++argno; + } + if (!really_overloaded) + break; + o = Getattr(o, "sym:nextSibling"); + } + + /* Clean up any parameters which haven't yet got names, or whose + * names clash. */ + Hash *seen = NewHash(); + /* We need $this to refer to the current class, so can't allow it + * to be used as a parameter. */ + Setattr(seen, "this", seen); + /* We use $r to store the return value, so disallow that as a parameter + * name in case the user uses the "call-time pass-by-reference" feature + * (it's deprecated and off by default in PHP5, but we want to be + * maximally portable). Similarly we use $c for the classname or new + * stdClass object. + */ + Setattr(seen, "r", seen); + Setattr(seen, "c", seen); + + for (int argno = 0; argno < max_num_of_arguments; ++argno) { + String *&pname = arg_names[argno]; + if (pname) { + Replaceall(pname, " ", "_"); + } else { + /* We get here if the SWIG .i file has "int foo(int);" */ + pname = NewStringEmpty(); + Printf(pname, "arg%d", argno + 1); + } + // Check if we've already used this parameter name. + while (Getattr(seen, pname)) { + // Append "_" to clashing names until they stop clashing... + Printf(pname, "_"); + } + Setattr(seen, Char(pname), seen); + + if (arg_values[argno] && Cmp(arg_values[argno], "?") == 0) { + handle_as_overload = true; + } + } + Delete(seen); + seen = NULL; + + String *invoke = NewStringEmpty(); + String *prepare = NewStringEmpty(); + String *args = NewStringEmpty(); + + if (!handle_as_overload && !(really_overloaded && max_num_of_arguments > min_num_of_arguments)) { + Printf(invoke, "%s(", iname); + if (wrapperType == memberfn) { + Printf(invoke, "$this->%s", SWIG_PTR); + } + for (int i = 0; i < max_num_of_arguments; ++i) { + if (i) + Printf(args, ","); + if (i || wrapperType == memberfn) + Printf(invoke, ","); + String *value = arg_values[i]; + if (value) { + const char *v = Char(value); + if (v[0] == '"') { + /* In a PHP double quoted string, $ needs to be escaped as \$. */ + Replaceall(value, "$", "\\$"); + } + Printf(args, "$%s=%s", arg_names[i], value); + } else { + Printf(args, "$%s", arg_names[i]); + } + Printf(invoke, "$%s", arg_names[i]); + } + Printf(invoke, ")"); + } else { + int i; + for (i = 0; i < min_num_of_arguments; ++i) { + if (i) + Printf(args, ","); + Printf(args, "$%s", arg_names[i]); + } + String *invoke_args = NewStringEmpty(); + if (wrapperType == memberfn) { + Printf(invoke_args, "$this->%s", SWIG_PTR); + if (min_num_of_arguments > 0) + Printf(invoke_args, ","); + } + Printf(invoke_args, "%s", args); + bool had_a_case = false; + int last_handled_i = i - 1; + for (; i < max_num_of_arguments; ++i) { + if (i) + Printf(args, ","); + const char *value = Char(arg_values[i]); + // FIXME: (really_overloaded && handle_as_overload) is perhaps a + // little conservative, but it doesn't hit any cases that it + // shouldn't for Xapian at least (and we need it to handle + // "Enquire::get_mset()" correctly). + bool non_php_default = ((really_overloaded && handle_as_overload) || + !value || strcmp(value, "?") == 0); + if (non_php_default) + value = "null"; + Printf(args, "$%s=%s", arg_names[i], value); + if (non_php_default) { + if (!had_a_case) { + Printf(prepare, "\t\tswitch (func_num_args()) {\n"); + had_a_case = true; + } + Printf(prepare, "\t\t"); + while (last_handled_i < i) { + Printf(prepare, "case %d: ", ++last_handled_i); + } + if (non_void_return) { + if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { + Append(prepare, "$r="); + } else { + Printf(prepare, "$this->%s=", SWIG_PTR); + } + } + if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { + Printf(prepare, "%s(%s); break;\n", iname, invoke_args); + } else if (!i) { + Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args); + } else { + Printf(prepare, "%s($_this, %s); break;\n", iname, invoke_args); + } + } + if (i || wrapperType == memberfn) + Printf(invoke_args, ","); + Printf(invoke_args, "$%s", arg_names[i]); + } + Printf(prepare, "\t\t"); + if (had_a_case) + Printf(prepare, "default: "); + if (non_void_return) { + if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { + Append(prepare, "$r="); + } else { + Printf(prepare, "$this->%s=", SWIG_PTR); + } + } + + if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { + Printf(prepare, "%s(%s);\n", iname, invoke_args); + } else { + Printf(prepare, "%s($_this, %s);\n", iname, invoke_args); + } + if (had_a_case) + Printf(prepare, "\t\t}\n"); + Delete(invoke_args); + Printf(invoke, "$r"); + } + + Printf(output, "\n"); + // If it's a member function or a class constructor... + if (wrapperType == memberfn || (constructor && current_class)) { + String *acc = NewString(Getattr(n, "access")); + // If a base has the same method with public access, then PHP + // requires to have it here as public as well + Node *bases = Getattr(Swig_methodclass(n), "bases"); + if (bases && Strcmp(acc, "public") != 0) { + String *warnmsg = 0; + int haspublicbase = 0; + Iterator i = First(bases); + while (i.item) { + Node *j = firstChild(i.item); + while (j) { + String *jname = Getattr(j, "name"); + if (!jname || Strcmp(jname, Getattr(n, "name")) != 0) { + j = nextSibling(j); + continue; + } + if (Strcmp(nodeType(j), "cdecl") == 0) { + if (!Getattr(j, "access") || checkAttribute(j, "access", "public")) { + haspublicbase = 1; + } + } else if (Strcmp(nodeType(j), "using") == 0 && firstChild(j) && Strcmp(nodeType(firstChild(j)), "cdecl") == 0) { + if (!Getattr(firstChild(j), "access") || checkAttribute(firstChild(j), "access", "public")) { + haspublicbase = 1; + } + } + if (haspublicbase) { + warnmsg = NewStringf("Modifying the access of '%s::%s' to public, as the base '%s' has it as public as well.\n", Getattr(current_class, "classtype"), Getattr(n, "name"), Getattr(i.item, "classtype")); + break; + } + j = nextSibling(j); + } + i = Next(i); + if (haspublicbase) { + break; + } + } + if (Getattr(n, "access") && haspublicbase) { + Delete(acc); + acc = NewStringEmpty(); // implicitly public + Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg)); + Delete(warnmsg); + } + } + + if (Cmp(acc, "public") == 0) { + // The default visibility for methods is public, so don't specify + // that explicitly to keep the wrapper size down. + Delete(acc); + acc = NewStringEmpty(); + } else if (Cmp(acc, "") != 0) { + Append(acc, " "); + } + + if (constructor) { + const char * arg0; + if (max_num_of_arguments > 0) { + arg0 = Char(arg_names[0]); + } else { + arg0 = "res"; + Delete(args); + args = NewString("$res=null"); + } + String *mangled_type = SwigType_manglestr(Getattr(n, "type")); + Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); + Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type); + Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0); + Printf(output, "\t\t\treturn;\n"); + Printf(output, "\t\t}\n"); + } else { + Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); + } + Delete(acc); + } else if (wrapperType == staticmembervar) { + // We're called twice for a writable static member variable - first + // with "foo_set" and then with "foo_get" - so generate half the + // wrapper function each time. + // + // For a const static member, we only get called once. + static bool started = false; + if (!started) { + Printf(output, "\tstatic function %s() {\n", methodname); + if (max_num_of_arguments) { + // Setter. + Printf(output, "\t\tif (func_num_args()) {\n"); + Printf(output, "\t\t\t%s(func_get_arg(0));\n", iname); + Printf(output, "\t\t\treturn;\n"); + Printf(output, "\t\t}\n"); + started = true; + goto done; + } + } + started = false; + } else { + Printf(output, "\tstatic function %s(%s) {\n", methodname, args); + } + + if (!newobject) + Printf(output, "%s", prepare); + if (constructor) { + if (!directorsEnabled() || !Swig_directorclass(n)) { + if (!Len(prepare)) { + if (strcmp(methodname, "__construct") == 0) { + Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke); + } else { + String *classname = Swig_class_name(current_class); + Printf(output, "\t\treturn new %s%s(%s);\n", prefix, classname, invoke); + } + } + } else { + Node *parent = Swig_methodclass(n); + String *classname = Swig_class_name(parent); + Printf(output, "\t\tif (get_class($this) === '%s%s') {\n", prefix, classname); + Printf(output, "\t\t\t$_this = null;\n"); + Printf(output, "\t\t} else {\n"); + Printf(output, "\t\t\t$_this = $this;\n"); + Printf(output, "\t\t}\n"); + if (!Len(prepare)) { + if (num_arguments > 1) { + Printf(output, "\t\t$this->%s=%s($_this, %s);\n", SWIG_PTR, iname, args); + } else { + Printf(output, "\t\t$this->%s=%s($_this);\n", SWIG_PTR, iname); + } + } + } + Printf(output, "%s", prepare); + } else if (!non_void_return && !hasargout) { + if (Cmp(invoke, "$r") != 0) + Printf(output, "\t\t%s;\n", invoke); + } else if (is_class(d)) { + if (Cmp(invoke, "$r") != 0) + Printf(output, "\t\t$r=%s;\n", invoke); + if (Len(ret_types) == 1) { + /* If d is abstract we can't create a new wrapper type d. */ + Node *d_class = classLookup(d); + int is_abstract = 0; + if (Getattr(d_class, "abstracts")) { + is_abstract = 1; + } + if (newobject || !is_abstract) { + Printf(output, "\t\tif (is_resource($r)) {\n"); + if (Getattr(classLookup(Getattr(n, "type")), "module")) { + /* + * _p_Foo -> Foo, _p_ns__Bar -> Bar + * TODO: do this in a more elegant way + */ + if (Len(prefix) == 0) { + Printf(output, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n"); + } else { + Printf(output, "\t\t\t$c='%s'.substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n", prefix); + } + Printf(output, "\t\t\tif (class_exists($c)) return new $c($r);\n"); + Printf(output, "\t\t\treturn new %s%s($r);\n", prefix, Getattr(classLookup(d), "sym:name")); + } else { + Printf(output, "\t\t\t$c = new stdClass();\n"); + Printf(output, "\t\t\t$c->" SWIG_PTR " = $r;\n"); + Printf(output, "\t\t\treturn $c;\n"); + } + Printf(output, "\t\t}\n\t\treturn $r;\n"); + } else { + Printf(output, "\t\t$this->%s = $r;\n", SWIG_PTR); + Printf(output, "\t\treturn $this;\n"); + } + } else { + Printf(output, "\t\tif (!is_resource($r)) return $r;\n"); + String *wrapobj = NULL; + String *common = NULL; + Iterator i = First(ret_types); + while (i.item) { + SwigType *ret_type = i.item; + i = Next(i); + String *mangled = NewString("_p"); + Printf(mangled, "%s", SwigType_manglestr(ret_type)); + Node *class_node = Getattr(zend_types, mangled); + if (!class_node) { + /* This is needed when we're returning a pointer to a type + * rather than returning the type by value or reference. */ + Delete(mangled); + mangled = NewString(SwigType_manglestr(ret_type)); + class_node = Getattr(zend_types, mangled); + if (!class_node) { + // Return type isn't an object, so will be handled by the + // !is_resource() check before the switch. + continue; + } + } + const char *classname = GetChar(class_node, "sym:name"); + if (!classname) + classname = GetChar(class_node, "name"); + String * action = NewStringEmpty(); + if (classname) + Printf(action, "return new %s%s($r);\n", prefix, classname); + else + Printf(action, "return $r;\n"); + if (!wrapobj) { + wrapobj = NewString("\t\tswitch (get_resource_type($r)) {\n"); + common = action; + } else { + if (common && Cmp(common, action) != 0) { + Delete(common); + common = NULL; + } + } + Printf(wrapobj, "\t\t"); + if (i.item) { + Printf(wrapobj, "case '%s': ", mangled); + } else { + Printf(wrapobj, "default: "); + } + Printv(wrapobj, action, NIL); + if (action != common) Delete(action); + Delete(mangled); + } + Printf(wrapobj, "\t\t}\n"); + if (common) { + // All cases have the same action, so eliminate the switch + // wrapper. + Printf(output, "\t\t%s", common); + Delete(common); + } else { + Printv(output, wrapobj, NIL); + } + Delete(wrapobj); + } + } else { + if (non_void_return) { + Printf(output, "\t\treturn %s;\n", invoke); + } else if (Cmp(invoke, "$r") != 0) { + Printf(output, "\t\t%s;\n", invoke); + } + } + Printf(output, "\t}\n"); + +done: + Delete(prepare); + Delete(invoke); + free(arg_values); + + Delete(args); + args = NULL; + + for (int i = 0; i < max_num_of_arguments; ++i) { + Delete(arg_names[i]); + } + free(arg_names); + arg_names = NULL; + } + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * globalvariableHandler() + * ------------------------------------------------------------ */ + + virtual int globalvariableHandler(Node *n) { + char *name = GetChar(n, "name"); + char *iname = GetChar(n, "sym:name"); + SwigType *t = Getattr(n, "type"); + String *tm; + + /* First do the wrappers such as name_set(), name_get() + * as provided by the baseclass's implementation of variableWrapper + */ + if (Language::globalvariableHandler(n) == SWIG_NOWRAP) { + return SWIG_NOWRAP; + } + + if (!addSymbol(iname, n)) + return SWIG_ERROR; + + /* First link C variables to PHP */ + + tm = Swig_typemap_lookup("varinit", n, name, 0); + if (tm) { + Replaceall(tm, "$target", name); + Printf(s_vinit, "%s\n", tm); + } else { + Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0)); + } + + /* Now generate PHP -> C sync blocks */ + /* + tm = Swig_typemap_lookup("varin", n, name, 0); + if(tm) { + Replaceall(tm, "$symname", iname); + Printf(f_c->code, "%s\n", tm); + } else { + Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0)); + } + */ + /* Now generate C -> PHP sync blocks */ + /* + if(!GetFlag(n,"feature:immutable")) { + + tm = Swig_typemap_lookup("varout", n, name, 0); + if(tm) { + Replaceall(tm, "$symname", iname); + Printf(f_php->code, "%s\n", tm); + } else { + Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0)); + } + } + */ + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constantWrapper() + * ------------------------------------------------------------ */ + + virtual int constantWrapper(Node *n) { + String *name = GetChar(n, "name"); + String *iname = GetChar(n, "sym:name"); + SwigType *type = Getattr(n, "type"); + String *rawval = Getattr(n, "rawval"); + String *value = rawval ? rawval : Getattr(n, "value"); + String *tm; + + if (!addSymbol(iname, n)) + return SWIG_ERROR; + + SwigType_remember(type); + + if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) { + Replaceall(tm, "$source", value); + Replaceall(tm, "$target", name); + Replaceall(tm, "$value", value); + Printf(s_cinit, "%s\n", tm); + } + + if (shadow) { + String *enumvalue = GetChar(n, "enumvalue"); + String *set_to = iname; + + if (!enumvalue) { + enumvalue = GetChar(n, "enumvalueex"); + } + + if (enumvalue && *Char(enumvalue)) { + // Check for a simple constant expression which is valid in PHP. + // If we find one, initialise the const member with it; otherwise + // we initialise it using the C/C++ wrapped constant. + const char *p; + for (p = Char(enumvalue); *p; ++p) { + if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) { + // FIXME: enhance to handle ` + 1' which is what + // we get for enums that don't have an explicit value set. + break; + } + } + if (!*p) + set_to = enumvalue; + } + + if (wrapping_member_constant) { + if (!s_oowrappers) + s_oowrappers = NewStringEmpty(); + Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, set_to); + } else { + if (!s_fakeoowrappers) + s_fakeoowrappers = NewStringEmpty(); + Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", iname, set_to); + } + } + + return SWIG_OK; + } + + /* + * PHP5::pragma() + * + * Pragma directive. + * + * %pragma(php) code="String" # Includes a string in the .php file + * %pragma(php) include="file.php" # Includes a file in the .php file + */ + + virtual int pragmaDirective(Node *n) { + if (!ImportMode) { + String *lang = Getattr(n, "lang"); + String *type = Getattr(n, "name"); + String *value = Getattr(n, "value"); + + if (Strcmp(lang, "php") == 0 || Strcmp(lang, "php4") == 0) { + if (Strcmp(type, "code") == 0) { + if (value) { + Printf(pragma_code, "%s\n", value); + } + } else if (Strcmp(type, "include") == 0) { + if (value) { + Printf(pragma_incl, "include '%s';\n", value); + } + } else if (Strcmp(type, "phpinfo") == 0) { + if (value) { + Printf(pragma_phpinfo, "%s\n", value); + } + } else { + Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type); + } + } + } + return Language::pragmaDirective(n); + } + + /* ------------------------------------------------------------ + * classDeclaration() + * ------------------------------------------------------------ */ + + virtual int classDeclaration(Node *n) { + if (!Getattr(n, "feature:onlychildren")) { + String *symname = Getattr(n, "sym:name"); + Setattr(n, "php:proxy", symname); + } + + return Language::classDeclaration(n); + } + + /* ------------------------------------------------------------ + * classHandler() + * ------------------------------------------------------------ */ + + virtual int classHandler(Node *n) { + constructors = 0; + current_class = n; + + if (shadow) { + char *rename = GetChar(n, "sym:name"); + + if (!addSymbol(rename, n)) + return SWIG_ERROR; + shadow_classname = NewString(rename); + + shadow_get_vars = NewHash(); + shadow_set_vars = NewHash(); + + /* Deal with inheritance */ + List *baselist = Getattr(n, "bases"); + if (baselist) { + Iterator base = First(baselist); + while (base.item && GetFlag(base.item, "feature:ignore")) { + base = Next(base); + } + base = Next(base); + if (base.item) { + /* Warn about multiple inheritance for additional base class(es) */ + while (base.item) { + if (GetFlag(base.item, "feature:ignore")) { + base = Next(base); + continue; + } + String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0); + String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0); + Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number, + "Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname); + base = Next(base); + } + } + } + } + + classnode = n; + Language::classHandler(n); + classnode = 0; + + if (shadow) { + List *baselist = Getattr(n, "bases"); + Iterator ki, base; + + if (baselist) { + base = First(baselist); + while (base.item && GetFlag(base.item, "feature:ignore")) { + base = Next(base); + } + } else { + base.item = NULL; + } + + if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) { + Printf(s_phpclasses, "abstract "); + } + + Printf(s_phpclasses, "class %s%s ", prefix, shadow_classname); + String *baseclass = NULL; + if (base.item && Getattr(base.item, "module")) { + baseclass = Getattr(base.item, "sym:name"); + if (!baseclass) + baseclass = Getattr(base.item, "name"); + Printf(s_phpclasses, "extends %s%s ", prefix, baseclass); + } else if (GetFlag(n, "feature:exceptionclass")) { + Append(s_phpclasses, "extends Exception "); + } + { + Node *node = NewHash(); + Setattr(node, "type", Getattr(n, "name")); + Setfile(node, Getfile(n)); + Setline(node, Getline(n)); + String * interfaces = Swig_typemap_lookup("phpinterfaces", node, "", 0); + if (interfaces) { + Printf(s_phpclasses, "implements %s ", interfaces); + } + Delete(node); + } + Printf(s_phpclasses, "{\n\tpublic $%s=null;\n", SWIG_PTR); + if (!baseclass) { + // Only store this in the base class (NB !baseclass means we *are* + // a base class...) + Printf(s_phpclasses, "\tprotected $%s=array();\n", SWIG_DATA); + } + + // 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"); + // FIXME: tune this threshold... + if (Len(shadow_set_vars) <= 2) { + // Not many setters, so avoid call_user_func. + for (; ki.key; ki = Next(ki)) { + DOH *key = ki.key; + String *iname = ki.item; + Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, iname, SWIG_PTR); + } + } else { + Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname); + Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s,$value);\n", SWIG_PTR); + } + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR); + if (baseclass) { + Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\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); + if (baseclass) { + Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass); + } else { + Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\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"); + int non_class_getters = 0; + for (; ki.key; ki = Next(ki)) { + DOH *key = ki.key; + SwigType *d = ki.item; + if (!is_class(d)) { + ++non_class_getters; + continue; + } + Printv(s_phpclasses, "\t\tif ($var === '", key, "') return new ", prefix, Getattr(classLookup(d), "sym:name"), "(", shadow_classname, "_", key, "_get($this->", SWIG_PTR, "));\n", NIL); + } + // FIXME: tune this threshold... + if (non_class_getters <= 2) { + // Not many non-class getters, so avoid call_user_func. + for (ki = First(shadow_get_vars); non_class_getters && ki.key; ki = Next(ki)) { + DOH *key = ki.key; + SwigType *d = ki.item; + if (is_class(d)) continue; + Printv(s_phpclasses, "\t\tif ($var === '", key, "') return ", shadow_classname, "_", key, "_get($this->", SWIG_PTR, ");\n", NIL); + --non_class_getters; + } + } else { + Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); + Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s);\n", SWIG_PTR); + } + Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); + } else { + // Reading an unknown property name gives null in PHP. + 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); + if (baseclass) { + Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); + } else { + 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) { + Printf(s_phpclasses, "\tfunction __construct($h) {\n"); + Printf(s_phpclasses, "\t\t$this->%s=$h;\n", SWIG_PTR); + Printf(s_phpclasses, "\t}\n"); + } + + if (s_oowrappers) { + Printf(s_phpclasses, "%s", s_oowrappers); + Delete(s_oowrappers); + s_oowrappers = NULL; + } + class_has_ctor = false; + + Printf(s_phpclasses, "}\n\n"); + + Delete(shadow_classname); + shadow_classname = NULL; + + Delete(shadow_set_vars); + shadow_set_vars = NULL; + Delete(shadow_get_vars); + shadow_get_vars = NULL; + } + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int memberfunctionHandler(Node *n) { + wrapperType = memberfn; + Language::memberfunctionHandler(n); + wrapperType = standard; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * membervariableHandler() + * ------------------------------------------------------------ */ + + virtual int membervariableHandler(Node *n) { + wrapperType = membervar; + Language::membervariableHandler(n); + wrapperType = standard; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmembervariableHandler() + * ------------------------------------------------------------ */ + + virtual int staticmembervariableHandler(Node *n) { + wrapperType = staticmembervar; + Language::staticmembervariableHandler(n); + wrapperType = standard; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * staticmemberfunctionHandler() + * ------------------------------------------------------------ */ + + virtual int staticmemberfunctionHandler(Node *n) { + wrapperType = staticmemberfn; + Language::staticmemberfunctionHandler(n); + wrapperType = standard; + + return SWIG_OK; + } + + int abstractConstructorHandler(Node *) { + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * constructorHandler() + * ------------------------------------------------------------ */ + + virtual int constructorHandler(Node *n) { + constructors++; + if (Swig_directorclass(n)) { + String *name = GetChar(Swig_methodclass(n), "name"); + String *ctype = GetChar(Swig_methodclass(n), "classtype"); + String *sname = GetChar(Swig_methodclass(n), "sym:name"); + String *args = NewStringEmpty(); + ParmList *p = Getattr(n, "parms"); + int i; + + for (i = 0; p; p = nextSibling(p), i++) { + if (i) { + Printf(args, ", "); + } + if (Strcmp(GetChar(p, "type"), SwigType_str(GetChar(p, "type"), 0))) { + SwigType *t = Getattr(p, "type"); + Printf(args, "%s", SwigType_rcaststr(t, 0)); + if (SwigType_isreference(t)) { + Append(args, "*"); + } + } + Printf(args, "arg%d", i+1); + } + + /* director ctor code is specific for each class */ + Delete(director_ctor_code); + director_ctor_code = NewStringEmpty(); + director_prot_ctor_code = NewStringEmpty(); + Printf(director_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); + Printf(director_prot_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); + Printf(director_ctor_code, " %s = (%s *)new %s(%s);\n", Swig_cresult_name(), ctype, ctype, args); + Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args); + if (i) { + Insert(args, 0, ", "); + } + Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0 TSRMLS_CC%s);\n}\n", Swig_cresult_name(), ctype, sname, args); + Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0 TSRMLS_CC%s);\n}\n", Swig_cresult_name(), ctype, sname, args); + Delete(args); + + wrapperType = directorconstructor; + } else { + wrapperType = constructor; + } + Language::constructorHandler(n); + wrapperType = standard; + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * CreateZendListDestructor() + * ------------------------------------------------------------ */ + //virtual int destructorHandler(Node *n) { + //} + int CreateZendListDestructor(Node *n) { + String *name = GetChar(Swig_methodclass(n), "name"); + String *iname = GetChar(n, "sym:name"); + ParmList *l = Getattr(n, "parms"); + + String *destructorname = NewStringEmpty(); + Printf(destructorname, "_%s", Swig_name_wrapper(iname)); + Setattr(classnode, "destructor", destructorname); + + Wrapper *f = NewWrapper(); + Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n"); + Printf(f->def, "/* to typecast and do the actual destruction */\n"); + Printf(f->def, "static void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname); + + Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); + Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL); + Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL); + + emit_parameter_variables(l, f); + emit_attach_parmmaps(l, f); + + // Get type of first arg, thing to be destructed + // Skip ignored arguments + Parm *p = l; + //while (Getattr(p,"tmap:ignore")) {p = Getattr(p,"tmap:ignore:next");} + while (checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + } + SwigType *pt = Getattr(p, "type"); + + Printf(f->code, " efree(value);\n"); + Printf(f->code, " if (! newobject) return; /* can't delete it! */\n"); + Printf(f->code, " arg1 = (%s)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); + Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name)); + + Setattr(n, "wrap:name", destructorname); + + String *actioncode = emit_action(n); + Append(f->code, actioncode); + Delete(actioncode); + + Printf(f->code, "thrown:\n"); + Append(f->code, "return;\n"); + Append(f->code, "fail:\n"); + Append(f->code, "SWIG_FAIL(TSRMLS_C);\n"); + Printf(f->code, "}\n"); + + Wrapper_print(f, s_wrappers); + DelWrapper(f); + + return SWIG_OK; + } + + /* ------------------------------------------------------------ + * memberconstantHandler() + * ------------------------------------------------------------ */ + + virtual int memberconstantHandler(Node *n) { + wrapping_member_constant = Getattr(n, "sym:name"); + Language::memberconstantHandler(n); + wrapping_member_constant = NULL; + return SWIG_OK; + } + + int classDirectorInit(Node *n) { + String *declaration = Swig_director_declaration(n); + Printf(f_directors_h, "%s\n", declaration); + Printf(f_directors_h, "public:\n"); + Delete(declaration); + return Language::classDirectorInit(n); + } + + int classDirectorEnd(Node *n) { + Printf(f_directors_h, "};\n"); + return Language::classDirectorEnd(n); + } + + int classDirectorConstructor(Node *n) { + Node *parent = Getattr(n, "parentNode"); + String *decl = Getattr(n, "decl"); + String *supername = Swig_class_name(parent); + String *classname = NewStringEmpty(); + Printf(classname, "SwigDirector_%s", supername); + + /* insert self parameter */ + Parm *p; + ParmList *superparms = Getattr(n, "parms"); + ParmList *parms = CopyParmList(superparms); + String *type = NewString("zval"); + SwigType_add_pointer(type); + p = NewParm(type, NewString("self"), n); + set_nextSibling(p, parms); + parms = p; + + if (!Getattr(n, "defaultargs")) { + // There should always be a "self" parameter first. + assert(ParmList_len(parms) > 0); + + /* constructor */ + { + Wrapper *w = NewWrapper(); + String *call; + String *basetype = Getattr(parent, "classtype"); + + // We put TSRMLS_DC after the self parameter in order to cope with + // any default parameters. + String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); + const char * p = Char(target); + const char * comma = strchr(p, ','); + int ins = comma ? (int)(comma - p) : Len(target) - 1; + Insert(target, ins, " TSRMLS_DC"); + + call = Swig_csuperclass_call(0, basetype, superparms); + Printf(w->def, "%s::%s: %s, Swig::Director(self TSRMLS_CC) {", classname, target, call); + Append(w->def, "}"); + Delete(target); + Wrapper_print(w, f_directors); + Delete(call); + DelWrapper(w); + } + + /* constructor header */ + { + // We put TSRMLS_DC after the self parameter in order to cope with + // any default parameters. + String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); + const char * p = Char(target); + const char * comma = strchr(p, ','); + int ins = comma ? (int)(comma - p) : Len(target) - 1; + Insert(target, ins, " TSRMLS_DC"); + + Printf(f_directors_h, " %s;\n", target); + Delete(target); + } + } + return Language::classDirectorConstructor(n); + } + + int classDirectorMethod(Node *n, Node *parent, String *super) { + int is_void = 0; + int is_pointer = 0; + String *decl = Getattr(n, "decl"); + String *returntype = Getattr(n, "type"); + String *name = Getattr(n, "name"); + String *classname = Getattr(parent, "sym:name"); + String *c_classname = Getattr(parent, "name"); + String *symname = Getattr(n, "sym:name"); + String *declaration = NewStringEmpty(); + ParmList *l = Getattr(n, "parms"); + Wrapper *w = NewWrapper(); + String *tm; + String *wrap_args = NewStringEmpty(); + String *value = Getattr(n, "value"); + String *storage = Getattr(n, "storage"); + bool pure_virtual = false; + int status = SWIG_OK; + int idx; + bool ignored_method = GetFlag(n, "feature:ignore") ? true : false; + + if (Cmp(storage, "virtual") == 0) { + if (Cmp(value, "0") == 0) { + pure_virtual = true; + } + } + + /* determine if the method returns a pointer */ + is_pointer = SwigType_ispointer_return(decl); + is_void = (Cmp(returntype, "void") == 0 && !is_pointer); + + /* virtual method definition */ + String *target; + String *pclassname = NewStringf("SwigDirector_%s", classname); + String *qualified_name = NewStringf("%s::%s", pclassname, name); + SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); + target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); + Printf(w->def, "%s", target); + Delete(qualified_name); + Delete(target); + /* header declaration */ + target = Swig_method_decl(rtype, decl, name, l, 0, 1); + Printf(declaration, " virtual %s", target); + Delete(target); + + // Get any exception classes in the throws typemap + ParmList *throw_parm_list = 0; + + if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { + Parm *p; + int gencomma = 0; + + Append(w->def, " throw("); + Append(declaration, " throw("); + + if (throw_parm_list) + Swig_typemap_attach_parms("throws", throw_parm_list, 0); + for (p = throw_parm_list; p; p = nextSibling(p)) { + if (Getattr(p, "tmap:throws")) { + if (gencomma++) { + Append(w->def, ", "); + Append(declaration, ", "); + } + String *str = SwigType_str(Getattr(p, "type"), 0); + Append(w->def, str); + Append(declaration, str); + Delete(str); + } + } + + Append(w->def, ")"); + Append(declaration, ")"); + } + + Append(w->def, " {"); + Append(declaration, ";\n"); + + Printf(w->code, "TSRMLS_FETCH_FROM_CTX(swig_zts_ctx);\n"); + + /* declare method return value + * if the return value is a reference or const reference, a specialized typemap must + * handle it, including declaration of c_result ($result). + */ + if (!is_void) { + if (!(ignored_method && !pure_virtual)) { + String *cres = SwigType_lstr(returntype, "c_result"); + Printf(w->code, "%s;\n", cres); + Delete(cres); + } + } + + if (ignored_method) { + if (!pure_virtual) { + if (!is_void) + Printf(w->code, "return "); + String *super_call = Swig_method_call(super, l); + Printf(w->code, "%s;\n", super_call); + Delete(super_call); + } else { + Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\" TSRMLS_CC);\n", SwigType_namestr(c_classname), + SwigType_namestr(name)); + } + } else { + /* attach typemaps to arguments (C/C++ -> PHP) */ + String *parse_args = NewStringEmpty(); + + Swig_director_parms_fixup(l); + + /* remove the wrapper 'w' since it was producing spurious temps */ + Swig_typemap_attach_parms("in", l, 0); + Swig_typemap_attach_parms("directorin", l, 0); + Swig_typemap_attach_parms("directorargout", l, w); + + Parm *p; + char source[256]; + + int outputs = 0; + if (!is_void) + outputs++; + + /* build argument list and type conversion string */ + idx = 0; + p = l; + while (p) { + if (checkAttribute(p, "tmap:in:numinputs", "0")) { + p = Getattr(p, "tmap:in:next"); + continue; + } + + if (Getattr(p, "tmap:directorargout") != 0) + outputs++; + + String *pname = Getattr(p, "name"); + String *ptype = Getattr(p, "type"); + + if ((tm = Getattr(p, "tmap:directorin")) != 0) { + String *parse = Getattr(p, "tmap:directorin:parse"); + if (!parse) { + sprintf(source, "obj%d", idx++); + String *input = NewStringf("&%s", source); + Setattr(p, "emit:directorinput", input); + Replaceall(tm, "$input", input); + Delete(input); + Replaceall(tm, "$owner", "0"); + Printv(wrap_args, "zval ", source, ";\n", NIL); + Printf(wrap_args, "args[%d] = &%s;\n", idx - 1, source); + Printv(wrap_args, "INIT_ZVAL(", source, ");\n", NIL); + + Printv(wrap_args, tm, "\n", NIL); + Putc('O', parse_args); + } else { + Append(parse_args, parse); + Setattr(p, "emit:directorinput", pname); + Replaceall(tm, "$input", pname); + Replaceall(tm, "$owner", "0"); + if (Len(tm) == 0) + Append(tm, pname); + } + p = Getattr(p, "tmap:directorin:next"); + continue; + } else if (Cmp(ptype, "void")) { + Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, + "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0), + SwigType_namestr(c_classname), SwigType_namestr(name)); + status = SWIG_NOWRAP; + break; + } + p = nextSibling(p); + } + + /* exception handling */ + bool error_used_in_typemap = false; + tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0); + if (!tm) { + tm = Getattr(n, "feature:director:except"); + if (tm) + tm = Copy(tm); + } + if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { + if (Replaceall(tm, "$error", "error")) { + /* Only declare error if it is used by the typemap. */ + error_used_in_typemap = true; + Append(w->code, "int error;\n"); + } + } else { + Delete(tm); + tm = NULL; + } + + if (!idx) { + Printf(w->code, "zval **args = NULL;\n"); + } else { + Printf(w->code, "zval *args[%d];\n", idx); + } + Printf(w->code, "zval *%s, funcname;\n", Swig_cresult_name()); + Append(w->code, "if (!swig_self) {\n"); + Append(w->code, " SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");"); + Append(w->code, "}\n\n"); + Printf(w->code, "MAKE_STD_ZVAL(%s);\n", Swig_cresult_name()); + const char * funcname = GetChar(n, "sym:name"); + Printf(w->code, "ZVAL_STRINGL(&funcname, (char *)\"%s\", %d, 0);\n", funcname, strlen(funcname)); + + /* wrap complex arguments to zvals */ + Printv(w->code, wrap_args, NIL); + + if (error_used_in_typemap) { + Append(w->code, "error = "); + } + Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,"); + Printf(w->code, " %s, %d, args TSRMLS_CC);\n", Swig_cresult_name(), idx); + + if (tm) { + Printv(w->code, Str(tm), "\n", NIL); + Delete(tm); + } + + /* marshal return value from PHP to C/C++ type */ + + String *cleanup = NewStringEmpty(); + String *outarg = NewStringEmpty(); + + idx = 0; + + /* marshal return value */ + if (!is_void) { + tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w); + if (tm != 0) { + Replaceall(tm, "$input", Swig_cresult_name()); + char temp[24]; + sprintf(temp, "%d", idx); + Replaceall(tm, "$argnum", temp); + + /* TODO check this */ + if (Getattr(n, "wrap:disown")) { + Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); + } else { + Replaceall(tm, "$disown", "0"); + } + Replaceall(tm, "$result", "c_result"); + Printv(w->code, tm, "\n", NIL); + Delete(tm); + } else { + Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, + "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), SwigType_namestr(c_classname), + SwigType_namestr(name)); + status = SWIG_ERROR; + } + } + + /* marshal outputs */ + for (p = l; p;) { + if ((tm = Getattr(p, "tmap:directorargout")) != 0) { + Replaceall(tm, "$result", Swig_cresult_name()); + Replaceall(tm, "$input", Getattr(p, "emit:directorinput")); + Printv(w->code, tm, "\n", NIL); + p = Getattr(p, "tmap:directorargout:next"); + } else { + p = nextSibling(p); + } + } + + Printf(w->code, "FREE_ZVAL(%s);\n", Swig_cresult_name()); + + Delete(parse_args); + Delete(cleanup); + Delete(outarg); + } + + Append(w->code, "thrown:\n"); + if (!is_void) { + if (!(ignored_method && !pure_virtual)) { + String *rettype = SwigType_str(returntype, 0); + if (!SwigType_isreference(returntype)) { + Printf(w->code, "return (%s) c_result;\n", rettype); + } else { + Printf(w->code, "return (%s) *c_result;\n", rettype); + } + Delete(rettype); + } + } else { + Append(w->code, "return;\n"); + } + + Append(w->code, "fail:\n"); + Append(w->code, "SWIG_FAIL(TSRMLS_C);\n"); + Append(w->code, "}\n"); + + // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method + String *inline_extra_method = NewStringEmpty(); + if (dirprot_mode() && !is_public(n) && !pure_virtual) { + Printv(inline_extra_method, declaration, NIL); + String *extra_method_name = NewStringf("%sSwigPublic", name); + Replaceall(inline_extra_method, name, extra_method_name); + Replaceall(inline_extra_method, ";\n", " {\n "); + if (!is_void) + Printf(inline_extra_method, "return "); + String *methodcall = Swig_method_call(super, l); + Printv(inline_extra_method, methodcall, ";\n }\n", NIL); + Delete(methodcall); + Delete(extra_method_name); + } + + /* emit the director method */ + if (status == SWIG_OK) { + if (!Getattr(n, "defaultargs")) { + Replaceall(w->code, "$symname", symname); + Wrapper_print(w, f_directors); + Printv(f_directors_h, declaration, NIL); + Printv(f_directors_h, inline_extra_method, NIL); + } + } + + /* clean up */ + Delete(wrap_args); + Delete(pclassname); + DelWrapper(w); + return status; + } + + int classDirectorDisown(Node *) { + return SWIG_OK; + } +}; /* class PHP */ + +static PHP5 *maininstance = 0; + +// We use this function to be able to write out zend_register_list_destructor_ex +// lines for most things in the type table +// NOTE: it's a function NOT A PHP5::METHOD +extern "C" { +static void typetrace(const SwigType *ty, String *mangled, String *clientdata) { + Node *class_node; + if (!zend_types) { + zend_types = NewHash(); + } + // we want to know if the type which reduced to this has a constructor + if ((class_node = maininstance->classLookup(ty))) { + if (!Getattr(zend_types, mangled)) { + // OK it may have been set before by a different SwigType but it would + // have had the same underlying class node I think + // - it is certainly required not to have different originating class + // nodes for the same SwigType + Setattr(zend_types, mangled, class_node); + } + } else { // a non-class pointer + Setattr(zend_types, mangled, NOTCLASS); + } + if (r_prevtracefunc) + (*r_prevtracefunc) (ty, mangled, (String *) clientdata); +} +} + +/* ----------------------------------------------------------------------------- + * new_swig_php5() - Instantiate module + * ----------------------------------------------------------------------------- */ + +static Language *new_swig_php5() { + maininstance = new PHP5; + if (!r_prevtracefunc) { + r_prevtracefunc = SwigType_remember_trace(typetrace); + } else { + Printf(stderr, "php Typetrace vector already saved!\n"); + assert(0); + } + return maininstance; +} + +extern "C" Language *swig_php4(void) { + Printf(stderr, "*** -php4 is no longer supported.\n" + "*** Either upgrade to PHP5 or use SWIG 1.3.36 or earlier.\n"); + SWIG_exit(EXIT_FAILURE); + return NULL; // To avoid compiler warnings. +} + +extern "C" Language *swig_php5(void) { + return new_swig_php5(); +} diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx index b7b5d66ee..397677fc5 100644 --- a/Source/Modules/swigmain.cxx +++ b/Source/Modules/swigmain.cxx @@ -36,6 +36,7 @@ extern "C" { Language *swig_java(void); Language *swig_php(void); Language *swig_php4(void); + Language *swig_php5(void); Language *swig_ocaml(void); Language *swig_octave(void); Language *swig_pike(void); @@ -83,9 +84,10 @@ static swig_module modules[] = { {"-octave", swig_octave, "Octave"}, {"-perl", swig_perl5, "Perl"}, {"-perl5", swig_perl5, 0}, - {"-php", swig_php, "PHP"}, + {"-php", swig_php5, 0}, {"-php4", swig_php4, 0}, - {"-php5", swig_php, 0}, + {"-php5", swig_php5, "PHP5"}, + {"-php7", swig_php, "PHP7"}, {"-pike", swig_pike, "Pike"}, {"-python", swig_python, "Python"}, {"-r", swig_r, "R (aka GNU S)"}, diff --git a/configure.ac b/configure.ac index 492d9cc1c..b99a3a0a3 100644 --- a/configure.ac +++ b/configure.ac @@ -386,6 +386,9 @@ case $host in *) PHP_SO=$SO;; esac +AC_SUBST(PHP5_SO) +PHP5_SO=$PHP_SO + AC_SUBST(MZSCHEME_SO) case $host in *) MZSCHEME_SO=.so;; @@ -1896,7 +1899,54 @@ AC_SUBST(RUBYSO) AC_SUBST(RUBYDYNAMICLINKING) #------------------------------------------------------------------------- -# Look for PHP +# Look for PHP5 +#------------------------------------------------------------------------- + +PHP5BIN= + +AC_ARG_WITH(php5, AS_HELP_STRING([--without-php5], [Disable PHP5]) +AS_HELP_STRING([--with-php5=path], [Set location of PHP5 executable]),[ PHP5BIN="$withval"], [PHP5BIN="$alllang_default"]) + +# First, check for "--without-php5" or "--with-php5=no". +if test x"${PHP5BIN}" = xno; then + AC_MSG_NOTICE([Disabling PHP5]) + PHP5= +else + if test "x$PHP5BIN" = xyes; then + AC_CHECK_PROGS(PHP5, [php5 php]) + else + PHP5=$PHP5BIN + fi + + AC_MSG_CHECKING(for PHP5 header files) + dnl /usr/bin/php5 -> /usr/bin/php-config5 + case $PHP5 in + *5) + PHP5CONFIG=`echo "$PHP5"|sed 's/5$/-config5/'` ;; + *) + PHP5CONFIG=$PHP5-config ;; + esac + php5_version=`$PHP5CONFIG --version 2>/dev/null` + case $php5_version in + 5*) + PHP5INC=`$PHP5CONFIG --includes 2>/dev/null` + if test -n "$PHP5INC"; then + AC_MSG_RESULT($PHP5INC) + else + AC_MSG_RESULT(not found) + fi + ;; + "") + AC_MSG_RESULT([could not find $PHP5CONFIG or obtain PHP5 version from it]) ;; + *) + AC_MSG_RESULT([found PHP $php_version - not PHP 5]) ;; + esac +fi +AC_SUBST(PHP5) +AC_SUBST(PHP5INC) + +#------------------------------------------------------------------------- +# Look for PHP7 #------------------------------------------------------------------------- PHPBIN= @@ -1909,24 +1959,23 @@ if test x"${PHPBIN}" = xno; then AC_MSG_NOTICE([Disabling PHP]) PHP= else - if test "x$PHPBIN" = xyes; then - AC_CHECK_PROGS(PHP, [php5 php]) + AC_CHECK_PROGS(PHP, [php7.0 php]) else PHP=$PHPBIN fi AC_MSG_CHECKING(for PHP header files) - dnl /usr/bin/php5 -> /usr/bin/php-config5 + dnl /usr/bin/php7.0 -> /usr/bin/php-config7.0 case $PHP in - *5) - PHPCONFIG=`echo "$PHP"|sed 's/5$/-config5/'` ;; + *7.*) + PHPCONFIG=`echo "$PHP"|sed 's/7\...*$/-config&/'` ;; *) PHPCONFIG=$PHP-config ;; esac php_version=`$PHPCONFIG --version 2>/dev/null` case $php_version in - 5*) + 7.*) PHPINC=`$PHPCONFIG --includes 2>/dev/null` if test -n "$PHPINC"; then AC_MSG_RESULT($PHPINC) @@ -1937,7 +1986,7 @@ else "") AC_MSG_RESULT([could not find $PHPCONFIG or obtain PHP version from it]) ;; *) - AC_MSG_RESULT([found PHP $php_version, but only PHP 5 is supported]) ;; + AC_MSG_RESULT([found PHP $php_version - not PHP 7]) ;; esac fi AC_SUBST(PHP) @@ -2756,6 +2805,13 @@ fi AC_SUBST(SKIP_PHP) +SKIP_PHP5= +if test -z "$PHP5" || test -z "$PHP5INC" ; then + SKIP_PHP5="1" +fi +AC_SUBST(SKIP_PHP5) + + SKIP_OCAML= if test -z "$OCAMLC" ; then SKIP_OCAML="1" @@ -2955,6 +3011,7 @@ AC_CONFIG_FILES([ Examples/test-suite/octave/Makefile Examples/test-suite/perl5/Makefile Examples/test-suite/php/Makefile + Examples/test-suite/php5/Makefile Examples/test-suite/pike/Makefile Examples/test-suite/python/Makefile Examples/test-suite/ruby/Makefile @@ -3029,6 +3086,7 @@ test -n "$SKIP_OCAML" || langs="${langs}ocaml " test -n "$SKIP_OCTAVE" || langs="${langs}octave " test -n "$SKIP_PERL5" || langs="${langs}perl5 " test -n "$SKIP_PHP" || langs="${langs}php " +test -n "$SKIP_PHP5" || langs="${langs}php5 " test -n "$SKIP_PIKE" || langs="${langs}pike " test -n "$SKIP_PYTHON" || langs="${langs}python " test -n "$SKIP_R" || langs="${langs}r "