summaryrefslogtreecommitdiff
path: root/Backport-php-8-support-from-upstream.patch
blob: 695d82e5d44f3f91dcf7d7ff9bf2506f39fa2123 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
From 70be7506121500945b1b31ae87085aa0b9fed771 Mon Sep 17 00:00:00 2001
From: misaka00251 <liuxin@iscas.ac.cn>
Date: Mon, 5 Jun 2023 18:24:06 +0800
Subject: [PATCH] Backport php 8 support from upstream

---
 Doc/Manual/Php.html                           |  6 +--
 Doc/Manual/Preprocessor.html                  |  2 +-
 Doc/Manual/SWIG.html                          |  2 +-
 Examples/Makefile.in                          |  6 +--
 Examples/test-suite/director_overload2.i      |  4 ++
 .../php/evil_diamond_prop_runme.php           |  2 +-
 Lib/cdata.i                                   |  2 +-
 Lib/exception.i                               |  2 +-
 Lib/php/phprun.swg                            |  8 ++-
 Source/Modules/php.cxx                        | 53 +++++++++++++++----
 configure.ac                                  | 10 ++--
 11 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html
index d0ec0df..20d2ac3 100644
--- a/Doc/Manual/Php.html
+++ b/Doc/Manual/Php.html
@@ -51,12 +51,12 @@
 
 <p>
 In this chapter, we discuss SWIG's support of PHP.  SWIG currently supports
-generating wrappers for PHP7.  Support for PHP5 was removed in SWIG 4.0.0
-and support for PHP4 was removed in SWIG 1.3.37.
+generating wrappers for PHP7 and PHP8.  Support for PHP5 was removed in SWIG
+4.0.0 and support for PHP4 was removed in SWIG 1.3.37.
 </p>
 
 <p>
-Currently any PHP7 release should work.
+Currently any PHP7 or PHP8 release should work.
 </p>
 
 <p>
diff --git a/Doc/Manual/Preprocessor.html b/Doc/Manual/Preprocessor.html
index 66061a5..4e783c8 100644
--- a/Doc/Manual/Preprocessor.html
+++ b/Doc/Manual/Preprocessor.html
@@ -123,7 +123,7 @@ SWIGOCAML                       Defined when using OCaml
 SWIGOCTAVE                      Defined when using Octave
 SWIGPERL                        Defined when using Perl
 SWIGPHP                         Defined when using PHP (any version)
-SWIGPHP7                        Defined when using PHP7
+SWIGPHP7                        Defined when using PHP 7 or later
 SWIGPYTHON                      Defined when using Python
 SWIGR                           Defined when using R
 SWIGRUBY                        Defined when using Ruby
diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html
index f9b5d7c..9cbcd72 100644
--- a/Doc/Manual/SWIG.html
+++ b/Doc/Manual/SWIG.html
@@ -127,7 +127,7 @@ Supported Target Language Options
      -lua            - Generate Lua wrappers
      -octave         - Generate Octave wrappers
      -perl5          - Generate Perl 5 wrappers
-     -php7           - Generate PHP 7 wrappers
+     -php7           - Generate PHP 7 or later wrappers
      -python         - Generate Python wrappers
      -r              - Generate R (aka GNU S) wrappers
      -ruby           - Generate Ruby wrappers
diff --git a/Examples/Makefile.in b/Examples/Makefile.in
index 87386f7..2efcd92 100644
--- a/Examples/Makefile.in
+++ b/Examples/Makefile.in
@@ -1056,7 +1056,7 @@ ruby_clean:
 	rm -f *.@OBJEXT@ *$(RUBY_SO)
 
 ##################################################################
-#####                       PHP7                            ######
+#####                        PHP                            ######
 ##################################################################
 
 PHP         = @PHP@
@@ -1069,7 +1069,7 @@ PHP_SCRIPT  = $(SRCDIR)$(RUNME).php
 # -------------------------------------------------------------------
 
 php: $(SRCDIR_SRCS)
-	$(SWIG) -php7 $(SWIGOPT) -o $(ISRCS) $(INTERFACEPATH)
+	$(SWIG) -php $(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)
 
@@ -1078,7 +1078,7 @@ php: $(SRCDIR_SRCS)
 # --------------------------------------------------------------------
 
 php_cpp: $(SRCDIR_SRCS)
-	$(SWIG) -php7 -c++ $(SWIGOPT) -o $(ICXXSRCS) $(INTERFACEPATH)
+	$(SWIG) -php -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/test-suite/director_overload2.i b/Examples/test-suite/director_overload2.i
index e467c18..b6c351c 100644
--- a/Examples/test-suite/director_overload2.i
+++ b/Examples/test-suite/director_overload2.i
@@ -14,11 +14,15 @@ struct OverloadDerived1 : OverloadBase {
   virtual void nnn(int vvv) {}
 #if defined(__SUNPRO_CC)
   virtual void nnn() {}
+#elif defined(SWIGPHP)
+  virtual void nnn() {}
 #endif
 };
 struct OverloadDerived2 : OverloadBase {
 #if defined(__SUNPRO_CC)
   virtual void nnn(int vvv) {}
+#elif defined(SWIGPHP)
+  virtual void nnn(int vvv) {}
 #endif
   virtual void nnn() {}
 };
diff --git a/Examples/test-suite/php/evil_diamond_prop_runme.php b/Examples/test-suite/php/evil_diamond_prop_runme.php
index 9bdb743..645328a 100644
--- a/Examples/test-suite/php/evil_diamond_prop_runme.php
+++ b/Examples/test-suite/php/evil_diamond_prop_runme.php
@@ -31,7 +31,7 @@ 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
-set_error_handler(NULL, 0); // Don't complain that _baz is unknown.
+set_error_handler(function () {return true;}, E_NOTICE|E_WARNING); // Don't complain that _baz is unknown.
 check::equal(null,$spam->_baz,"null==spam->_baz");
 restore_error_handler();
 check::equal(4,$spam->_spam,"4==spam->_spam");
diff --git a/Lib/cdata.i b/Lib/cdata.i
index f18ed4a..cd15266 100644
--- a/Lib/cdata.i
+++ b/Lib/cdata.i
@@ -21,7 +21,7 @@ typedef struct SWIGCDATA {
 }
 %typemap(in) (const void *indata, int inlen) = (char *STRING, int LENGTH);
 
-#elif SWIGPHP7
+#elif SWIGPHP
 
 %typemap(out) SWIGCDATA {
   ZVAL_STRINGL($result, $1.data, $1.len);
diff --git a/Lib/exception.i b/Lib/exception.i
index ee9ce9b..3d6eecc 100644
--- a/Lib/exception.i
+++ b/Lib/exception.i
@@ -12,7 +12,7 @@
 %insert("runtime") "swigerrors.swg"
 
 
-#ifdef SWIGPHP7
+#ifdef SWIGPHP
 %{
 #include "zend_exceptions.h"
 #define SWIG_exception(code, msg) do { zend_throw_exception(NULL, (char*)msg, code); goto thrown; } while (0)
diff --git a/Lib/php/phprun.swg b/Lib/php/phprun.swg
index a07a1b9..08b26da 100644
--- a/Lib/php/phprun.swg
+++ b/Lib/php/phprun.swg
@@ -12,8 +12,8 @@ extern "C" {
 #include "zend_exceptions.h"
 #include "php.h"
 
-#if PHP_MAJOR_VERSION != 7
-# error These bindings need PHP7 - to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5
+#if PHP_MAJOR_VERSION < 7
+# error These bindings need PHP7 or later - to generate PHP5 bindings use: SWIG < 4.0.0 and swig -php5
 #endif
 
 #include "ext/standard/php_string.h"
@@ -204,7 +204,11 @@ SWIG_ConvertPtr(zval *z, void **ptr, swig_type_info *ty, int flags) {
 
   switch (Z_TYPE_P(z)) {
     case IS_OBJECT: {
+#if PHP_MAJOR_VERSION < 8
       HashTable * ht = Z_OBJ_HT_P(z)->get_properties(z);
+#else
+      HashTable * ht = Z_OBJ_HT_P(z)->get_properties(Z_OBJ_P(z));
+#endif
       if (ht) {
         zval * _cPtr = zend_hash_str_find(ht, "_cPtr", sizeof("_cPtr") - 1);
         if (_cPtr) {
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
index 1edbd87..daacd8f 100644
--- a/Source/Modules/php.cxx
+++ b/Source/Modules/php.cxx
@@ -473,6 +473,20 @@ public:
     s_arginfo = NewString("/* arginfo subsection */\n");
     arginfo_used = NewHash();
 
+    /* Add arginfo we will definitely need for *_alter_newobject and *_get_newobject. */
+    SetFlag(arginfo_used, "1");
+    Append(s_arginfo,
+	   "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_1, 0, 0, 0)\n"
+	   " ZEND_ARG_INFO(0,arg1)\n"
+	   "ZEND_END_ARG_INFO()\n");
+
+    SetFlag(arginfo_used, "2");
+    Append(s_arginfo,
+	   "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_2, 0, 0, 0)\n"
+	   " ZEND_ARG_INFO(0,arg1)\n"
+	   " ZEND_ARG_INFO(0,arg2)\n"
+	   "ZEND_END_ARG_INFO()\n");
+
     /* start the function entry section */
     s_entry = NewString("/* entry subsection */\n");
 
@@ -653,8 +667,8 @@ public:
     }
     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"
+	" SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,swig_arginfo_2)\n"
+	" SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,swig_arginfo_1)\n"
 	" ZEND_FE_END\n};\n\n", NIL);
     Printv(f_begin, s_init, NIL);
     Delete(s_header);
@@ -689,25 +703,46 @@ public:
 
     // We want to only emit each different arginfo once, as that reduces the
     // size of both the generated source code and the compiled extension
-    // module.  To do this, we name the arginfo to encode the number of
-    // parameters and which (if any) are passed by reference by using a
-    // sequence of 0s (for non-reference) and 1s (for by references).
+    // module.  The parameters at this level are just named arg1, arg2, etc
+    // so we generate an arginfo name with the number of parameters and a
+    // bitmap value saying which (if any) are passed by reference.
     ParmList *l = Getattr(n, "parms");
-    String * arginfo_code = NewStringEmpty();
+    unsigned long bitmap = 0, bit = 1;
+    int n_params = 0;
+    bool overflowed = false;
     for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) {
       /* Ignored parameters */
       if (checkAttribute(p, "tmap:in:numinputs", "0")) {
 	continue;
       }
-      Append(arginfo_code, GetFlag(p, "tmap:in:byref") ? "1" : "0");
+      ++n_params;
+      if (GetFlag(p, "tmap:in:byref")) {
+        bitmap |= bit;
+        if (bit == 0) overflowed = true;
+      }
+      bit <<= 1;
+    }
+    String * arginfo_code;
+    if (overflowed) {
+      // We overflowed the bitmap so just generate a unique name - this only
+      // happens for a function with more parameters than bits in a long
+      // where a high numbered parameter is passed by reference, so should be
+      // rare in practice.
+      static int overflowed_counter = 0;
+      arginfo_code = NewStringf("z%d", ++overflowed_counter);
+    } else if (bitmap == 0) {
+      // No parameters passed by reference.
+      arginfo_code = NewStringf("%d", n_params);
+    } else {
+      arginfo_code = NewStringf("%d_%lx", n_params, bitmap);
     }
 
     if (!GetFlag(arginfo_used, arginfo_code)) {
       // Not had this one before, so emit it.
       SetFlag(arginfo_used, arginfo_code);
       Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%s, 0, 0, 0)\n", arginfo_code);
-      for (const char * p = Char(arginfo_code); *p; ++p) {
-	Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%c)\n", *p);
+      for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) {
+        Printf(s_arginfo, " ZEND_ARG_INFO(%d,%s)\n", GetFlag(p, "tmap:in:byref"), Getattr(p, "lname"));
       }
       Printf(s_arginfo, "ZEND_END_ARG_INFO()\n");
     }
diff --git a/configure.ac b/configure.ac
index 12b2460..479f1f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2036,7 +2036,7 @@ AC_SUBST(RUBYSO)
 AC_SUBST(RUBYDYNAMICLINKING)
 
 #-------------------------------------------------------------------------
-# Look for PHP7
+# Look for PHP
 #-------------------------------------------------------------------------
 
 PHPBIN=
@@ -2050,7 +2050,7 @@ if test x"${PHPBIN}" = xno; then
     PHP=
 else
     if test "x$PHPBIN" = xyes; then
-      AC_CHECK_PROGS(PHP, [php7.3 php7.2 php7.1 php7.0 php])
+      AC_CHECK_PROGS(PHP, [php8.2 php8.1 php8.0 php7.3 php7.2 php7.1 php7.0 php])
     else
       PHP=$PHPBIN
     fi
@@ -2061,12 +2061,14 @@ else
       case $PHP in
         *7.*)
           PHPCONFIG=`echo "$PHP"|sed 's/7\...*$/-config&/'` ;;
+        *8.*)
+          PHPCONFIG=`echo "$PHP"|sed 's/8\...*$/-config&/'` ;;
         *)
           PHPCONFIG=$PHP-config ;;
       esac
       php_version=`$PHPCONFIG --version 2>/dev/null`
       case $php_version in
-      7.*)
+      7.*|8.*)
         PHPINC=`$PHPCONFIG --includes 2>/dev/null`
         if test -n "$PHPINC"; then
           AC_MSG_RESULT($PHPINC)
@@ -2077,7 +2079,7 @@ else
       "")
         AC_MSG_RESULT([could not find $PHPCONFIG or obtain PHP version from it]) ;;
       *)
-        AC_MSG_RESULT([found PHP $php_version - not PHP 7]) ;;
+        AC_MSG_RESULT([found PHP $php_version - not PHP 7 or 8]) ;;
       esac
     fi
 fi
-- 
2.39.2 (Apple Git-143)