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