1 /* -----------------------------------------------------------------------------
2 * This file is part of SWIG, which is licensed as a whole under version 3
3 * (or any later version) of the GNU General Public License. Some additional
4 * terms also apply to certain portions of SWIG. The full details of the SWIG
5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
6 * included with the SWIG source code as distributed by the SWIG developers
7 * and at http://www.swig.org/legal.html.
8 *
9 * php.cxx
10 *
11 * PHP language module for SWIG.
12 * -----------------------------------------------------------------------------
13 */
14
15 /* FIXME: PHP OO wrapping TODO list:
16 *
17 * Medium term:
18 *
19 * Handle default parameters on overloaded methods in PHP where possible.
20 * (Mostly done - just need to handle cases of overloaded methods with
21 * default parameters...)
22 * This is an optimisation - we could handle this case using a PHP
23 * default value, but currently we treat it as we would for a default
24 * value which is a compound C++ expression (i.e. as if we had a
25 * method with two overloaded forms instead of a single method with
26 * a default parameter value).
27 *
28 * Long term:
29 *
30 * Sort out locale-dependent behaviour of strtod() - it's harmless unless
31 * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably
32 * OK currently at least.
33 */
34
35 /*
36 * TODO: Replace remaining stderr messages with Swig_error or Swig_warning
37 * (may need to add more WARN_PHP_xxx codes...)
38 */
39
40 #include "swigmod.h"
41
42 #include <ctype.h>
43 #include <errno.h>
44
45 static const char *usage = "\
46 PHP 7 Options (available with -php7)\n\
47 -noproxy - Don't generate proxy classes.\n\
48 -prefix <prefix> - Prepend <prefix> to all class names in PHP wrappers\n\
49 \n";
50
51 /* The original class wrappers for PHP stored the pointer to the C++ class in
52 * the object property _cPtr. If we use the same name for the member variable
53 * which we put the pointer to the C++ class in, then the flat function
54 * wrappers will automatically pull it out without any changes being required.
55 * FIXME: Isn't using a leading underscore a bit suspect here?
56 */
57 #define SWIG_PTR "_cPtr"
58
59 /* This is the name of the hash where the variables existing only in PHP
60 * classes are stored.
61 */
62 #define SWIG_DATA "_pData"
63
64 static int constructors = 0;
65 static String *NOTCLASS = NewString("Not a class");
66 static Node *classnode = 0;
67 static String *module = 0;
68 static String *cap_module = 0;
69 static String *prefix = 0;
70
71 static String *shadow_classname = 0;
72
73 static File *f_begin = 0;
74 static File *f_runtime = 0;
75 static File *f_runtime_h = 0;
76 static File *f_h = 0;
77 static File *f_phpcode = 0;
78 static File *f_directors = 0;
79 static File *f_directors_h = 0;
80 static String *phpfilename = 0;
81
82 static String *s_header;
83 static String *s_wrappers;
84 static String *s_init;
85 static String *r_init; // RINIT user code
86 static String *s_shutdown; // MSHUTDOWN user code
87 static String *r_shutdown; // RSHUTDOWN user code
88 static String *s_vinit; // varinit initialization code.
89 static String *s_vdecl;
90 static String *s_cinit; // consttab initialization code.
91 static String *s_oinit;
92 static String *s_arginfo;
93 static String *s_entry;
94 static String *cs_entry;
95 static String *all_cs_entry;
96 static String *pragma_incl;
97 static String *pragma_code;
98 static String *pragma_phpinfo;
99 static String *pragma_version;
100 static String *s_oowrappers;
101 static String *s_fakeoowrappers;
102 static String *s_phpclasses;
103
104 /* To reduce code size (generated and compiled) we only want to emit each
105 * different arginfo once, so we need to track which have been used.
106 */
107 static Hash *arginfo_used;
108
109 /* Variables for using PHP classes */
110 static Node *current_class = 0;
111
112 static Hash *shadow_get_vars;
113 static Hash *shadow_set_vars;
114 static Hash *zend_types = 0;
115
116 static int shadow = 1;
117
118 static bool class_has_ctor = false;
119 static String *wrapping_member_constant = NULL;
120
121 // These static variables are used to pass some state from Handlers into functionWrapper
122 static enum {
123 standard = 0,
124 memberfn,
125 staticmemberfn,
126 membervar,
127 staticmembervar,
128 constructor,
129 directorconstructor
130 } wrapperType = standard;
131
132 extern "C" {
133 static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
134 }
135
SwigPHP_emit_resource_registrations()136 static void SwigPHP_emit_resource_registrations() {
137 Iterator ki;
138 bool emitted_default_dtor = false;
139
140 if (!zend_types)
141 return;
142
143 ki = First(zend_types);
144 if (ki.key)
145 Printf(s_oinit, "\n /* Register resource destructors for pointer types */\n");
146 while (ki.key) {
147 DOH *key = ki.key;
148 Node *class_node = ki.item;
149 String *human_name = key;
150 String *rsrc_dtor_name = NULL;
151
152 // write out body
153 if (class_node != NOTCLASS) {
154 String *destructor = Getattr(class_node, "destructor");
155 human_name = Getattr(class_node, "sym:name");
156 if (!human_name)
157 human_name = Getattr(class_node, "name");
158 // Do we have a known destructor for this type?
159 if (destructor) {
160 rsrc_dtor_name = NewStringf("_wrap_destroy%s", key);
161 // Write out custom destructor function
162 Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(%s) {\n", rsrc_dtor_name);
163 Printf(s_wrappers, " %s(res, SWIGTYPE%s->name);\n", destructor, key);
164 Printf(s_wrappers, "}\n");
165 }
166 }
167
168 if (!rsrc_dtor_name) {
169 rsrc_dtor_name = NewString("_swig_default_rsrc_destroy");
170 if (!emitted_default_dtor) {
171 // Write out custom destructor function
172 Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(%s) {\n", rsrc_dtor_name);
173 Printf(s_wrappers, " efree(res->ptr);\n");
174 Printf(s_wrappers, "}\n");
175 emitted_default_dtor = true;
176 }
177 }
178
179 // declare le_swig_<mangled> to store php registration
180 Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name);
181
182 // register with php
183 Printf(s_oinit, " le_swig_%s=zend_register_list_destructors_ex"
184 "(%s, NULL, SWIGTYPE%s->name, module_number);\n", key, rsrc_dtor_name, key);
185
186 // store php type in class struct
187 Printf(s_oinit, " SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key);
188
189 Delete(rsrc_dtor_name);
190
191 ki = Next(ki);
192 }
193 }
194
195 class PHP : public Language {
196 public:
PHP()197 PHP() {
198 director_language = 1;
199 }
200
201 /* ------------------------------------------------------------
202 * main()
203 * ------------------------------------------------------------ */
204
main(int argc,char * argv[])205 virtual void main(int argc, char *argv[]) {
206 SWIG_library_directory("php");
207
208 for (int i = 1; i < argc; i++) {
209 if (strcmp(argv[i], "-prefix") == 0) {
210 if (argv[i + 1]) {
211 prefix = NewString(argv[i + 1]);
212 Swig_mark_arg(i);
213 Swig_mark_arg(i + 1);
214 i++;
215 } else {
216 Swig_arg_error();
217 }
218 } else if ((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) {
219 shadow = 0;
220 Swig_mark_arg(i);
221 } else if (strcmp(argv[i], "-help") == 0) {
222 fputs(usage, stdout);
223 }
224 }
225
226 Preprocessor_define("SWIGPHP 1", 0);
227 Preprocessor_define("SWIGPHP7 1", 0);
228 SWIG_typemap_lang("php");
229 SWIG_config_file("php.swg");
230 allow_overloading();
231 }
232
233 /* ------------------------------------------------------------
234 * top()
235 * ------------------------------------------------------------ */
236
top(Node * n)237 virtual int top(Node *n) {
238
239 String *filen;
240
241 /* Check if directors are enabled for this module. */
242 Node *mod = Getattr(n, "module");
243 if (mod) {
244 Node *options = Getattr(mod, "options");
245 if (options && Getattr(options, "directors")) {
246 allow_directors();
247 }
248 }
249
250 /* Set comparison with null for ConstructorToFunction */
251 setSubclassInstanceCheck(NewString("Z_TYPE_P($arg) != IS_NULL"));
252
253 /* Initialize all of the output files */
254 String *outfile = Getattr(n, "outfile");
255 String *outfile_h = Getattr(n, "outfile_h");
256
257 /* main output file */
258 f_begin = NewFile(outfile, "w", SWIG_output_files());
259 if (!f_begin) {
260 FileErrorDisplay(outfile);
261 SWIG_exit(EXIT_FAILURE);
262 }
263 f_runtime = NewStringEmpty();
264
265 /* sections of the output file */
266 s_init = NewStringEmpty();
267 r_init = NewStringEmpty();
268 s_shutdown = NewStringEmpty();
269 r_shutdown = NewStringEmpty();
270 s_header = NewString("/* header section */\n");
271 s_wrappers = NewString("/* wrapper section */\n");
272 /* subsections of the init section */
273 s_vinit = NewStringEmpty();
274 s_vdecl = NewString("/* vdecl subsection */\n");
275 s_cinit = NewString(" /* cinit subsection */\n");
276 s_oinit = NewString(" /* oinit subsection */\n");
277 pragma_phpinfo = NewStringEmpty();
278 s_phpclasses = NewString("/* PHP Proxy Classes */\n");
279 f_directors_h = NewStringEmpty();
280 f_directors = NewStringEmpty();
281
282 if (directorsEnabled()) {
283 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
284 if (!f_runtime_h) {
285 FileErrorDisplay(outfile_h);
286 SWIG_exit(EXIT_FAILURE);
287 }
288 }
289
290 /* Register file targets with the SWIG file handler */
291 Swig_register_filebyname("begin", f_begin);
292 Swig_register_filebyname("runtime", f_runtime);
293 Swig_register_filebyname("init", s_init);
294 Swig_register_filebyname("rinit", r_init);
295 Swig_register_filebyname("shutdown", s_shutdown);
296 Swig_register_filebyname("rshutdown", r_shutdown);
297 Swig_register_filebyname("header", s_header);
298 Swig_register_filebyname("wrapper", s_wrappers);
299 Swig_register_filebyname("director", f_directors);
300 Swig_register_filebyname("director_h", f_directors_h);
301
302 Swig_banner(f_begin);
303
304 Printf(f_runtime, "\n\n#ifndef SWIGPHP\n#define SWIGPHP\n#endif\n\n");
305
306 if (directorsEnabled()) {
307 Printf(f_runtime, "#define SWIG_DIRECTORS\n");
308 }
309
310 /* Set the module name */
311 module = Copy(Getattr(n, "name"));
312 cap_module = NewStringf("%(upper)s", module);
313 if (!prefix)
314 prefix = NewStringEmpty();
315
316 Printf(f_runtime, "#define SWIG_PREFIX \"%s\"\n", prefix);
317 Printf(f_runtime, "#define SWIG_PREFIX_LEN %lu\n", (unsigned long)Len(prefix));
318
319 if (directorsEnabled()) {
320 Swig_banner(f_directors_h);
321 Printf(f_directors_h, "\n");
322 Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module);
323 Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module);
324
325 String *filename = Swig_file_filename(outfile_h);
326 Printf(f_directors, "\n#include \"%s\"\n\n", filename);
327 Delete(filename);
328 }
329
330 /* PHP module file */
331 filen = NewStringEmpty();
332 Printv(filen, SWIG_output_directory(), module, ".php", NIL);
333 phpfilename = NewString(filen);
334
335 f_phpcode = NewFile(filen, "w", SWIG_output_files());
336 if (!f_phpcode) {
337 FileErrorDisplay(filen);
338 SWIG_exit(EXIT_FAILURE);
339 }
340
341 Printf(f_phpcode, "<?php\n\n");
342
343 Swig_banner(f_phpcode);
344
345 Printf(f_phpcode, "\n");
346 Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n");
347 Printf(f_phpcode, "if (!extension_loaded('%s')) {\n", module);
348 Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n");
349 Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module);
350 Printf(f_phpcode, " } else {\n");
351 Printf(f_phpcode, " // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.\n");
352 Printf(f_phpcode, " if (PHP_SHLIB_SUFFIX === 'dylib') {\n");
353 Printf(f_phpcode, " if (!dl('%s.so')) return;\n", module);
354 Printf(f_phpcode, " } else {\n");
355 Printf(f_phpcode, " if (!dl('%s.'.PHP_SHLIB_SUFFIX)) return;\n", module);
356 Printf(f_phpcode, " }\n");
357 Printf(f_phpcode, " }\n");
358 Printf(f_phpcode, "}\n\n");
359
360 /* sub-sections of the php file */
361 pragma_code = NewStringEmpty();
362 pragma_incl = NewStringEmpty();
363 pragma_version = NULL;
364
365 /* Initialize the rest of the module */
366
367 Printf(s_oinit, " ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, NULL);\n", module, module);
368
369 /* start the header section */
370 Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module);
371 Printf(s_header, "const char *error_msg;\n");
372 Printf(s_header, "int error_code;\n");
373 Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module);
374 Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module);
375 Printf(s_header, "#define SWIG_ErrorMsg() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_msg)\n", module);
376 Printf(s_header, "#define SWIG_ErrorCode() ZEND_MODULE_GLOBALS_ACCESSOR(%s, error_code)\n", module);
377
378 /* The following can't go in Lib/php/phprun.swg as it uses SWIG_ErrorMsg(), etc
379 * which has to be dynamically generated as it depends on the module name.
380 */
381 Append(s_header, "#ifdef __GNUC__\n");
382 Append(s_header, "static void SWIG_FAIL(void) __attribute__ ((__noreturn__));\n");
383 Append(s_header, "#endif\n\n");
384 Append(s_header, "static void SWIG_FAIL(void) {\n");
385 Append(s_header, " zend_error(SWIG_ErrorCode(), \"%s\", SWIG_ErrorMsg());\n");
386 // zend_error() should never return with the parameters we pass, but if it
387 // does, we really don't want to let SWIG_FAIL() return. This also avoids
388 // a warning about returning from a function marked as "__noreturn__".
389 Append(s_header, " abort();\n");
390 Append(s_header, "}\n\n");
391
392 Printf(s_header, "static void %s_init_globals(zend_%s_globals *globals ) {\n", module, module);
393 Printf(s_header, " globals->error_msg = default_error_msg;\n");
394 Printf(s_header, " globals->error_code = default_error_code;\n");
395 Printf(s_header, "}\n");
396
397 Printf(s_header, "static void SWIG_ResetError(void) {\n");
398 Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n");
399 Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n");
400 Printf(s_header, "}\n");
401
402 Append(s_header, "\n");
403 Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module);
404 Append(s_header, " zval args[2];\n");
405 Append(s_header, " swig_object_wrapper *value;\n");
406 Append(s_header, "\n");
407 Append(s_header, " SWIG_ResetError();\n");
408 Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n");
409 Append(s_header, " WRONG_PARAM_COUNT;\n");
410 Append(s_header, " }\n");
411 Append(s_header, "\n");
412 Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n");
413 Append(s_header, " value->newobject = zval_is_true(&args[1]);\n");
414 Append(s_header, "\n");
415 Append(s_header, " return;\n");
416 Append(s_header, "}\n");
417 Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module);
418 Append(s_header, " zval args[1];\n");
419 Append(s_header, " swig_object_wrapper *value;\n");
420 Append(s_header, "\n");
421 Append(s_header, " SWIG_ResetError();\n");
422 Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n");
423 Append(s_header, " WRONG_PARAM_COUNT;\n");
424 Append(s_header, " }\n");
425 Append(s_header, "\n");
426 Append(s_header, " value = (swig_object_wrapper *) Z_RES_VAL(args[0]);\n");
427 Append(s_header, " RETVAL_LONG(value->newobject);\n");
428 Append(s_header, "\n");
429 Append(s_header, " return;\n");
430 Append(s_header, "}\n");
431
432 Printf(s_header, "#define SWIG_name \"%s\"\n", module);
433 Printf(s_header, "#ifdef __cplusplus\n");
434 Printf(s_header, "extern \"C\" {\n");
435 Printf(s_header, "#endif\n");
436 Printf(s_header, "#include \"php.h\"\n");
437 Printf(s_header, "#include \"php_ini.h\"\n");
438 Printf(s_header, "#include \"ext/standard/info.h\"\n");
439 Printf(s_header, "#include \"php_%s.h\"\n", module);
440 Printf(s_header, "#ifdef __cplusplus\n");
441 Printf(s_header, "}\n");
442 Printf(s_header, "#endif\n\n");
443
444 if (directorsEnabled()) {
445 // Insert director runtime
446 Swig_insert_file("director_common.swg", s_header);
447 Swig_insert_file("director.swg", s_header);
448 }
449
450 /* Create the .h file too */
451 filen = NewStringEmpty();
452 Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL);
453 f_h = NewFile(filen, "w", SWIG_output_files());
454 if (!f_h) {
455 FileErrorDisplay(filen);
456 SWIG_exit(EXIT_FAILURE);
457 }
458
459 Swig_banner(f_h);
460
461 Printf(f_h, "\n");
462 Printf(f_h, "#ifndef PHP_%s_H\n", cap_module);
463 Printf(f_h, "#define PHP_%s_H\n\n", cap_module);
464 Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module);
465 Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module);
466 Printf(f_h, "#ifdef PHP_WIN32\n");
467 Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module);
468 Printf(f_h, "#else\n");
469 Printf(f_h, "# define PHP_%s_API\n", cap_module);
470 Printf(f_h, "#endif\n\n");
471
472 /* start the arginfo section */
473 s_arginfo = NewString("/* arginfo subsection */\n");
474 arginfo_used = NewHash();
475
476 /* start the function entry section */
477 s_entry = NewString("/* entry subsection */\n");
478
479 /* holds all the per-class function entry sections */
480 all_cs_entry = NewString("/* class entry subsection */\n");
481 cs_entry = NULL;
482
483 Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n");
484 Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module);
485
486 /* Emit all of the code */
487 Language::top(n);
488
489 SwigPHP_emit_resource_registrations();
490
491 /* start the init section */
492 {
493 String * s_init_old = s_init;
494 s_init = NewString("/* init section */\n");
495 Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n", NIL);
496 Printf(s_init, " STANDARD_MODULE_HEADER,\n");
497 Printf(s_init, " \"%s\",\n", module);
498 Printf(s_init, " %s_functions,\n", module);
499 Printf(s_init, " PHP_MINIT(%s),\n", module);
500 if (Len(s_shutdown) > 0) {
501 Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module);
502 } else {
503 Printf(s_init, " NULL, /* No MSHUTDOWN code */\n");
504 }
505 if (Len(r_init) > 0 || Len(s_vinit) > 0) {
506 Printf(s_init, " PHP_RINIT(%s),\n", module);
507 } else {
508 Printf(s_init, " NULL, /* No RINIT code */\n");
509 }
510 if (Len(r_shutdown) > 0) {
511 Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module);
512 } else {
513 Printf(s_init, " NULL, /* No RSHUTDOWN code */\n");
514 }
515 if (Len(pragma_phpinfo) > 0) {
516 Printf(s_init, " PHP_MINFO(%s),\n", module);
517 } else {
518 Printf(s_init, " NULL, /* No MINFO code */\n");
519 }
520 if (Len(pragma_version) > 0) {
521 Printf(s_init, " \"%s\",\n", pragma_version);
522 } else {
523 Printf(s_init, " NO_VERSION_YET,\n");
524 }
525 Printf(s_init, " STANDARD_MODULE_PROPERTIES\n");
526 Printf(s_init, "};\n");
527 Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module);
528
529 Printf(s_init, "#ifdef __cplusplus\n");
530 Printf(s_init, "extern \"C\" {\n");
531 Printf(s_init, "#endif\n");
532 // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE
533 // in PHP7 has "extern "C" { ... }" around it so we can't do that.
534 Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module);
535 Printf(s_init, "#ifdef __cplusplus\n");
536 Printf(s_init, "}\n");
537 Printf(s_init, "#endif\n\n");
538
539 Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n\n", module);
540
541 Printv(s_init, s_init_old, NIL);
542 Delete(s_init_old);
543 }
544
545 /* We have to register the constants before they are (possibly) used
546 * by the pointer typemaps. This all needs re-arranging really as
547 * things are being called in the wrong order
548 */
549
550 // Printv(s_init,s_resourcetypes,NIL);
551 /* We need this after all classes written out by ::top */
552 Printf(s_oinit, " CG(active_class_entry) = NULL;\n");
553 Printf(s_oinit, " /* end oinit subsection */\n");
554 Printf(s_init, "%s\n", s_oinit);
555
556 /* Constants generated during top call */
557 Printf(s_cinit, " /* end cinit subsection */\n");
558 Printf(s_init, "%s\n", s_cinit);
559 Clear(s_cinit);
560 Delete(s_cinit);
561
562 Printf(s_init, " return SUCCESS;\n");
563 Printf(s_init, "}\n\n");
564
565 // Now do REQUEST init which holds any user specified %rinit, and also vinit
566 if (Len(r_init) > 0 || Len(s_vinit) > 0) {
567 Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module);
568
569 Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module);
570 if (Len(r_init) > 0) {
571 Printv(s_init,
572 "/* rinit section */\n",
573 r_init, "\n",
574 NIL);
575 }
576
577 if (Len(s_vinit) > 0) {
578 /* finish our init section which will have been used by class wrappers */
579 Printv(s_init,
580 " /* vinit subsection */\n",
581 s_vinit, "\n"
582 " /* end vinit subsection */\n",
583 NIL);
584 Clear(s_vinit);
585 }
586 Delete(s_vinit);
587
588 Printf(s_init, " return SUCCESS;\n");
589 Printf(s_init, "}\n\n");
590 }
591
592 Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module);
593
594 if (Len(s_shutdown) > 0) {
595 Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module);
596
597 Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
598 "/* shutdown section */\n"
599 "{\n",
600 s_shutdown,
601 " return SUCCESS;\n"
602 "}\n\n", NIL);
603 }
604
605 if (Len(r_shutdown) > 0) {
606 Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module);
607
608 Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
609 Printf(s_init, "/* rshutdown section */\n");
610 Printf(s_init, "%s\n", r_shutdown);
611 Printf(s_init, " return SUCCESS;\n");
612 Printf(s_init, "}\n\n");
613 }
614
615 if (Len(pragma_phpinfo) > 0) {
616 Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n", module);
617
618 Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module);
619 Printf(s_init, "%s", pragma_phpinfo);
620 Printf(s_init, "}\n");
621 }
622
623 Printf(s_init, "/* end init section */\n");
624
625 Printf(f_h, "\n#endif /* PHP_%s_H */\n", cap_module);
626
627 Delete(f_h);
628
629 String *type_table = NewStringEmpty();
630 SwigType_emit_type_table(f_runtime, type_table);
631 Printf(s_header, "%s", type_table);
632 Delete(type_table);
633
634 /* Oh dear, more things being called in the wrong order. This whole
635 * function really needs totally redoing.
636 */
637
638 if (directorsEnabled()) {
639 Dump(f_directors_h, f_runtime_h);
640 Printf(f_runtime_h, "\n");
641 Printf(f_runtime_h, "#endif\n");
642 Delete(f_runtime_h);
643 }
644
645 Printf(s_header, "/* end header section */\n");
646 Printf(s_wrappers, "/* end wrapper section */\n");
647 Printf(s_vdecl, "/* end vdecl subsection */\n");
648
649 Dump(f_runtime, f_begin);
650 Printv(f_begin, s_header, NIL);
651 if (directorsEnabled()) {
652 Dump(f_directors, f_begin);
653 }
654 Printv(f_begin, s_vdecl, s_wrappers, NIL);
655 Printv(f_begin, all_cs_entry, "\n\n", s_arginfo, "\n\n", s_entry,
656 " SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n"
657 " SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n"
658 " ZEND_FE_END\n};\n\n", NIL);
659 Printv(f_begin, s_init, NIL);
660 Delete(s_header);
661 Delete(s_wrappers);
662 Delete(s_init);
663 Delete(s_vdecl);
664 Delete(all_cs_entry);
665 Delete(s_entry);
666 Delete(s_arginfo);
667 Delete(f_runtime);
668 Delete(f_begin);
669 Delete(arginfo_used);
670
671 Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code);
672 if (s_fakeoowrappers) {
673 Printf(f_phpcode, "abstract class %s {", Len(prefix) ? prefix : module);
674 Printf(f_phpcode, "%s", s_fakeoowrappers);
675 Printf(f_phpcode, "}\n\n");
676 Delete(s_fakeoowrappers);
677 s_fakeoowrappers = NULL;
678 }
679 Printf(f_phpcode, "%s\n", s_phpclasses);
680 Delete(f_phpcode);
681
682 return SWIG_OK;
683 }
684
685 /* Just need to append function names to function table to register with PHP. */
create_command(String * cname,String * iname,Node * n)686 void create_command(String *cname, String *iname, Node *n) {
687 // This is for the single main zend_function_entry record
688 Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname);
689
690 // We want to only emit each different arginfo once, as that reduces the
691 // size of both the generated source code and the compiled extension
692 // module. To do this, we name the arginfo to encode the number of
693 // parameters and which (if any) are passed by reference by using a
694 // sequence of 0s (for non-reference) and 1s (for by references).
695 ParmList *l = Getattr(n, "parms");
696 String * arginfo_code = NewStringEmpty();
697 for (Parm *p = l; p; p = Getattr(p, "tmap:in:next")) {
698 /* Ignored parameters */
699 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
700 continue;
701 }
702 Append(arginfo_code, GetFlag(p, "tmap:in:byref") ? "1" : "0");
703 }
704
705 if (!GetFlag(arginfo_used, arginfo_code)) {
706 // Not had this one before, so emit it.
707 SetFlag(arginfo_used, arginfo_code);
708 Printf(s_arginfo, "ZEND_BEGIN_ARG_INFO_EX(swig_arginfo_%s, 0, 0, 0)\n", arginfo_code);
709 for (const char * p = Char(arginfo_code); *p; ++p) {
710 Printf(s_arginfo, " ZEND_ARG_PASS_INFO(%c)\n", *p);
711 }
712 Printf(s_arginfo, "ZEND_END_ARG_INFO()\n");
713 }
714
715 String * s = cs_entry;
716 if (!s) s = s_entry;
717 Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,swig_arginfo_%s)\n", cname, iname, arginfo_code);
718 Delete(arginfo_code);
719 }
720
721 /* ------------------------------------------------------------
722 * dispatchFunction()
723 * ------------------------------------------------------------ */
dispatchFunction(Node * n)724 void dispatchFunction(Node *n) {
725 /* Last node in overloaded chain */
726
727 int maxargs;
728 String *tmp = NewStringEmpty();
729 if (Swig_directorclass(n) && wrapperType == directorconstructor) {
730 /* We have an extra 'this' parameter. */
731 SetFlag(n, "wrap:this");
732 }
733 String *dispatch = Swig_overload_dispatch(n, "%s(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;", &maxargs);
734
735 /* Generate a dispatch wrapper for all overloaded functions */
736
737 Wrapper *f = NewWrapper();
738 String *symname = Getattr(n, "sym:name");
739 String *wname = Swig_name_wrapper(symname);
740
741 create_command(symname, wname, n);
742 Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
743
744 Wrapper_add_local(f, "argc", "int argc");
745
746 Printf(tmp, "zval argv[%d]", maxargs);
747 Wrapper_add_local(f, "argv", tmp);
748
749 Printf(f->code, "argc = ZEND_NUM_ARGS();\n");
750
751 Printf(f->code, "zend_get_parameters_array_ex(argc, argv);\n");
752
753 Replaceall(dispatch, "$args", "self,args");
754
755 Printv(f->code, dispatch, "\n", NIL);
756
757 Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n");
758 Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname);
759 Printv(f->code, "SWIG_FAIL();\n", NIL);
760
761 Printv(f->code, "}\n", NIL);
762 Wrapper_print(f, s_wrappers);
763
764 DelWrapper(f);
765 Delete(dispatch);
766 Delete(tmp);
767 Delete(wname);
768 }
769
770 /* ------------------------------------------------------------
771 * functionWrapper()
772 * ------------------------------------------------------------ */
773
774 /* Helper method for PHP::functionWrapper */
is_class(SwigType * t)775 bool is_class(SwigType *t) {
776 Node *n = classLookup(t);
777 if (n) {
778 String *r = Getattr(n, "php:proxy"); // Set by classDeclaration()
779 if (!r)
780 r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name
781 if (r)
782 return true;
783 }
784 return false;
785 }
786
functionWrapper(Node * n)787 virtual int functionWrapper(Node *n) {
788 String *name = GetChar(n, "name");
789 String *iname = GetChar(n, "sym:name");
790 SwigType *d = Getattr(n, "type");
791 ParmList *l = Getattr(n, "parms");
792 String *nodeType = Getattr(n, "nodeType");
793 int newobject = GetFlag(n, "feature:new");
794 int constructor = (Cmp(nodeType, "constructor") == 0);
795
796 Parm *p;
797 int i;
798 int numopt;
799 String *tm;
800 Wrapper *f;
801
802 String *wname;
803 int overloaded = 0;
804 String *overname = 0;
805
806 if (Cmp(nodeType, "destructor") == 0) {
807 // We just generate the Zend List Destructor and let Zend manage the
808 // reference counting. There's no explicit destructor, but the user can
809 // just do `$obj = null;' to remove a reference to an object.
810 return CreateZendListDestructor(n);
811 }
812 // Test for overloading;
813 if (Getattr(n, "sym:overloaded")) {
814 overloaded = 1;
815 overname = Getattr(n, "sym:overname");
816 } else {
817 if (!addSymbol(iname, n))
818 return SWIG_ERROR;
819 }
820
821 wname = Swig_name_wrapper(iname);
822 if (overname) {
823 Printf(wname, "%s", overname);
824 }
825
826 f = NewWrapper();
827
828 String *outarg = NewStringEmpty();
829 String *cleanup = NewStringEmpty();
830
831 Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
832
833 emit_parameter_variables(l, f);
834 /* Attach standard typemaps */
835
836 emit_attach_parmmaps(l, f);
837 // Not issued for overloaded functions.
838 if (!overloaded) {
839 create_command(iname, wname, n);
840 }
841
842 // wrap:parms is used by overload resolution.
843 Setattr(n, "wrap:parms", l);
844
845 int num_arguments = emit_num_arguments(l);
846 int num_required = emit_num_required(l);
847 numopt = num_arguments - num_required;
848
849 if (wrapperType == directorconstructor)
850 num_arguments++;
851
852 if (num_arguments > 0) {
853 String *args = NewStringEmpty();
854 if (wrapperType == directorconstructor)
855 Wrapper_add_local(f, "arg0", "zval * arg0");
856 Printf(args, "zval args[%d]", num_arguments);
857 Wrapper_add_local(f, "args", args);
858 Delete(args);
859 args = NULL;
860 }
861
862 // This generated code may be called:
863 // 1) as an object method, or
864 // 2) as a class-method/function (without a "this_ptr")
865 // Option (1) has "this_ptr" for "this", option (2) needs it as
866 // first parameter
867
868 // NOTE: possible we ignore this_ptr as a param for native constructor
869
870 Printf(f->code, "SWIG_ResetError();\n");
871
872 if (numopt > 0) { // membervariable wrappers do not have optional args
873 Wrapper_add_local(f, "arg_count", "int arg_count");
874 Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n");
875 Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments);
876 Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n");
877 Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n");
878 } else {
879 if (num_arguments == 0) {
880 Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n");
881 } else {
882 Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments);
883 }
884 Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n");
885 }
886 if (wrapperType == directorconstructor)
887 Printf(f->code, "arg0 = &args[0];\n \n");
888
889 /* Now convert from PHP to C variables */
890 // At this point, argcount if used is the number of deliberately passed args
891 // not including this_ptr even if it is used.
892 // It means error messages may be out by argbase with error
893 // reports. We can either take argbase into account when raising
894 // errors, or find a better way of dealing with _thisptr.
895 // I would like, if objects are wrapped, to assume _thisptr is always
896 // _this and not the first argument.
897 // This may mean looking at Language::memberfunctionHandler
898
899 int limit = num_arguments;
900 if (wrapperType == directorconstructor)
901 limit--;
902 for (i = 0, p = l; i < limit; i++) {
903 String *source;
904
905 /* Skip ignored arguments */
906 //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");}
907 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
908 p = Getattr(p, "tmap:in:next");
909 }
910
911 SwigType *pt = Getattr(p, "type");
912
913 if (wrapperType == directorconstructor) {
914 source = NewStringf("args[%d]", i+1);
915 } else {
916 source = NewStringf("args[%d]", i);
917 }
918
919 String *ln = Getattr(p, "lname");
920
921 /* Check if optional */
922 if (i >= num_required) {
923 Printf(f->code, "\tif(arg_count > %d) {\n", i);
924 }
925
926 if ((tm = Getattr(p, "tmap:in"))) {
927 Replaceall(tm, "$source", &source);
928 Replaceall(tm, "$target", ln);
929 Replaceall(tm, "$input", source);
930 Setattr(p, "emit:input", source);
931 Printf(f->code, "%s\n", tm);
932 if (i == 0 && Getattr(p, "self")) {
933 Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n");
934 }
935 p = Getattr(p, "tmap:in:next");
936 if (i >= num_required) {
937 Printf(f->code, "}\n");
938 }
939 continue;
940 } else {
941 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
942 }
943 if (i >= num_required) {
944 Printf(f->code, "\t}\n");
945 }
946 Delete(source);
947 }
948
949 if (is_member_director(n)) {
950 Wrapper_add_local(f, "upcall", "bool upcall = false");
951 Printf(f->code, "upcall = !Swig::Director::swig_is_overridden_method(\"%s%s\", \"%s\");\n",
952 prefix, Swig_class_name(Swig_methodclass(n)), name);
953 }
954
955 Swig_director_emit_dynamic_cast(n, f);
956
957 /* Insert constraint checking code */
958 for (p = l; p;) {
959 if ((tm = Getattr(p, "tmap:check"))) {
960 Replaceall(tm, "$target", Getattr(p, "lname"));
961 Printv(f->code, tm, "\n", NIL);
962 p = Getattr(p, "tmap:check:next");
963 } else {
964 p = nextSibling(p);
965 }
966 }
967
968 /* Insert cleanup code */
969 for (i = 0, p = l; p; i++) {
970 if ((tm = Getattr(p, "tmap:freearg"))) {
971 Replaceall(tm, "$source", Getattr(p, "lname"));
972 Printv(cleanup, tm, "\n", NIL);
973 p = Getattr(p, "tmap:freearg:next");
974 } else {
975 p = nextSibling(p);
976 }
977 }
978
979 /* Insert argument output code */
980 bool hasargout = false;
981 for (i = 0, p = l; p; i++) {
982 if ((tm = Getattr(p, "tmap:argout")) && Len(tm)) {
983 hasargout = true;
984 Replaceall(tm, "$source", Getattr(p, "lname"));
985 // Replaceall(tm,"$input",Getattr(p,"lname"));
986 Replaceall(tm, "$target", "return_value");
987 Replaceall(tm, "$result", "return_value");
988 Replaceall(tm, "$arg", Getattr(p, "emit:input"));
989 Replaceall(tm, "$input", Getattr(p, "emit:input"));
990 Printv(outarg, tm, "\n", NIL);
991 p = Getattr(p, "tmap:argout:next");
992 } else {
993 p = nextSibling(p);
994 }
995 }
996
997 Setattr(n, "wrap:name", wname);
998
999 /* emit function call */
1000 String *actioncode = emit_action(n);
1001
1002 if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
1003 Replaceall(tm, "$input", Swig_cresult_name());
1004 Replaceall(tm, "$source", Swig_cresult_name());
1005 Replaceall(tm, "$target", "return_value");
1006 Replaceall(tm, "$result", "return_value");
1007 Replaceall(tm, "$owner", newobject ? "1" : "0");
1008 Printf(f->code, "%s\n", tm);
1009 } else {
1010 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);
1011 }
1012 emit_return_variable(n, d, f);
1013
1014 if (outarg) {
1015 Printv(f->code, outarg, NIL);
1016 }
1017
1018 if (cleanup) {
1019 Printv(f->code, cleanup, NIL);
1020 }
1021
1022 /* Look to see if there is any newfree cleanup code */
1023 if (GetFlag(n, "feature:new")) {
1024 if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
1025 Printf(f->code, "%s\n", tm);
1026 Delete(tm);
1027 }
1028 }
1029
1030 /* See if there is any return cleanup code */
1031 if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
1032 Printf(f->code, "%s\n", tm);
1033 Delete(tm);
1034 }
1035
1036 Printf(f->code, "thrown:\n");
1037 Printf(f->code, "return;\n");
1038
1039 /* Error handling code */
1040 Printf(f->code, "fail:\n");
1041 Printv(f->code, cleanup, NIL);
1042 Append(f->code, "SWIG_FAIL();\n");
1043
1044 Printf(f->code, "}\n");
1045
1046 Replaceall(f->code, "$cleanup", cleanup);
1047 Replaceall(f->code, "$symname", iname);
1048
1049 Wrapper_print(f, s_wrappers);
1050 DelWrapper(f);
1051 f = NULL;
1052
1053 if (overloaded && !Getattr(n, "sym:nextSibling")) {
1054 dispatchFunction(n);
1055 }
1056
1057 Delete(wname);
1058 wname = NULL;
1059
1060 if (!shadow) {
1061 return SWIG_OK;
1062 }
1063
1064 // Handle getters and setters.
1065 if (wrapperType == membervar) {
1066 const char *p = Char(iname);
1067 if (strlen(p) > 4) {
1068 p += strlen(p) - 4;
1069 String *varname = Getattr(n, "membervariableHandler:sym:name");
1070 if (strcmp(p, "_get") == 0) {
1071 Setattr(shadow_get_vars, varname, Getattr(n, "type"));
1072 } else if (strcmp(p, "_set") == 0) {
1073 Setattr(shadow_set_vars, varname, iname);
1074 }
1075 }
1076 return SWIG_OK;
1077 }
1078
1079 // Only look at non-overloaded methods and the last entry in each overload
1080 // chain (we check the last so that wrap:parms and wrap:name have been set
1081 // for them all).
1082 if (overloaded && Getattr(n, "sym:nextSibling") != 0)
1083 return SWIG_OK;
1084
1085 if (!s_oowrappers)
1086 s_oowrappers = NewStringEmpty();
1087
1088 if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard || wrapperType == staticmembervar) {
1089 bool handle_as_overload = false;
1090 String **arg_names;
1091 String **arg_values;
1092 unsigned char * byref;
1093 // Method or static method or plain function.
1094 const char *methodname = 0;
1095 String *output = s_oowrappers;
1096 if (constructor) {
1097 class_has_ctor = true;
1098 // Skip the Foo:: prefix.
1099 char *ptr = strrchr(GetChar(current_class, "sym:name"), ':');
1100 if (ptr) {
1101 ptr++;
1102 } else {
1103 ptr = GetChar(current_class, "sym:name");
1104 }
1105 if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) {
1106 methodname = "__construct";
1107 } else {
1108 // The class has multiple constructors and this one is
1109 // renamed, so this will be a static factory function
1110 methodname = GetChar(n, "constructorHandler:sym:name");
1111 }
1112 } else if (wrapperType == memberfn) {
1113 methodname = Char(Getattr(n, "memberfunctionHandler:sym:name"));
1114 } else if (wrapperType == staticmemberfn) {
1115 methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name"));
1116 } else if (wrapperType == staticmembervar) {
1117 // Static member variable, wrapped as a function due to PHP limitations.
1118 methodname = Char(Getattr(n, "staticmembervariableHandler:sym:name"));
1119 } else { // wrapperType == standard
1120 methodname = Char(iname);
1121 if (!s_fakeoowrappers)
1122 s_fakeoowrappers = NewStringEmpty();
1123 output = s_fakeoowrappers;
1124 }
1125
1126 bool really_overloaded = overloaded ? true : false;
1127 int min_num_of_arguments = emit_num_required(l);
1128 int max_num_of_arguments = emit_num_arguments(l);
1129
1130 Hash *ret_types = NewHash();
1131 Setattr(ret_types, d, d);
1132
1133 bool non_void_return = (Cmp(d, "void") != 0);
1134
1135 if (overloaded) {
1136 // Look at all the overloaded versions of this method in turn to
1137 // decide if it's really an overloaded method, or just one where some
1138 // parameters have default values.
1139 Node *o = Getattr(n, "sym:overloaded");
1140 while (o) {
1141 if (o == n) {
1142 o = Getattr(o, "sym:nextSibling");
1143 continue;
1144 }
1145
1146 SwigType *d2 = Getattr(o, "type");
1147 if (!d2) {
1148 assert(constructor);
1149 } else if (!Getattr(ret_types, d2)) {
1150 Setattr(ret_types, d2, d2);
1151 non_void_return = non_void_return || (Cmp(d2, "void") != 0);
1152 }
1153
1154 ParmList *l2 = Getattr(o, "wrap:parms");
1155 int num_arguments = emit_num_arguments(l2);
1156 int num_required = emit_num_required(l2);
1157 if (num_required < min_num_of_arguments)
1158 min_num_of_arguments = num_required;
1159
1160 if (num_arguments > max_num_of_arguments) {
1161 max_num_of_arguments = num_arguments;
1162 }
1163 o = Getattr(o, "sym:nextSibling");
1164 }
1165
1166 o = Getattr(n, "sym:overloaded");
1167 while (o) {
1168 if (o == n) {
1169 o = Getattr(o, "sym:nextSibling");
1170 continue;
1171 }
1172
1173 ParmList *l2 = Getattr(o, "wrap:parms");
1174 Parm *p = l, *p2 = l2;
1175 if (wrapperType == memberfn) {
1176 p = nextSibling(p);
1177 p2 = nextSibling(p2);
1178 }
1179 while (p && p2) {
1180 if (Cmp(Getattr(p, "type"), Getattr(p2, "type")) != 0)
1181 break;
1182 if (Cmp(Getattr(p, "name"), Getattr(p2, "name")) != 0)
1183 break;
1184 String *value = Getattr(p, "value");
1185 String *value2 = Getattr(p2, "value");
1186 if (value && !value2)
1187 break;
1188 if (!value && value2)
1189 break;
1190 if (value) {
1191 if (Cmp(value, value2) != 0)
1192 break;
1193 }
1194 p = nextSibling(p);
1195 p2 = nextSibling(p2);
1196 }
1197 if (p && p2)
1198 break;
1199 // One parameter list is a prefix of the other, so check that all
1200 // remaining parameters of the longer list are optional.
1201 if (p2)
1202 p = p2;
1203 while (p && Getattr(p, "value"))
1204 p = nextSibling(p);
1205 if (p)
1206 break;
1207 o = Getattr(o, "sym:nextSibling");
1208 }
1209 if (!o) {
1210 // This "overloaded method" is really just one with default args.
1211 really_overloaded = false;
1212 }
1213 }
1214
1215 if (wrapperType == memberfn) {
1216 // Allow for the "this" pointer.
1217 --min_num_of_arguments;
1218 --max_num_of_arguments;
1219 }
1220
1221 arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *));
1222 if (!arg_names) {
1223 /* FIXME: How should this be handled? The rest of SWIG just seems
1224 * to not bother checking for malloc failing! */
1225 fprintf(stderr, "Malloc failed!\n");
1226 SWIG_exit(EXIT_FAILURE);
1227 }
1228 for (i = 0; i < max_num_of_arguments; ++i) {
1229 arg_names[i] = NULL;
1230 }
1231
1232 arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *));
1233 byref = (unsigned char *) malloc(max_num_of_arguments);
1234 if (!arg_values || !byref) {
1235 /* FIXME: How should this be handled? The rest of SWIG just seems
1236 * to not bother checking for malloc failing! */
1237 fprintf(stderr, "Malloc failed!\n");
1238 SWIG_exit(EXIT_FAILURE);
1239 }
1240 for (i = 0; i < max_num_of_arguments; ++i) {
1241 arg_values[i] = NULL;
1242 byref[i] = false;
1243 }
1244
1245 Node *o;
1246 if (overloaded) {
1247 o = Getattr(n, "sym:overloaded");
1248 } else {
1249 o = n;
1250 }
1251 while (o) {
1252 int argno = 0;
1253 Parm *p = Getattr(o, "wrap:parms");
1254 if (wrapperType == memberfn)
1255 p = nextSibling(p);
1256 while (p) {
1257 if (GetInt(p, "tmap:in:numinputs") == 0) {
1258 p = nextSibling(p);
1259 continue;
1260 }
1261 assert(0 <= argno && argno < max_num_of_arguments);
1262 byref[argno] = GetFlag(p, "tmap:in:byref");
1263 String *&pname = arg_names[argno];
1264 const char *pname_cstr = GetChar(p, "name");
1265 // Just get rid of the C++ namespace part for now.
1266 const char *ptr = NULL;
1267 if (pname_cstr && (ptr = strrchr(pname_cstr, ':'))) {
1268 pname_cstr = ptr + 1;
1269 }
1270 if (!pname_cstr) {
1271 // Unnamed parameter, e.g. int foo(int);
1272 } else if (!pname) {
1273 pname = NewString(pname_cstr);
1274 } else {
1275 size_t len = strlen(pname_cstr);
1276 size_t spc = 0;
1277 size_t len_pname = strlen(Char(pname));
1278 while (spc + len <= len_pname) {
1279 if (strncmp(pname_cstr, Char(pname) + spc, len) == 0) {
1280 char ch = ((char *) Char(pname))[spc + len];
1281 if (ch == '\0' || ch == ' ') {
1282 // Already have this pname_cstr.
1283 pname_cstr = NULL;
1284 break;
1285 }
1286 }
1287 char *p = strchr(Char(pname) + spc, ' ');
1288 if (!p)
1289 break;
1290 spc = (p + 4) - Char(pname);
1291 }
1292 if (pname_cstr) {
1293 Printf(pname, " or_%s", pname_cstr);
1294 }
1295 }
1296 String *value = NewString(Getattr(p, "value"));
1297 if (Len(value)) {
1298 /* Check that value is a valid constant in PHP (and adjust it if
1299 * necessary, or replace it with "?" if it's just not valid). */
1300 SwigType *type = Getattr(p, "type");
1301 switch (SwigType_type(type)) {
1302 case T_BOOL: {
1303 if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0)
1304 break;
1305 char *p;
1306 errno = 0;
1307 long n = strtol(Char(value), &p, 0);
1308 Clear(value);
1309 if (errno || *p) {
1310 Append(value, "?");
1311 } else if (n) {
1312 Append(value, "true");
1313 } else {
1314 Append(value, "false");
1315 }
1316 break;
1317 }
1318 case T_CHAR:
1319 case T_SCHAR:
1320 case T_SHORT:
1321 case T_INT:
1322 case T_LONG:
1323 case T_LONGLONG: {
1324 char *p;
1325 errno = 0;
1326 long n = strtol(Char(value), &p, 0);
1327 (void) n;
1328 if (errno || *p) {
1329 Clear(value);
1330 Append(value, "?");
1331 }
1332 break;
1333 }
1334 case T_UCHAR:
1335 case T_USHORT:
1336 case T_UINT:
1337 case T_ULONG:
1338 case T_ULONGLONG: {
1339 char *p;
1340 errno = 0;
1341 unsigned int n = strtoul(Char(value), &p, 0);
1342 (void) n;
1343 if (errno || *p) {
1344 Clear(value);
1345 Append(value, "?");
1346 }
1347 break;
1348 }
1349 case T_FLOAT:
1350 case T_DOUBLE:
1351 case T_LONGDOUBLE: {
1352 char *p;
1353 errno = 0;
1354 /* FIXME: strtod is locale dependent... */
1355 double val = strtod(Char(value), &p);
1356 if (errno || *p) {
1357 Clear(value);
1358 Append(value, "?");
1359 } else if (strchr(Char(value), '.') == 0) {
1360 // Ensure value is a double constant, not an integer one.
1361 Append(value, ".0");
1362 double val2 = strtod(Char(value), &p);
1363 if (errno || *p || val != val2) {
1364 Clear(value);
1365 Append(value, "?");
1366 }
1367 }
1368 break;
1369 }
1370 case T_STRING:
1371 if (Len(value) < 2) {
1372 // How can a string (including "" be less than 2 characters?)
1373 Clear(value);
1374 Append(value, "?");
1375 } else {
1376 const char *v = Char(value);
1377 if (v[0] != '"' || v[Len(value) - 1] != '"') {
1378 Clear(value);
1379 Append(value, "?");
1380 }
1381 // Strings containing "$" require special handling, but we do
1382 // that later.
1383 }
1384 break;
1385 case T_VOID:
1386 assert(false);
1387 break;
1388 case T_POINTER: {
1389 const char *v = Char(value);
1390 if (v[0] == '(') {
1391 // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc.
1392 v += strcspn(v + 1, "*()") + 1;
1393 if (*v == '*') {
1394 do {
1395 v++;
1396 v += strspn(v, " \t");
1397 } while (*v == '*');
1398 if (*v++ == ')') {
1399 v += strspn(v, " \t");
1400 String * old = value;
1401 value = NewString(v);
1402 Delete(old);
1403 }
1404 }
1405 }
1406 if (Strcmp(value, "NULL") == 0 ||
1407 Strcmp(value, "nullptr") == 0 ||
1408 Strcmp(value, "0") == 0 ||
1409 Strcmp(value, "0L") == 0) {
1410 Clear(value);
1411 Append(value, "null");
1412 } else {
1413 Clear(value);
1414 Append(value, "?");
1415 }
1416 break;
1417 }
1418 default:
1419 /* Safe default */
1420 Clear(value);
1421 Append(value, "?");
1422 break;
1423 }
1424
1425 if (!arg_values[argno]) {
1426 arg_values[argno] = value;
1427 value = NULL;
1428 } else if (Cmp(arg_values[argno], value) != 0) {
1429 // If a parameter has two different default values in
1430 // different overloaded forms of the function, we can't
1431 // set its default in PHP. Flag this by setting its
1432 // default to `?'.
1433 Delete(arg_values[argno]);
1434 arg_values[argno] = NewString("?");
1435 }
1436 } else if (arg_values[argno]) {
1437 // This argument already has a default value in another overloaded
1438 // form, but doesn't in this form. So don't try to do anything
1439 // clever, just let the C wrappers resolve the overload and set the
1440 // default values.
1441 //
1442 // This handling is safe, but I'm wondering if it may be overly
1443 // conservative (FIXME) in some cases. It seems it's only bad when
1444 // there's an overloaded form with the appropriate number of
1445 // parameters which doesn't want the default value, but I need to
1446 // think about this more.
1447 Delete(arg_values[argno]);
1448 arg_values[argno] = NewString("?");
1449 }
1450 Delete(value);
1451 p = nextSibling(p);
1452 ++argno;
1453 }
1454 if (!really_overloaded)
1455 break;
1456 o = Getattr(o, "sym:nextSibling");
1457 }
1458
1459 /* Clean up any parameters which haven't yet got names, or whose
1460 * names clash. */
1461 Hash *seen = NewHash();
1462 /* We need $this to refer to the current class, so can't allow it
1463 * to be used as a parameter. */
1464 Setattr(seen, "this", seen);
1465
1466 for (int argno = 0; argno < max_num_of_arguments; ++argno) {
1467 String *&pname = arg_names[argno];
1468 if (pname) {
1469 Replaceall(pname, " ", "_");
1470 } else {
1471 /* We get here if the SWIG .i file has "int foo(int);" */
1472 pname = NewStringEmpty();
1473 Printf(pname, "arg%d", argno + 1);
1474 }
1475 // Check if we've already used this parameter name.
1476 while (Getattr(seen, pname)) {
1477 // Append "_" to clashing names until they stop clashing...
1478 Printf(pname, "_");
1479 }
1480 Setattr(seen, Char(pname), seen);
1481
1482 if (arg_values[argno] && Cmp(arg_values[argno], "?") == 0) {
1483 handle_as_overload = true;
1484 }
1485 }
1486 Delete(seen);
1487 seen = NULL;
1488
1489 String *invoke = NewStringEmpty();
1490 String *prepare = NewStringEmpty();
1491 String *args = NewStringEmpty();
1492
1493 if (!handle_as_overload && !(really_overloaded && max_num_of_arguments > min_num_of_arguments)) {
1494 Printf(invoke, "%s(", iname);
1495 if (wrapperType == memberfn) {
1496 Printf(invoke, "$this->%s", SWIG_PTR);
1497 }
1498 for (int i = 0; i < max_num_of_arguments; ++i) {
1499 if (i)
1500 Printf(args, ",");
1501 if (i || wrapperType == memberfn)
1502 Printf(invoke, ",");
1503 if (byref[i]) Printf(args, "&");
1504 String *value = arg_values[i];
1505 if (value) {
1506 const char *v = Char(value);
1507 if (v[0] == '"') {
1508 /* In a PHP double quoted string, $ needs to be escaped as \$. */
1509 Replaceall(value, "$", "\\$");
1510 }
1511 Printf(args, "$%s=%s", arg_names[i], value);
1512 } else if (constructor && strcmp(methodname, "__construct") == 0 && i >= 1 && i < min_num_of_arguments) {
1513 // We need to be able to call __construct($resource).
1514 Printf(args, "$%s=null", arg_names[i]);
1515 } else {
1516 Printf(args, "$%s", arg_names[i]);
1517 }
1518 Printf(invoke, "$%s", arg_names[i]);
1519 }
1520 Printf(invoke, ")");
1521 } else {
1522 int i;
1523 for (i = 0; i < min_num_of_arguments; ++i) {
1524 if (i)
1525 Printf(args, ",");
1526 Printf(args, "$%s", arg_names[i]);
1527 }
1528 String *invoke_args = NewStringEmpty();
1529 if (wrapperType == memberfn) {
1530 Printf(invoke_args, "$this->%s", SWIG_PTR);
1531 if (min_num_of_arguments > 0)
1532 Printf(invoke_args, ",");
1533 }
1534 Printf(invoke_args, "%s", args);
1535 if (constructor && min_num_of_arguments > 1) {
1536 // We need to be able to call __construct($resource).
1537 Clear(args);
1538 Printf(args, "$%s", arg_names[0]);
1539 for (i = 1; i < min_num_of_arguments; ++i) {
1540 Printf(args, ",");
1541 Printf(args, "$%s=null", arg_names[i]);
1542 }
1543 }
1544 bool had_a_case = false;
1545 int last_handled_i = i - 1;
1546 for (; i < max_num_of_arguments; ++i) {
1547 if (i)
1548 Printf(args, ",");
1549 const char *value = Char(arg_values[i]);
1550 // FIXME: (really_overloaded && handle_as_overload) is perhaps a
1551 // little conservative, but it doesn't hit any cases that it
1552 // shouldn't for Xapian at least (and we need it to handle
1553 // "Enquire::get_mset()" correctly).
1554 bool non_php_default = ((really_overloaded && handle_as_overload) ||
1555 !value || strcmp(value, "?") == 0);
1556 if (non_php_default)
1557 value = "null";
1558 Printf(args, "$%s=%s", arg_names[i], value);
1559 if (non_php_default) {
1560 if (!had_a_case) {
1561 Printf(prepare, "\t\tswitch (func_num_args()) {\n");
1562 had_a_case = true;
1563 }
1564 Printf(prepare, "\t\t");
1565 while (last_handled_i < i) {
1566 Printf(prepare, "case %d: ", ++last_handled_i);
1567 }
1568 if (non_void_return) {
1569 if ((!directorsEnabled() || !Swig_directorclass(n)) && !constructor) {
1570 Append(prepare, "$r=");
1571 } else if (wrapperType == staticmemberfn || wrapperType == staticmembervar) {
1572 Append(prepare, "$r=");
1573 } else {
1574 Printf(prepare, "$this->%s=", SWIG_PTR);
1575 }
1576 }
1577 if (!directorsEnabled() || !Swig_directorclass(n) || !constructor) {
1578 Printf(prepare, "%s(%s); break;\n", iname, invoke_args);
1579 } else if (!i) {
1580 Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args);
1581 } else {
1582 Printf(prepare, "%s($_this, %s); break;\n", iname, invoke_args);
1583 }
1584 }
1585 if (i || wrapperType == memberfn)
1586 Printf(invoke_args, ",");
1587 Printf(invoke_args, "$%s", arg_names[i]);
1588 }
1589 Printf(prepare, "\t\t");
1590 if (had_a_case)
1591 Printf(prepare, "default: ");
1592 if (non_void_return) {
1593 if ((!directorsEnabled() || !Swig_directorclass(n)) && !constructor) {
1594 Append(prepare, "$r=");
1595 } else if (wrapperType == staticmemberfn || wrapperType == staticmembervar) {
1596 Append(prepare, "$r=");
1597 } else {
1598 Printf(prepare, "$this->%s=", SWIG_PTR);
1599 }
1600 }
1601
1602 if (!directorsEnabled() || !Swig_directorclass(n) || !constructor) {
1603 Printf(prepare, "%s(%s);\n", iname, invoke_args);
1604 } else {
1605 Printf(prepare, "%s($_this, %s);\n", iname, invoke_args);
1606 }
1607 if (had_a_case)
1608 Printf(prepare, "\t\t}\n");
1609 Delete(invoke_args);
1610 Printf(invoke, "$r");
1611 }
1612
1613 Printf(output, "\n");
1614 // If it's a member function or a class constructor...
1615 if (wrapperType == memberfn || (constructor && current_class)) {
1616 String *acc = NewString(Getattr(n, "access"));
1617 // If a base has the same method with public access, then PHP
1618 // requires to have it here as public as well
1619 Node *bases = Getattr(Swig_methodclass(n), "bases");
1620 if (bases && Strcmp(acc, "public") != 0) {
1621 String *warnmsg = 0;
1622 int haspublicbase = 0;
1623 Iterator i = First(bases);
1624 while (i.item) {
1625 Node *j = firstChild(i.item);
1626 while (j) {
1627 String *jname = Getattr(j, "name");
1628 if (!jname || Strcmp(jname, Getattr(n, "name")) != 0) {
1629 j = nextSibling(j);
1630 continue;
1631 }
1632 if (Strcmp(nodeType(j), "cdecl") == 0) {
1633 if (!Getattr(j, "access") || checkAttribute(j, "access", "public")) {
1634 haspublicbase = 1;
1635 }
1636 } else if (Strcmp(nodeType(j), "using") == 0 && firstChild(j) && Strcmp(nodeType(firstChild(j)), "cdecl") == 0) {
1637 if (!Getattr(firstChild(j), "access") || checkAttribute(firstChild(j), "access", "public")) {
1638 haspublicbase = 1;
1639 }
1640 }
1641 if (haspublicbase) {
1642 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"));
1643 break;
1644 }
1645 j = nextSibling(j);
1646 }
1647 i = Next(i);
1648 if (haspublicbase) {
1649 break;
1650 }
1651 }
1652 if (Getattr(n, "access") && haspublicbase) {
1653 Delete(acc);
1654 acc = NewStringEmpty(); // implicitly public
1655 Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg));
1656 Delete(warnmsg);
1657 }
1658 }
1659
1660 if (Cmp(acc, "public") == 0) {
1661 // The default visibility for methods is public, so don't specify
1662 // that explicitly to keep the wrapper size down.
1663 Delete(acc);
1664 acc = NewStringEmpty();
1665 } else if (Cmp(acc, "") != 0) {
1666 Append(acc, " ");
1667 }
1668
1669 if (constructor) {
1670 // Discriminate between the PHP constructor and a C++ constructor
1671 // renamed to become a factory function in PHP.
1672 bool php_constructor = (strcmp(methodname, "__construct") == 0);
1673 const char * arg0 = NULL;
1674 if (max_num_of_arguments > 0) {
1675 arg0 = Char(arg_names[0]);
1676 } else if (php_constructor) {
1677 // The PHP constructor needs to be able to wrap a resource, but a
1678 // renamed constructor doesn't.
1679 arg0 = "res";
1680 Delete(args);
1681 args = NewString("$res=null");
1682 }
1683 String *mangled_type = SwigType_manglestr(Getattr(n, "type"));
1684 if (!php_constructor) {
1685 // A renamed constructor should be a static method.
1686 Append(acc, "static ");
1687 }
1688 Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
1689 if (php_constructor) {
1690 // The PHP constructor needs to be able to wrap a resource, but a
1691 // renamed constructor doesn't.
1692 Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type);
1693 Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0);
1694 Printf(output, "\t\t\treturn;\n");
1695 Printf(output, "\t\t}\n");
1696 }
1697 } else {
1698 Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
1699 }
1700 Delete(acc);
1701 } else if (wrapperType == staticmembervar) {
1702 // We're called twice for a writable static member variable - first
1703 // with "foo_set" and then with "foo_get" - so generate half the
1704 // wrapper function each time.
1705 //
1706 // For a const static member, we only get called once.
1707 static bool started = false;
1708 if (!started) {
1709 Printf(output, "\tstatic function %s() {\n", methodname);
1710 if (max_num_of_arguments) {
1711 // Setter.
1712 Printf(output, "\t\tif (func_num_args()) {\n");
1713 Printf(output, "\t\t\t%s(func_get_arg(0));\n", iname);
1714 Printf(output, "\t\t\treturn;\n");
1715 Printf(output, "\t\t}\n");
1716 started = true;
1717 goto done;
1718 }
1719 }
1720 started = false;
1721 } else {
1722 Printf(output, "\tstatic function %s(%s) {\n", methodname, args);
1723 }
1724
1725 if (!constructor)
1726 Printf(output, "%s", prepare);
1727 if (constructor) {
1728 if (!directorsEnabled() || !Swig_directorclass(n)) {
1729 if (!Len(prepare)) {
1730 if (strcmp(methodname, "__construct") == 0) {
1731 Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke);
1732 } else {
1733 String *classname = Swig_class_name(current_class);
1734 Printf(output, "\t\treturn new %s%s(%s);\n", prefix, classname, invoke);
1735 }
1736 }
1737 } else {
1738 Node *parent = Swig_methodclass(n);
1739 String *classname = Swig_class_name(parent);
1740 Printf(output, "\t\tif (get_class($this) === '%s%s') {\n", prefix, classname);
1741 Printf(output, "\t\t\t$_this = null;\n");
1742 Printf(output, "\t\t} else {\n");
1743 Printf(output, "\t\t\t$_this = $this;\n");
1744 Printf(output, "\t\t}\n");
1745 if (!Len(prepare)) {
1746 if (num_arguments > 1) {
1747 Printf(output, "\t\t$this->%s=%s($_this, %s);\n", SWIG_PTR, iname, args);
1748 } else {
1749 Printf(output, "\t\t$this->%s=%s($_this);\n", SWIG_PTR, iname);
1750 }
1751 }
1752 }
1753 Printf(output, "%s", prepare);
1754 } else if (!non_void_return && !hasargout) {
1755 if (Cmp(invoke, "$r") != 0)
1756 Printf(output, "\t\t%s;\n", invoke);
1757 } else if (is_class(d)) {
1758 if (Cmp(invoke, "$r") != 0)
1759 Printf(output, "\t\t$r=%s;\n", invoke);
1760 if (Len(ret_types) == 1) {
1761 /* If d is abstract we can't create a new wrapper type d. */
1762 Node *d_class = classLookup(d);
1763 int is_abstract = 0;
1764 if (Getattr(d_class, "abstracts")) {
1765 is_abstract = 1;
1766 }
1767 if (newobject || !is_abstract) {
1768 Printf(output, "\t\tif (is_resource($r)) {\n");
1769 if (Getattr(classLookup(Getattr(n, "type")), "module")) {
1770 /*
1771 * _p_Foo -> Foo, _p_ns__Bar -> Bar
1772 * TODO: do this in a more elegant way
1773 */
1774 if (Len(prefix) == 0) {
1775 Printf(output, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n");
1776 } else {
1777 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);
1778 }
1779 Printf(output, "\t\t\tif (class_exists($c)) return new $c($r);\n");
1780 Printf(output, "\t\t\treturn new %s%s($r);\n", prefix, Getattr(classLookup(d), "sym:name"));
1781 } else {
1782 Printf(output, "\t\t\t$c = new stdClass();\n");
1783 Printf(output, "\t\t\t$c->" SWIG_PTR " = $r;\n");
1784 Printf(output, "\t\t\treturn $c;\n");
1785 }
1786 Printf(output, "\t\t}\n\t\treturn $r;\n");
1787 } else {
1788 Printf(output, "\t\t$this->%s = $r;\n", SWIG_PTR);
1789 Printf(output, "\t\treturn $this;\n");
1790 }
1791 } else {
1792 Printf(output, "\t\tif (!is_resource($r)) return $r;\n");
1793 String *wrapobj = NULL;
1794 String *common = NULL;
1795 Iterator i = First(ret_types);
1796 while (i.item) {
1797 SwigType *ret_type = i.item;
1798 i = Next(i);
1799 String *mangled = NewString("_p");
1800 Printf(mangled, "%s", SwigType_manglestr(ret_type));
1801 Node *class_node = Getattr(zend_types, mangled);
1802 if (!class_node) {
1803 /* This is needed when we're returning a pointer to a type
1804 * rather than returning the type by value or reference. */
1805 Delete(mangled);
1806 mangled = NewString(SwigType_manglestr(ret_type));
1807 class_node = Getattr(zend_types, mangled);
1808 if (!class_node) {
1809 // Return type isn't an object, so will be handled by the
1810 // !is_resource() check before the switch.
1811 continue;
1812 }
1813 }
1814 const char *classname = GetChar(class_node, "sym:name");
1815 if (!classname)
1816 classname = GetChar(class_node, "name");
1817 String * action = NewStringEmpty();
1818 if (classname)
1819 Printf(action, "return new %s%s($r);\n", prefix, classname);
1820 else
1821 Printf(action, "return $r;\n");
1822 if (!wrapobj) {
1823 wrapobj = NewString("\t\tswitch (get_resource_type($r)) {\n");
1824 common = action;
1825 } else {
1826 if (common && Cmp(common, action) != 0) {
1827 Delete(common);
1828 common = NULL;
1829 }
1830 }
1831 Printf(wrapobj, "\t\t");
1832 if (i.item) {
1833 Printf(wrapobj, "case '%s': ", mangled);
1834 } else {
1835 Printf(wrapobj, "default: ");
1836 }
1837 Printv(wrapobj, action, NIL);
1838 if (action != common) Delete(action);
1839 Delete(mangled);
1840 }
1841 Printf(wrapobj, "\t\t}\n");
1842 if (common) {
1843 // All cases have the same action, so eliminate the switch
1844 // wrapper.
1845 Printf(output, "\t\t%s", common);
1846 Delete(common);
1847 } else {
1848 Printv(output, wrapobj, NIL);
1849 }
1850 Delete(wrapobj);
1851 }
1852 } else {
1853 if (non_void_return || hasargout) {
1854 Printf(output, "\t\treturn %s;\n", invoke);
1855 } else if (Cmp(invoke, "$r") != 0) {
1856 Printf(output, "\t\t%s;\n", invoke);
1857 }
1858 }
1859 Printf(output, "\t}\n");
1860
1861 done:
1862 Delete(prepare);
1863 Delete(invoke);
1864 free(arg_values);
1865
1866 Delete(args);
1867 args = NULL;
1868
1869 for (int i = 0; i < max_num_of_arguments; ++i) {
1870 Delete(arg_names[i]);
1871 }
1872 free(arg_names);
1873 arg_names = NULL;
1874 }
1875
1876 return SWIG_OK;
1877 }
1878
1879 /* ------------------------------------------------------------
1880 * globalvariableHandler()
1881 * ------------------------------------------------------------ */
1882
globalvariableHandler(Node * n)1883 virtual int globalvariableHandler(Node *n) {
1884 char *name = GetChar(n, "name");
1885 char *iname = GetChar(n, "sym:name");
1886 SwigType *t = Getattr(n, "type");
1887 String *tm;
1888
1889 /* First do the wrappers such as name_set(), name_get()
1890 * as provided by the baseclass's implementation of variableWrapper
1891 */
1892 if (Language::globalvariableHandler(n) == SWIG_NOWRAP) {
1893 return SWIG_NOWRAP;
1894 }
1895
1896 if (!addSymbol(iname, n))
1897 return SWIG_ERROR;
1898
1899 /* First link C variables to PHP */
1900
1901 tm = Swig_typemap_lookup("varinit", n, name, 0);
1902 if (tm) {
1903 Replaceall(tm, "$target", name);
1904 Printf(s_vinit, "%s\n", tm);
1905 } else {
1906 Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
1907 }
1908
1909 /* Now generate PHP -> C sync blocks */
1910 /*
1911 tm = Swig_typemap_lookup("varin", n, name, 0);
1912 if(tm) {
1913 Replaceall(tm, "$symname", iname);
1914 Printf(f_c->code, "%s\n", tm);
1915 } else {
1916 Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
1917 }
1918 */
1919 /* Now generate C -> PHP sync blocks */
1920 /*
1921 if(!GetFlag(n,"feature:immutable")) {
1922
1923 tm = Swig_typemap_lookup("varout", n, name, 0);
1924 if(tm) {
1925 Replaceall(tm, "$symname", iname);
1926 Printf(f_php->code, "%s\n", tm);
1927 } else {
1928 Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
1929 }
1930 }
1931 */
1932 return SWIG_OK;
1933 }
1934
1935 /* ------------------------------------------------------------
1936 * constantWrapper()
1937 * ------------------------------------------------------------ */
1938
constantWrapper(Node * n)1939 virtual int constantWrapper(Node *n) {
1940 String *name = GetChar(n, "name");
1941 String *iname = GetChar(n, "sym:name");
1942 SwigType *type = Getattr(n, "type");
1943 String *rawval = Getattr(n, "rawval");
1944 String *value = rawval ? rawval : Getattr(n, "value");
1945 String *tm;
1946
1947 if (!addSymbol(iname, n))
1948 return SWIG_ERROR;
1949
1950 SwigType_remember(type);
1951
1952 if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
1953 Replaceall(tm, "$source", value);
1954 Replaceall(tm, "$target", name);
1955 Replaceall(tm, "$value", value);
1956 Printf(s_cinit, "%s\n", tm);
1957 }
1958
1959 if (shadow) {
1960 String *enumvalue = GetChar(n, "enumvalue");
1961 String *set_to = iname;
1962
1963 if (!enumvalue) {
1964 enumvalue = GetChar(n, "enumvalueex");
1965 }
1966
1967 if (enumvalue && *Char(enumvalue)) {
1968 // Check for a simple constant expression which is valid in PHP.
1969 // If we find one, initialise the const member with it; otherwise
1970 // we initialise it using the C/C++ wrapped constant.
1971 const char *p;
1972 for (p = Char(enumvalue); *p; ++p) {
1973 if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) {
1974 // FIXME: enhance to handle `<previous_enum> + 1' which is what
1975 // we get for enums that don't have an explicit value set.
1976 break;
1977 }
1978 }
1979 if (!*p)
1980 set_to = enumvalue;
1981 }
1982
1983 if (wrapping_member_constant) {
1984 if (!s_oowrappers)
1985 s_oowrappers = NewStringEmpty();
1986 Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, set_to);
1987 } else {
1988 if (!s_fakeoowrappers)
1989 s_fakeoowrappers = NewStringEmpty();
1990 Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", iname, set_to);
1991 }
1992 }
1993
1994 return SWIG_OK;
1995 }
1996
1997 /*
1998 * PHP::pragma()
1999 *
2000 * Pragma directive.
2001 *
2002 * %pragma(php) code="String" # Includes a string in the .php file
2003 * %pragma(php) include="file.php" # Includes a file in the .php file
2004 */
2005
pragmaDirective(Node * n)2006 virtual int pragmaDirective(Node *n) {
2007 if (!ImportMode) {
2008 String *lang = Getattr(n, "lang");
2009 String *type = Getattr(n, "name");
2010 String *value = Getattr(n, "value");
2011
2012 if (Strcmp(lang, "php") == 0) {
2013 if (Strcmp(type, "code") == 0) {
2014 if (value) {
2015 Printf(pragma_code, "%s\n", value);
2016 }
2017 } else if (Strcmp(type, "include") == 0) {
2018 if (value) {
2019 Printf(pragma_incl, "include '%s';\n", value);
2020 }
2021 } else if (Strcmp(type, "phpinfo") == 0) {
2022 if (value) {
2023 Printf(pragma_phpinfo, "%s\n", value);
2024 }
2025 } else if (Strcmp(type, "version") == 0) {
2026 if (value) {
2027 pragma_version = value;
2028 }
2029 } else {
2030 Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type);
2031 }
2032 }
2033 }
2034 return Language::pragmaDirective(n);
2035 }
2036
2037 /* ------------------------------------------------------------
2038 * classDeclaration()
2039 * ------------------------------------------------------------ */
2040
classDeclaration(Node * n)2041 virtual int classDeclaration(Node *n) {
2042 if (!Getattr(n, "feature:onlychildren")) {
2043 String *symname = Getattr(n, "sym:name");
2044 Setattr(n, "php:proxy", symname);
2045 }
2046
2047 return Language::classDeclaration(n);
2048 }
2049
2050 /* ------------------------------------------------------------
2051 * classHandler()
2052 * ------------------------------------------------------------ */
2053
classHandler(Node * n)2054 virtual int classHandler(Node *n) {
2055 constructors = 0;
2056 current_class = n;
2057
2058 if (shadow) {
2059 char *rename = GetChar(n, "sym:name");
2060
2061 if (!addSymbol(rename, n))
2062 return SWIG_ERROR;
2063 shadow_classname = NewString(rename);
2064
2065 shadow_get_vars = NewHash();
2066 shadow_set_vars = NewHash();
2067
2068 /* Deal with inheritance */
2069 List *baselist = Getattr(n, "bases");
2070 if (baselist) {
2071 Iterator base = First(baselist);
2072 while (base.item && GetFlag(base.item, "feature:ignore")) {
2073 base = Next(base);
2074 }
2075 base = Next(base);
2076 if (base.item) {
2077 /* Warn about multiple inheritance for additional base class(es) */
2078 while (base.item) {
2079 if (GetFlag(base.item, "feature:ignore")) {
2080 base = Next(base);
2081 continue;
2082 }
2083 String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
2084 String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
2085 Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number,
2086 "Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname);
2087 base = Next(base);
2088 }
2089 }
2090 }
2091 }
2092
2093 classnode = n;
2094 Language::classHandler(n);
2095 classnode = 0;
2096
2097 if (shadow) {
2098 List *baselist = Getattr(n, "bases");
2099 Iterator ki, base;
2100
2101 if (baselist) {
2102 base = First(baselist);
2103 while (base.item && GetFlag(base.item, "feature:ignore")) {
2104 base = Next(base);
2105 }
2106 } else {
2107 base.item = NULL;
2108 }
2109
2110 if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) {
2111 Printf(s_phpclasses, "abstract ");
2112 }
2113
2114 Printf(s_phpclasses, "class %s%s ", prefix, shadow_classname);
2115 String *baseclass = NULL;
2116 if (base.item && Getattr(base.item, "module")) {
2117 baseclass = Getattr(base.item, "sym:name");
2118 if (!baseclass)
2119 baseclass = Getattr(base.item, "name");
2120 Printf(s_phpclasses, "extends %s%s ", prefix, baseclass);
2121 } else if (GetFlag(n, "feature:exceptionclass")) {
2122 Append(s_phpclasses, "extends Exception ");
2123 }
2124 {
2125 Node *node = NewHash();
2126 Setattr(node, "type", Getattr(n, "name"));
2127 Setfile(node, Getfile(n));
2128 Setline(node, Getline(n));
2129 String * interfaces = Swig_typemap_lookup("phpinterfaces", node, "", 0);
2130 if (interfaces) {
2131 Printf(s_phpclasses, "implements %s ", interfaces);
2132 }
2133 Delete(node);
2134 }
2135 Printf(s_phpclasses, "{\n\tpublic $%s=null;\n", SWIG_PTR);
2136 if (!baseclass) {
2137 // Only store this in the base class (NB !baseclass means we *are*
2138 // a base class...)
2139 Printf(s_phpclasses, "\tprotected $%s=array();\n", SWIG_DATA);
2140 }
2141
2142 // Write property SET handlers
2143 ki = First(shadow_set_vars);
2144 if (ki.key) {
2145 // This class has setters.
2146 Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n");
2147 // FIXME: tune this threshold...
2148 if (Len(shadow_set_vars) <= 2) {
2149 // Not many setters, so avoid call_user_func.
2150 for (; ki.key; ki = Next(ki)) {
2151 DOH *key = ki.key;
2152 String *iname = ki.item;
2153 Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, iname, SWIG_PTR);
2154 }
2155 } else {
2156 Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname);
2157 Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s,$value);\n", SWIG_PTR);
2158 }
2159 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR);
2160 if (baseclass) {
2161 Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass);
2162 } else {
2163 Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA);
2164 }
2165 Printf(s_phpclasses, "\t}\n");
2166 } else {
2167 Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n");
2168 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR);
2169 if (baseclass) {
2170 Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass);
2171 } else {
2172 Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA);
2173 }
2174 Printf(s_phpclasses, "\t}\n");
2175 }
2176
2177 // Write property GET handlers
2178 ki = First(shadow_get_vars);
2179 if (ki.key) {
2180 // This class has getters.
2181 Printf(s_phpclasses, "\n\tfunction __get($var) {\n");
2182 int non_class_getters = 0;
2183 for (; ki.key; ki = Next(ki)) {
2184 DOH *key = ki.key;
2185 SwigType *d = ki.item;
2186 if (!is_class(d)) {
2187 ++non_class_getters;
2188 continue;
2189 }
2190 Printv(s_phpclasses, "\t\tif ($var === '", key, "') return new ", prefix, Getattr(classLookup(d), "sym:name"), "(", shadow_classname, "_", key, "_get($this->", SWIG_PTR, "));\n", NIL);
2191 }
2192 // FIXME: tune this threshold...
2193 if (non_class_getters <= 2) {
2194 // Not many non-class getters, so avoid call_user_func.
2195 for (ki = First(shadow_get_vars); non_class_getters && ki.key; ki = Next(ki)) {
2196 DOH *key = ki.key;
2197 SwigType *d = ki.item;
2198 if (is_class(d)) continue;
2199 Printv(s_phpclasses, "\t\tif ($var === '", key, "') return ", shadow_classname, "_", key, "_get($this->", SWIG_PTR, ");\n", NIL);
2200 --non_class_getters;
2201 }
2202 } else {
2203 Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname);
2204 Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s);\n", SWIG_PTR);
2205 }
2206 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR);
2207 if (baseclass) {
2208 Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass);
2209 } else {
2210 // Reading an unknown property name gives null in PHP.
2211 Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA);
2212 }
2213 Printf(s_phpclasses, "\t}\n");
2214
2215 /* __isset() should return true for read-only properties, so check for
2216 * *_get() not *_set(). */
2217 Printf(s_phpclasses, "\n\tfunction __isset($var) {\n");
2218 Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_get')) return true;\n", shadow_classname);
2219 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n");
2220 if (baseclass) {
2221 Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass);
2222 } else {
2223 Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA);
2224 }
2225 Printf(s_phpclasses, "\t}\n");
2226 } else {
2227 Printf(s_phpclasses, "\n\tfunction __get($var) {\n");
2228 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR);
2229 if (baseclass) {
2230 Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass);
2231 } else {
2232 Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA);
2233 }
2234 Printf(s_phpclasses, "\t}\n");
2235 Printf(s_phpclasses, "\n\tfunction __isset($var) {\n");
2236 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n");
2237 if (baseclass) {
2238 Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass);
2239 } else {
2240 Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA);
2241 }
2242 Printf(s_phpclasses, "\t}\n");
2243 }
2244
2245 if (!class_has_ctor) {
2246 Printf(s_phpclasses, "\tfunction __construct($h) {\n");
2247 Printf(s_phpclasses, "\t\t$this->%s=$h;\n", SWIG_PTR);
2248 Printf(s_phpclasses, "\t}\n");
2249 }
2250
2251 if (s_oowrappers) {
2252 Printf(s_phpclasses, "%s", s_oowrappers);
2253 Delete(s_oowrappers);
2254 s_oowrappers = NULL;
2255 }
2256 class_has_ctor = false;
2257
2258 Printf(s_phpclasses, "}\n\n");
2259
2260 Delete(shadow_classname);
2261 shadow_classname = NULL;
2262
2263 Delete(shadow_set_vars);
2264 shadow_set_vars = NULL;
2265 Delete(shadow_get_vars);
2266 shadow_get_vars = NULL;
2267 }
2268 return SWIG_OK;
2269 }
2270
2271 /* ------------------------------------------------------------
2272 * memberfunctionHandler()
2273 * ------------------------------------------------------------ */
2274
memberfunctionHandler(Node * n)2275 virtual int memberfunctionHandler(Node *n) {
2276 wrapperType = memberfn;
2277 Language::memberfunctionHandler(n);
2278 wrapperType = standard;
2279
2280 return SWIG_OK;
2281 }
2282
2283 /* ------------------------------------------------------------
2284 * membervariableHandler()
2285 * ------------------------------------------------------------ */
2286
membervariableHandler(Node * n)2287 virtual int membervariableHandler(Node *n) {
2288 wrapperType = membervar;
2289 Language::membervariableHandler(n);
2290 wrapperType = standard;
2291
2292 return SWIG_OK;
2293 }
2294
2295 /* ------------------------------------------------------------
2296 * staticmembervariableHandler()
2297 * ------------------------------------------------------------ */
2298
staticmembervariableHandler(Node * n)2299 virtual int staticmembervariableHandler(Node *n) {
2300 wrapperType = staticmembervar;
2301 Language::staticmembervariableHandler(n);
2302 wrapperType = standard;
2303
2304 return SWIG_OK;
2305 }
2306
2307 /* ------------------------------------------------------------
2308 * staticmemberfunctionHandler()
2309 * ------------------------------------------------------------ */
2310
staticmemberfunctionHandler(Node * n)2311 virtual int staticmemberfunctionHandler(Node *n) {
2312 wrapperType = staticmemberfn;
2313 Language::staticmemberfunctionHandler(n);
2314 wrapperType = standard;
2315
2316 return SWIG_OK;
2317 }
2318
abstractConstructorHandler(Node *)2319 int abstractConstructorHandler(Node *) {
2320 return SWIG_OK;
2321 }
2322
2323 /* ------------------------------------------------------------
2324 * constructorHandler()
2325 * ------------------------------------------------------------ */
2326
constructorHandler(Node * n)2327 virtual int constructorHandler(Node *n) {
2328 constructors++;
2329 if (Swig_directorclass(n)) {
2330 String *name = GetChar(Swig_methodclass(n), "name");
2331 String *ctype = GetChar(Swig_methodclass(n), "classtype");
2332 String *sname = GetChar(Swig_methodclass(n), "sym:name");
2333 String *args = NewStringEmpty();
2334 ParmList *p = Getattr(n, "parms");
2335 int i;
2336
2337 for (i = 0; p; p = nextSibling(p), i++) {
2338 if (i) {
2339 Printf(args, ", ");
2340 }
2341 if (Strcmp(GetChar(p, "type"), SwigType_str(GetChar(p, "type"), 0))) {
2342 SwigType *t = Getattr(p, "type");
2343 Printf(args, "%s", SwigType_rcaststr(t, 0));
2344 if (SwigType_isreference(t)) {
2345 Append(args, "*");
2346 }
2347 }
2348 Printf(args, "arg%d", i+1);
2349 }
2350
2351 /* director ctor code is specific for each class */
2352 Delete(director_ctor_code);
2353 director_ctor_code = NewStringEmpty();
2354 director_prot_ctor_code = NewStringEmpty();
2355 Printf(director_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n");
2356 Printf(director_prot_ctor_code, "if (Z_TYPE_P(arg0) == IS_NULL) { /* not subclassed */\n");
2357 Printf(director_ctor_code, " %s = (%s *)new %s(%s);\n", Swig_cresult_name(), ctype, ctype, args);
2358 Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args);
2359 if (i) {
2360 Insert(args, 0, ", ");
2361 }
2362 Printf(director_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args);
2363 Printf(director_prot_ctor_code, "} else {\n %s = (%s *)new SwigDirector_%s(arg0%s);\n}\n", Swig_cresult_name(), ctype, sname, args);
2364 Delete(args);
2365
2366 wrapperType = directorconstructor;
2367 } else {
2368 wrapperType = constructor;
2369 }
2370 Language::constructorHandler(n);
2371 wrapperType = standard;
2372
2373 return SWIG_OK;
2374 }
2375
2376 /* ------------------------------------------------------------
2377 * CreateZendListDestructor()
2378 * ------------------------------------------------------------ */
2379 //virtual int destructorHandler(Node *n) {
2380 //}
CreateZendListDestructor(Node * n)2381 int CreateZendListDestructor(Node *n) {
2382 String *name = GetChar(Swig_methodclass(n), "name");
2383 String *iname = GetChar(n, "sym:name");
2384 ParmList *l = Getattr(n, "parms");
2385
2386 String *destructorname = NewStringEmpty();
2387 Printf(destructorname, "_%s", Swig_name_wrapper(iname));
2388 Setattr(classnode, "destructor", destructorname);
2389
2390 Wrapper *f = NewWrapper();
2391 Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n");
2392 Printf(f->def, "/* to typecast and do the actual destruction */\n");
2393 Printf(f->def, "static void %s(zend_resource *res, const char *type_name) {\n", destructorname);
2394
2395 Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) res->ptr", NIL);
2396 Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL);
2397 Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL);
2398
2399 emit_parameter_variables(l, f);
2400 emit_attach_parmmaps(l, f);
2401
2402 // Get type of first arg, thing to be destructed
2403 // Skip ignored arguments
2404 Parm *p = l;
2405 //while (Getattr(p,"tmap:ignore")) {p = Getattr(p,"tmap:ignore:next");}
2406 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
2407 p = Getattr(p, "tmap:in:next");
2408 }
2409 SwigType *pt = Getattr(p, "type");
2410
2411 Printf(f->code, " efree(value);\n");
2412 Printf(f->code, " if (! newobject) return; /* can't delete it! */\n");
2413 Printf(f->code, " arg1 = (%s)SWIG_ConvertResourceData(ptr, type_name, SWIGTYPE%s);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt));
2414 Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name));
2415
2416 Setattr(n, "wrap:name", destructorname);
2417
2418 String *actioncode = emit_action(n);
2419 Append(f->code, actioncode);
2420 Delete(actioncode);
2421
2422 Printf(f->code, "thrown:\n");
2423 Append(f->code, "return;\n");
2424 Append(f->code, "fail:\n");
2425 Append(f->code, "SWIG_FAIL();\n");
2426 Printf(f->code, "}\n");
2427
2428 Wrapper_print(f, s_wrappers);
2429 DelWrapper(f);
2430
2431 return SWIG_OK;
2432 }
2433
2434 /* ------------------------------------------------------------
2435 * memberconstantHandler()
2436 * ------------------------------------------------------------ */
2437
memberconstantHandler(Node * n)2438 virtual int memberconstantHandler(Node *n) {
2439 wrapping_member_constant = Getattr(n, "sym:name");
2440 Language::memberconstantHandler(n);
2441 wrapping_member_constant = NULL;
2442 return SWIG_OK;
2443 }
2444
classDirectorInit(Node * n)2445 int classDirectorInit(Node *n) {
2446 String *declaration = Swig_director_declaration(n);
2447 Printf(f_directors_h, "%s\n", declaration);
2448 Printf(f_directors_h, "public:\n");
2449 Delete(declaration);
2450 return Language::classDirectorInit(n);
2451 }
2452
classDirectorEnd(Node * n)2453 int classDirectorEnd(Node *n) {
2454 Printf(f_directors_h, "};\n");
2455 return Language::classDirectorEnd(n);
2456 }
2457
classDirectorConstructor(Node * n)2458 int classDirectorConstructor(Node *n) {
2459 Node *parent = Getattr(n, "parentNode");
2460 String *decl = Getattr(n, "decl");
2461 String *supername = Swig_class_name(parent);
2462 String *classname = NewStringEmpty();
2463 Printf(classname, "SwigDirector_%s", supername);
2464
2465 /* insert self parameter */
2466 Parm *p;
2467 ParmList *superparms = Getattr(n, "parms");
2468 ParmList *parms = CopyParmList(superparms);
2469 String *type = NewString("zval");
2470 SwigType_add_pointer(type);
2471 p = NewParm(type, NewString("self"), n);
2472 set_nextSibling(p, parms);
2473 parms = p;
2474
2475 if (!Getattr(n, "defaultargs")) {
2476 // There should always be a "self" parameter first.
2477 assert(ParmList_len(parms) > 0);
2478
2479 /* constructor */
2480 {
2481 Wrapper *w = NewWrapper();
2482 String *call;
2483 String *basetype = Getattr(parent, "classtype");
2484
2485 String *target = Swig_method_decl(0, decl, classname, parms, 0);
2486 call = Swig_csuperclass_call(0, basetype, superparms);
2487 Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call);
2488 Append(w->def, "}");
2489 Delete(target);
2490 Wrapper_print(w, f_directors);
2491 Delete(call);
2492 DelWrapper(w);
2493 }
2494
2495 /* constructor header */
2496 {
2497 String *target = Swig_method_decl(0, decl, classname, parms, 1);
2498 Printf(f_directors_h, " %s;\n", target);
2499 Delete(target);
2500 }
2501 }
2502 return Language::classDirectorConstructor(n);
2503 }
2504
classDirectorMethod(Node * n,Node * parent,String * super)2505 int classDirectorMethod(Node *n, Node *parent, String *super) {
2506 int is_void = 0;
2507 int is_pointer = 0;
2508 String *decl = Getattr(n, "decl");
2509 String *returntype = Getattr(n, "type");
2510 String *name = Getattr(n, "name");
2511 String *classname = Getattr(parent, "sym:name");
2512 String *c_classname = Getattr(parent, "name");
2513 String *symname = Getattr(n, "sym:name");
2514 String *declaration = NewStringEmpty();
2515 ParmList *l = Getattr(n, "parms");
2516 Wrapper *w = NewWrapper();
2517 String *tm;
2518 String *wrap_args = NewStringEmpty();
2519 String *value = Getattr(n, "value");
2520 String *storage = Getattr(n, "storage");
2521 bool pure_virtual = false;
2522 int status = SWIG_OK;
2523 int idx;
2524 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
2525
2526 if (Cmp(storage, "virtual") == 0) {
2527 if (Cmp(value, "0") == 0) {
2528 pure_virtual = true;
2529 }
2530 }
2531
2532 /* determine if the method returns a pointer */
2533 is_pointer = SwigType_ispointer_return(decl);
2534 is_void = (Cmp(returntype, "void") == 0 && !is_pointer);
2535
2536 /* virtual method definition */
2537 String *target;
2538 String *pclassname = NewStringf("SwigDirector_%s", classname);
2539 String *qualified_name = NewStringf("%s::%s", pclassname, name);
2540 SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
2541 target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
2542 Printf(w->def, "%s", target);
2543 Delete(qualified_name);
2544 Delete(target);
2545 /* header declaration */
2546 target = Swig_method_decl(rtype, decl, name, l, 1);
2547 Printf(declaration, " virtual %s", target);
2548 Delete(target);
2549
2550 // Get any exception classes in the throws typemap
2551 if (Getattr(n, "noexcept")) {
2552 Append(w->def, " noexcept");
2553 Append(declaration, " noexcept");
2554 }
2555 ParmList *throw_parm_list = 0;
2556
2557 if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
2558 Parm *p;
2559 int gencomma = 0;
2560
2561 Append(w->def, " throw(");
2562 Append(declaration, " throw(");
2563
2564 if (throw_parm_list)
2565 Swig_typemap_attach_parms("throws", throw_parm_list, 0);
2566 for (p = throw_parm_list; p; p = nextSibling(p)) {
2567 if (Getattr(p, "tmap:throws")) {
2568 if (gencomma++) {
2569 Append(w->def, ", ");
2570 Append(declaration, ", ");
2571 }
2572 String *str = SwigType_str(Getattr(p, "type"), 0);
2573 Append(w->def, str);
2574 Append(declaration, str);
2575 Delete(str);
2576 }
2577 }
2578
2579 Append(w->def, ")");
2580 Append(declaration, ")");
2581 }
2582
2583 Append(w->def, " {");
2584 Append(declaration, ";\n");
2585
2586 /* declare method return value
2587 * if the return value is a reference or const reference, a specialized typemap must
2588 * handle it, including declaration of c_result ($result).
2589 */
2590 if (!is_void && (!ignored_method || pure_virtual)) {
2591 if (!SwigType_isclass(returntype)) {
2592 if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
2593 String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
2594 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
2595 Delete(construct_result);
2596 } else {
2597 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
2598 }
2599 } else {
2600 String *cres = SwigType_lstr(returntype, "c_result");
2601 Printf(w->code, "%s;\n", cres);
2602 Delete(cres);
2603 }
2604 }
2605
2606 if (ignored_method) {
2607 if (!pure_virtual) {
2608 if (!is_void)
2609 Printf(w->code, "return ");
2610 String *super_call = Swig_method_call(super, l);
2611 Printf(w->code, "%s;\n", super_call);
2612 Delete(super_call);
2613 } else {
2614 Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname),
2615 SwigType_namestr(name));
2616 }
2617 } else {
2618 /* attach typemaps to arguments (C/C++ -> PHP) */
2619 String *parse_args = NewStringEmpty();
2620
2621 Swig_director_parms_fixup(l);
2622
2623 /* remove the wrapper 'w' since it was producing spurious temps */
2624 Swig_typemap_attach_parms("in", l, 0);
2625 Swig_typemap_attach_parms("directorin", l, w);
2626 Swig_typemap_attach_parms("directorargout", l, w);
2627
2628 Parm *p;
2629
2630 int outputs = 0;
2631 if (!is_void)
2632 outputs++;
2633
2634 /* build argument list and type conversion string */
2635 idx = 0;
2636 p = l;
2637 while (p) {
2638 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2639 p = Getattr(p, "tmap:in:next");
2640 continue;
2641 }
2642
2643 if (Getattr(p, "tmap:directorargout") != 0)
2644 outputs++;
2645
2646 String *pname = Getattr(p, "name");
2647 String *ptype = Getattr(p, "type");
2648
2649 if ((tm = Getattr(p, "tmap:directorin")) != 0) {
2650 String *parse = Getattr(p, "tmap:directorin:parse");
2651 if (!parse) {
2652 String *input = NewStringf("&args[%d]", idx++);
2653 Setattr(p, "emit:directorinput", input);
2654 Replaceall(tm, "$input", input);
2655 Delete(input);
2656 Replaceall(tm, "$owner", "0");
2657 Printv(wrap_args, tm, "\n", NIL);
2658 Putc('O', parse_args);
2659 } else {
2660 Append(parse_args, parse);
2661 Setattr(p, "emit:directorinput", pname);
2662 Replaceall(tm, "$input", pname);
2663 Replaceall(tm, "$owner", "0");
2664 if (Len(tm) == 0)
2665 Append(tm, pname);
2666 }
2667 p = Getattr(p, "tmap:directorin:next");
2668 continue;
2669 } else if (Cmp(ptype, "void")) {
2670 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
2671 "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0),
2672 SwigType_namestr(c_classname), SwigType_namestr(name));
2673 status = SWIG_NOWRAP;
2674 break;
2675 }
2676 p = nextSibling(p);
2677 }
2678
2679 /* exception handling */
2680 bool error_used_in_typemap = false;
2681 tm = Swig_typemap_lookup("director:except", n, Swig_cresult_name(), 0);
2682 if (!tm) {
2683 tm = Getattr(n, "feature:director:except");
2684 if (tm)
2685 tm = Copy(tm);
2686 }
2687 if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) {
2688 if (Replaceall(tm, "$error", "error")) {
2689 /* Only declare error if it is used by the typemap. */
2690 error_used_in_typemap = true;
2691 Append(w->code, "int error;\n");
2692 }
2693 } else {
2694 Delete(tm);
2695 tm = NULL;
2696 }
2697
2698 if (!idx) {
2699 Printf(w->code, "zval *args = NULL;\n");
2700 } else {
2701 Printf(w->code, "zval args[%d];\n", idx);
2702 }
2703 // typemap_directorout testcase requires that 0 can be assigned to the
2704 // variable named after the result of Swig_cresult_name(), so that can't
2705 // be a zval - make it a pointer to one instead.
2706 Printf(w->code, "zval swig_zval_result, swig_funcname;\n", Swig_cresult_name());
2707 Printf(w->code, "zval * SWIGUNUSED %s = &swig_zval_result;\n", Swig_cresult_name());
2708 const char * funcname = GetChar(n, "sym:name");
2709 Printf(w->code, "ZVAL_STRINGL(&swig_funcname, \"%s\", %d);\n", funcname, strlen(funcname));
2710
2711 /* wrap complex arguments to zvals */
2712 Printv(w->code, wrap_args, NIL);
2713
2714 if (error_used_in_typemap) {
2715 Append(w->code, "error = ");
2716 }
2717 Append(w->code, "call_user_function(EG(function_table), &swig_self, &swig_funcname,");
2718 Printf(w->code, " &swig_zval_result, %d, args);\n", idx);
2719
2720 if (tm) {
2721 Printv(w->code, Str(tm), "\n", NIL);
2722 Delete(tm);
2723 }
2724
2725 /* marshal return value from PHP to C/C++ type */
2726
2727 String *cleanup = NewStringEmpty();
2728 String *outarg = NewStringEmpty();
2729
2730 idx = 0;
2731
2732 /* marshal return value */
2733 if (!is_void) {
2734 tm = Swig_typemap_lookup("directorout", n, Swig_cresult_name(), w);
2735 if (tm != 0) {
2736 Replaceall(tm, "$input", Swig_cresult_name());
2737 char temp[24];
2738 sprintf(temp, "%d", idx);
2739 Replaceall(tm, "$argnum", temp);
2740
2741 /* TODO check this */
2742 if (Getattr(n, "wrap:disown")) {
2743 Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
2744 } else {
2745 Replaceall(tm, "$disown", "0");
2746 }
2747 Replaceall(tm, "$result", "c_result");
2748 Printv(w->code, tm, "\n", NIL);
2749 Delete(tm);
2750 } else {
2751 Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
2752 "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(returntype, 0), SwigType_namestr(c_classname),
2753 SwigType_namestr(name));
2754 status = SWIG_ERROR;
2755 }
2756 }
2757
2758 /* marshal outputs */
2759 for (p = l; p;) {
2760 if ((tm = Getattr(p, "tmap:directorargout")) != 0) {
2761 Replaceall(tm, "$result", Swig_cresult_name());
2762 Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
2763 Printv(w->code, tm, "\n", NIL);
2764 p = Getattr(p, "tmap:directorargout:next");
2765 } else {
2766 p = nextSibling(p);
2767 }
2768 }
2769
2770 Delete(parse_args);
2771 Delete(cleanup);
2772 Delete(outarg);
2773 }
2774
2775 Append(w->code, "thrown:\n");
2776 if (!is_void) {
2777 if (!(ignored_method && !pure_virtual)) {
2778 String *rettype = SwigType_str(returntype, 0);
2779 if (!SwigType_isreference(returntype)) {
2780 Printf(w->code, "return (%s) c_result;\n", rettype);
2781 } else {
2782 Printf(w->code, "return (%s) *c_result;\n", rettype);
2783 }
2784 Delete(rettype);
2785 }
2786 } else {
2787 Append(w->code, "return;\n");
2788 }
2789
2790 Append(w->code, "fail:\n");
2791 Append(w->code, "SWIG_FAIL();\n");
2792 Append(w->code, "}\n");
2793
2794 // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
2795 String *inline_extra_method = NewStringEmpty();
2796 if (dirprot_mode() && !is_public(n) && !pure_virtual) {
2797 Printv(inline_extra_method, declaration, NIL);
2798 String *extra_method_name = NewStringf("%sSwigPublic", name);
2799 Replaceall(inline_extra_method, name, extra_method_name);
2800 Replaceall(inline_extra_method, ";\n", " {\n ");
2801 if (!is_void)
2802 Printf(inline_extra_method, "return ");
2803 String *methodcall = Swig_method_call(super, l);
2804 Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
2805 Delete(methodcall);
2806 Delete(extra_method_name);
2807 }
2808
2809 /* emit the director method */
2810 if (status == SWIG_OK) {
2811 if (!Getattr(n, "defaultargs")) {
2812 Replaceall(w->code, "$symname", symname);
2813 Wrapper_print(w, f_directors);
2814 Printv(f_directors_h, declaration, NIL);
2815 Printv(f_directors_h, inline_extra_method, NIL);
2816 }
2817 }
2818
2819 /* clean up */
2820 Delete(wrap_args);
2821 Delete(pclassname);
2822 DelWrapper(w);
2823 return status;
2824 }
2825
classDirectorDisown(Node *)2826 int classDirectorDisown(Node *) {
2827 return SWIG_OK;
2828 }
2829 }; /* class PHP */
2830
2831 static PHP *maininstance = 0;
2832
2833 // We use this function to be able to write out zend_register_list_destructor_ex
2834 // lines for most things in the type table
2835 // NOTE: it's a function NOT A PHP::METHOD
2836 extern "C" {
typetrace(const SwigType * ty,String * mangled,String * clientdata)2837 static void typetrace(const SwigType *ty, String *mangled, String *clientdata) {
2838 Node *class_node;
2839 if (!zend_types) {
2840 zend_types = NewHash();
2841 }
2842 // we want to know if the type which reduced to this has a constructor
2843 if ((class_node = maininstance->classLookup(ty))) {
2844 if (!Getattr(zend_types, mangled)) {
2845 // OK it may have been set before by a different SwigType but it would
2846 // have had the same underlying class node I think
2847 // - it is certainly required not to have different originating class
2848 // nodes for the same SwigType
2849 Setattr(zend_types, mangled, class_node);
2850 }
2851 } else { // a non-class pointer
2852 Setattr(zend_types, mangled, NOTCLASS);
2853 }
2854 if (r_prevtracefunc)
2855 (*r_prevtracefunc) (ty, mangled, (String *) clientdata);
2856 }
2857 }
2858
2859 /* -----------------------------------------------------------------------------
2860 * new_swig_php() - Instantiate module
2861 * ----------------------------------------------------------------------------- */
2862
new_swig_php()2863 static Language *new_swig_php() {
2864 maininstance = new PHP;
2865 if (!r_prevtracefunc) {
2866 r_prevtracefunc = SwigType_remember_trace(typetrace);
2867 } else {
2868 Printf(stderr, "php Typetrace vector already saved!\n");
2869 assert(0);
2870 }
2871 return maininstance;
2872 }
2873
swig_php(void)2874 extern "C" Language *swig_php(void) {
2875 return new_swig_php();
2876 }
2877