/branches/gsoc2009-ashishs99/Source/Modules/php.cxx

# · C++ · 2016 lines · 1632 code · 178 blank · 206 comment · 297 complexity · f104e2b743bac3e13de366739c846f58 MD5 · raw file

  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at http://www.swig.org/legal.html.
  8. *
  9. * php.cxx
  10. *
  11. * PHP language module for SWIG.
  12. * -----------------------------------------------------------------------------
  13. */
  14. /* FIXME: PHP5 OO wrapping TODO list:
  15. *
  16. * Medium term:
  17. *
  18. * Handle default parameters on overloaded methods in PHP where possible.
  19. * (Mostly done - just need to handle cases of overloaded methods with
  20. * default parameters...)
  21. * This is an optimisation - we could handle this case using a PHP
  22. * default value, but currently we treat it as we would for a default
  23. * value which is a compound C++ expression (i.e. as if we had a
  24. * method with two overloaded forms instead of a single method with
  25. * a default parameter value).
  26. *
  27. * Long term:
  28. *
  29. * Sort out locale-dependent behaviour of strtod() - it's harmless unless
  30. * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably
  31. * OK currently at least.
  32. */
  33. /*
  34. * TODO: Replace remaining stderr messages with Swig_error or Swig_warning
  35. * (may need to add more WARN_PHP_xxx codes...)
  36. */
  37. char cvsroot_php_cxx[] = "$Id: php.cxx 12709 2011-05-23 22:53:10Z ashishs99 $";
  38. #include "swigmod.h"
  39. #include <ctype.h>
  40. #include <errno.h>
  41. static const char *usage = (char *) "\
  42. PHP Options (available with -php)\n\
  43. -cppext <ext> - Change C++ file extension to <ext> (default is cpp)\n\
  44. -noproxy - Don't generate proxy classes.\n\
  45. -prefix <prefix> - Prepend <prefix> to all class names in PHP wrappers\n\
  46. \n";
  47. /* The original class wrappers for PHP stored the pointer to the C++ class in
  48. * the object property _cPtr. If we use the same name for the member variable
  49. * which we put the pointer to the C++ class in, then the flat function
  50. * wrappers will automatically pull it out without any changes being required.
  51. * FIXME: Isn't using a leading underscore a bit suspect here?
  52. */
  53. #define SWIG_PTR "_cPtr"
  54. /* This is the name of the hash where the variables existing only in PHP
  55. * classes are stored.
  56. */
  57. #define SWIG_DATA "_pData"
  58. static int constructors = 0;
  59. static String *NOTCLASS = NewString("Not a class");
  60. static Node *classnode = 0;
  61. static String *module = 0;
  62. static String *cap_module = 0;
  63. static String *prefix = 0;
  64. static String *shadow_classname = 0;
  65. static File *f_begin = 0;
  66. static File *f_runtime = 0;
  67. static File *f_runtime_h = 0;
  68. static File *f_h = 0;
  69. static File *f_phpcode = 0;
  70. static File *f_directors = 0;
  71. static File *f_directors_h = 0;
  72. static String *phpfilename = 0;
  73. static String *s_header;
  74. static String *s_wrappers;
  75. static String *s_init;
  76. static String *r_init; // RINIT user code
  77. static String *s_shutdown; // MSHUTDOWN user code
  78. static String *r_shutdown; // RSHUTDOWN user code
  79. static String *s_vinit; // varinit initialization code.
  80. static String *s_vdecl;
  81. static String *s_cinit; // consttab initialization code.
  82. static String *s_oinit;
  83. static String *s_entry;
  84. static String *cs_entry;
  85. static String *all_cs_entry;
  86. static String *pragma_incl;
  87. static String *pragma_code;
  88. static String *pragma_phpinfo;
  89. static String *s_oowrappers;
  90. static String *s_fakeoowrappers;
  91. static String *s_phpclasses;
  92. /* Variables for using PHP classes */
  93. static Node *current_class = 0;
  94. static Hash *shadow_get_vars;
  95. static Hash *shadow_set_vars;
  96. static Hash *zend_types = 0;
  97. static int shadow = 1;
  98. static bool class_has_ctor = false;
  99. static String *wrapping_member_constant = NULL;
  100. // These static variables are used to pass some state from Handlers into functionWrapper
  101. static enum {
  102. standard = 0,
  103. memberfn,
  104. staticmemberfn,
  105. membervar,
  106. staticmembervar,
  107. constructor,
  108. directorconstructor
  109. } wrapperType = standard;
  110. extern "C" {
  111. static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
  112. }
  113. static void SwigPHP_emit_resource_registrations() {
  114. Iterator ki;
  115. if (!zend_types)
  116. return;
  117. ki = First(zend_types);
  118. if (ki.key)
  119. Printf(s_oinit, "\n/* Register resource destructors for pointer types */\n");
  120. while (ki.key) {
  121. DOH *key = ki.key;
  122. Node *class_node = ki.item;
  123. String *human_name = key;
  124. // Write out destructor function header
  125. Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key);
  126. // write out body
  127. if (class_node != NOTCLASS) {
  128. String *destructor = Getattr(class_node, "destructor");
  129. human_name = Getattr(class_node, "sym:name");
  130. if (!human_name)
  131. human_name = Getattr(class_node, "name");
  132. // Do we have a known destructor for this type?
  133. if (destructor) {
  134. Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key);
  135. } else {
  136. Printf(s_wrappers, " /* No destructor for class %s */\n", human_name);
  137. Printf(s_wrappers, " efree(rsrc->ptr);\n");
  138. }
  139. } else {
  140. Printf(s_wrappers, " /* No destructor for simple type %s */\n", key);
  141. Printf(s_wrappers, " efree(rsrc->ptr);\n");
  142. }
  143. // close function
  144. Printf(s_wrappers, "}\n");
  145. // declare le_swig_<mangled> to store php registration
  146. Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name);
  147. // register with php
  148. Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex"
  149. "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key);
  150. // store php type in class struct
  151. Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key);
  152. ki = Next(ki);
  153. }
  154. }
  155. class PHP : public Language {
  156. public:
  157. PHP() {
  158. director_language = 1;
  159. }
  160. /* ------------------------------------------------------------
  161. * main()
  162. * ------------------------------------------------------------ */
  163. virtual void main(int argc, char *argv[]) {
  164. SWIG_library_directory("php");
  165. SWIG_config_cppext("cpp");
  166. for (int i = 1; i < argc; i++) {
  167. if (strcmp(argv[i], "-prefix") == 0) {
  168. if (argv[i + 1]) {
  169. prefix = NewString(argv[i + 1]);
  170. Swig_mark_arg(i);
  171. Swig_mark_arg(i + 1);
  172. i++;
  173. } else {
  174. Swig_arg_error();
  175. }
  176. } else if (strcmp(argv[i], "-cppext") == 0) {
  177. if (argv[i + 1]) {
  178. SWIG_config_cppext(argv[i + 1]);
  179. Swig_mark_arg(i);
  180. Swig_mark_arg(i + 1);
  181. i++;
  182. } else {
  183. Swig_arg_error();
  184. }
  185. } else if ((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) {
  186. shadow = 0;
  187. Swig_mark_arg(i);
  188. } else if (strcmp(argv[i], "-help") == 0) {
  189. fputs(usage, stdout);
  190. } else if (strcmp(argv[i], "-make") == 0 ||
  191. strcmp(argv[i], "-withc") == 0 ||
  192. strcmp(argv[i], "-withcxx") == 0) {
  193. Printf(stderr, "*** %s is no longer supported.\n", argv[i]);
  194. SWIG_exit(EXIT_FAILURE);
  195. } else if (strcmp(argv[i], "-phpfull") == 0 ||
  196. strcmp(argv[i], "-withlibs") == 0 ||
  197. strcmp(argv[i], "-withincs") == 0) {
  198. Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]);
  199. SWIG_exit(EXIT_FAILURE);
  200. } else if (strcmp(argv[i], "-dlname") == 0) {
  201. Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n");
  202. SWIG_exit(EXIT_FAILURE);
  203. }
  204. }
  205. Preprocessor_define("SWIGPHP 1", 0);
  206. // SWIGPHP5 is deprecated, and no longer documented.
  207. Preprocessor_define("SWIGPHP5 1", 0);
  208. SWIG_typemap_lang("php");
  209. SWIG_config_file("php.swg");
  210. allow_overloading();
  211. }
  212. /* ------------------------------------------------------------
  213. * top()
  214. * ------------------------------------------------------------ */
  215. virtual int top(Node *n) {
  216. String *filen;
  217. /* Check if directors are enabled for this module. */
  218. Node *mod = Getattr(n, "module");
  219. if (mod) {
  220. Node *options = Getattr(mod, "options");
  221. if (options && Getattr(options, "directors")) {
  222. allow_directors();
  223. }
  224. }
  225. /* Set comparison with null for ConstructorToFunction */
  226. setSubclassInstanceCheck(NewString("$arg->type != IS_NULL"));
  227. /* Initialize all of the output files */
  228. String *outfile = Getattr(n, "outfile");
  229. String *outfile_h = Getattr(n, "outfile_h");
  230. /* main output file */
  231. f_begin = NewFile(outfile, "w", SWIG_output_files());
  232. if (!f_begin) {
  233. FileErrorDisplay(outfile);
  234. SWIG_exit(EXIT_FAILURE);
  235. }
  236. f_runtime = NewStringEmpty();
  237. /* sections of the output file */
  238. s_init = NewString("/* init section */\n");
  239. r_init = NewString("/* rinit section */\n");
  240. s_shutdown = NewString("/* shutdown section */\n");
  241. r_shutdown = NewString("/* rshutdown section */\n");
  242. s_header = NewString("/* header section */\n");
  243. s_wrappers = NewString("/* wrapper section */\n");
  244. /* subsections of the init section */
  245. s_vinit = NewString("/* vinit subsection */\n");
  246. s_vdecl = NewString("/* vdecl subsection */\n");
  247. s_cinit = NewString("/* cinit subsection */\n");
  248. s_oinit = NewString("/* oinit subsection */\n");
  249. pragma_phpinfo = NewStringEmpty();
  250. s_phpclasses = NewString("/* PHP Proxy Classes */\n");
  251. f_directors_h = NewStringEmpty();
  252. f_directors = NewStringEmpty();
  253. if (directorsEnabled()) {
  254. f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
  255. if (!f_runtime_h) {
  256. FileErrorDisplay(outfile_h);
  257. SWIG_exit(EXIT_FAILURE);
  258. }
  259. }
  260. /* Register file targets with the SWIG file handler */
  261. Swig_register_filebyname("begin", f_begin);
  262. Swig_register_filebyname("runtime", f_runtime);
  263. Swig_register_filebyname("init", s_init);
  264. Swig_register_filebyname("rinit", r_init);
  265. Swig_register_filebyname("shutdown", s_shutdown);
  266. Swig_register_filebyname("rshutdown", r_shutdown);
  267. Swig_register_filebyname("header", s_header);
  268. Swig_register_filebyname("wrapper", s_wrappers);
  269. Swig_register_filebyname("director", f_directors);
  270. Swig_register_filebyname("director_h", f_directors_h);
  271. Swig_banner(f_begin);
  272. Printf(f_runtime, "\n");
  273. Printf(f_runtime, "#define SWIGPHP\n");
  274. Printf(f_runtime, "\n");
  275. if (directorsEnabled()) {
  276. Printf(f_runtime, "#define SWIG_DIRECTORS\n");
  277. }
  278. /* Set the module name */
  279. module = Copy(Getattr(n, "name"));
  280. cap_module = NewStringf("%(upper)s", module);
  281. if (!prefix)
  282. prefix = NewStringEmpty();
  283. if (directorsEnabled()) {
  284. Swig_banner(f_directors_h);
  285. Printf(f_directors_h, "\n");
  286. Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module);
  287. Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module);
  288. Printf(f_directors, "\n#include \"%s\"\n\n", Swig_file_filename(outfile_h));
  289. }
  290. /* PHP module file */
  291. filen = NewStringEmpty();
  292. Printv(filen, SWIG_output_directory(), module, ".php", NIL);
  293. phpfilename = NewString(filen);
  294. f_phpcode = NewFile(filen, "w", SWIG_output_files());
  295. if (!f_phpcode) {
  296. FileErrorDisplay(filen);
  297. SWIG_exit(EXIT_FAILURE);
  298. }
  299. Printf(f_phpcode, "<?php\n\n");
  300. Swig_banner(f_phpcode);
  301. Printf(f_phpcode, "\n");
  302. Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n");
  303. Printf(f_phpcode, "if (!extension_loaded('%s')) {\n", module);
  304. Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n");
  305. Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module);
  306. Printf(f_phpcode, " } else {\n");
  307. Printf(f_phpcode, " // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.\n");
  308. Printf(f_phpcode, " if (PHP_SHLIB_SUFFIX === 'dylib') {\n");
  309. Printf(f_phpcode, " if (!dl('%s.so')) return;\n", module);
  310. Printf(f_phpcode, " } else {\n");
  311. Printf(f_phpcode, " if (!dl('%s.'.PHP_SHLIB_SUFFIX)) return;\n", module);
  312. Printf(f_phpcode, " }\n");
  313. Printf(f_phpcode, " }\n");
  314. Printf(f_phpcode, "}\n\n");
  315. /* sub-sections of the php file */
  316. pragma_code = NewStringEmpty();
  317. pragma_incl = NewStringEmpty();
  318. /* Initialize the rest of the module */
  319. Printf(s_oinit, "ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, %s_destroy_globals);\n", module, module, module);
  320. /* start the header section */
  321. Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module);
  322. Printf(s_header, "const char *error_msg;\n");
  323. Printf(s_header, "int error_code;\n");
  324. Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module);
  325. Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module);
  326. Printf(s_header, "#ifdef ZTS\n");
  327. Printf(s_header, "#define SWIG_ErrorMsg() TSRMG(%s_globals_id, zend_%s_globals *, error_msg )\n", module, module);
  328. Printf(s_header, "#define SWIG_ErrorCode() TSRMG(%s_globals_id, zend_%s_globals *, error_code )\n", module, module);
  329. Printf(s_header, "#else\n");
  330. Printf(s_header, "#define SWIG_ErrorMsg() (%s_globals.error_msg)\n", module);
  331. Printf(s_header, "#define SWIG_ErrorCode() (%s_globals.error_code)\n", module);
  332. Printf(s_header, "#endif\n\n");
  333. Printf(s_header, "// Allow the user to workaround a PHP bug on some platforms/architectures by\n");
  334. Printf(s_header, "// compiling with -DSWIG_ZEND_ERROR_NORETURN=zend_error\n");
  335. Printf(s_header, "#ifndef SWIG_ZEND_ERROR_NORETURN\n");
  336. Printf(s_header, "# define SWIG_ZEND_ERROR_NORETURN zend_error_noreturn\n");
  337. Printf(s_header, "#endif\n\n");
  338. Printf(s_header, "static void %s_init_globals(zend_%s_globals *globals ) {\n", module, module);
  339. Printf(s_header, " globals->error_msg = default_error_msg;\n");
  340. Printf(s_header, " globals->error_code = default_error_code;\n");
  341. Printf(s_header, "}\n");
  342. Printf(s_header, "static void %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module);
  343. Printf(s_header, "\n");
  344. Printf(s_header, "static void SWIG_ResetError() {\n");
  345. Printf(s_header, " TSRMLS_FETCH();\n");
  346. Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n");
  347. Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n");
  348. Printf(s_header, "}\n");
  349. Append(s_header, "\n");
  350. Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module);
  351. Append(s_header, " zval **args[2];\n");
  352. Append(s_header, " swig_object_wrapper *value;\n");
  353. Append(s_header, " int type;\n");
  354. Append(s_header, " int thisown;\n");
  355. Append(s_header, "\n");
  356. Append(s_header, " SWIG_ResetError();\n");
  357. Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n");
  358. Append(s_header, " WRONG_PARAM_COUNT;\n");
  359. Append(s_header, " }\n");
  360. Append(s_header, "\n");
  361. Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n");
  362. Append(s_header, " value->newobject = zval_is_true(*args[1]);\n");
  363. Append(s_header, "\n");
  364. Append(s_header, " return;\n");
  365. Append(s_header, "}\n");
  366. Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module);
  367. Append(s_header, " zval **args[1];\n");
  368. Append(s_header, " swig_object_wrapper *value;\n");
  369. Append(s_header, " int type;\n");
  370. Append(s_header, "\n");
  371. Append(s_header, " SWIG_ResetError();\n");
  372. Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n");
  373. Append(s_header, " WRONG_PARAM_COUNT;\n");
  374. Append(s_header, " }\n");
  375. Append(s_header, "\n");
  376. Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n");
  377. Append(s_header, " RETVAL_LONG(value->newobject);\n");
  378. Append(s_header, "\n");
  379. Append(s_header, " return;\n");
  380. Append(s_header, "}\n");
  381. Printf(s_header, "#define SWIG_name \"%s\"\n", module);
  382. /* Printf(s_header,"#ifdef HAVE_CONFIG_H\n");
  383. Printf(s_header,"#include \"config.h\"\n");
  384. Printf(s_header,"#endif\n\n");
  385. */
  386. Printf(s_header, "#ifdef __cplusplus\n");
  387. Printf(s_header, "extern \"C\" {\n");
  388. Printf(s_header, "#endif\n");
  389. Printf(s_header, "#include \"php.h\"\n");
  390. Printf(s_header, "#include \"php_ini.h\"\n");
  391. Printf(s_header, "#include \"ext/standard/info.h\"\n");
  392. Printf(s_header, "#include \"php_%s.h\"\n", module);
  393. Printf(s_header, "#ifdef __cplusplus\n");
  394. Printf(s_header, "}\n");
  395. Printf(s_header, "#endif\n\n");
  396. if (directorsEnabled()) {
  397. // Insert director runtime
  398. Swig_insert_file("director.swg", s_header);
  399. }
  400. /* Create the .h file too */
  401. filen = NewStringEmpty();
  402. Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL);
  403. f_h = NewFile(filen, "w", SWIG_output_files());
  404. if (!f_h) {
  405. FileErrorDisplay(filen);
  406. SWIG_exit(EXIT_FAILURE);
  407. }
  408. Swig_banner(f_h);
  409. Printf(f_h, "\n");
  410. Printf(f_h, "#ifndef PHP_%s_H\n", cap_module);
  411. Printf(f_h, "#define PHP_%s_H\n\n", cap_module);
  412. Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module);
  413. Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module);
  414. Printf(f_h, "#ifdef PHP_WIN32\n");
  415. Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module);
  416. Printf(f_h, "#else\n");
  417. Printf(f_h, "# define PHP_%s_API\n", cap_module);
  418. Printf(f_h, "#endif\n\n");
  419. Printf(f_h, "#ifdef ZTS\n");
  420. Printf(f_h, "#include \"TSRM.h\"\n");
  421. Printf(f_h, "#endif\n\n");
  422. Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module);
  423. Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module);
  424. Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module);
  425. Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module);
  426. Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n\n", module);
  427. /* start the function entry section */
  428. s_entry = NewString("/* entry subsection */\n");
  429. /* holds all the per-class function entry sections */
  430. all_cs_entry = NewString("/* class entry subsection */\n");
  431. cs_entry = NULL;
  432. Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n");
  433. Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module);
  434. /* start the init section */
  435. Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n");
  436. Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n");
  437. 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");
  438. Append(s_init, "#endif\n");
  439. Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n" "#if ZEND_MODULE_API_NO > 20010900\n" " STANDARD_MODULE_HEADER,\n" "#endif\n", NIL);
  440. Printf(s_init, " (char*)\"%s\",\n", module);
  441. Printf(s_init, " %s_functions,\n", module);
  442. Printf(s_init, " PHP_MINIT(%s),\n", module);
  443. Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module);
  444. Printf(s_init, " PHP_RINIT(%s),\n", module);
  445. Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module);
  446. Printf(s_init, " PHP_MINFO(%s),\n", module);
  447. Printf(s_init, "#if ZEND_MODULE_API_NO > 20010900\n");
  448. Printf(s_init, " NO_VERSION_YET,\n");
  449. Printf(s_init, "#endif\n");
  450. Printf(s_init, " STANDARD_MODULE_PROPERTIES\n");
  451. Printf(s_init, "};\n");
  452. Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module);
  453. Printf(s_init, "#ifdef __cplusplus\n");
  454. Printf(s_init, "extern \"C\" {\n");
  455. Printf(s_init, "#endif\n");
  456. // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE
  457. // in PHP5 has "extern "C" { ... }" around it so we can't do that.
  458. Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module);
  459. Printf(s_init, "#ifdef __cplusplus\n");
  460. Printf(s_init, "}\n");
  461. Printf(s_init, "#endif\n\n");
  462. /* We have to register the constants before they are (possibly) used
  463. * by the pointer typemaps. This all needs re-arranging really as
  464. * things are being called in the wrong order
  465. */
  466. Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module);
  467. /* Emit all of the code */
  468. Language::top(n);
  469. SwigPHP_emit_resource_registrations();
  470. // Printv(s_init,s_resourcetypes,NIL);
  471. /* We need this after all classes written out by ::top */
  472. Printf(s_oinit, "CG(active_class_entry) = NULL;\n");
  473. Printf(s_oinit, "/* end oinit subsection */\n");
  474. Printf(s_init, "%s\n", s_oinit);
  475. /* Constants generated during top call */
  476. Printf(s_cinit, "/* end cinit subsection */\n");
  477. Printf(s_init, "%s\n", s_cinit);
  478. Clear(s_cinit);
  479. Delete(s_cinit);
  480. Printf(s_init, " return SUCCESS;\n");
  481. Printf(s_init, "}\n\n");
  482. // Now do REQUEST init which holds any user specified %rinit, and also vinit
  483. Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module);
  484. Printf(s_init, "%s\n", r_init);
  485. /* finish our init section which will have been used by class wrappers */
  486. Printf(s_vinit, "/* end vinit subsection */\n");
  487. Printf(s_init, "%s\n", s_vinit);
  488. Clear(s_vinit);
  489. Delete(s_vinit);
  490. Printf(s_init, " return SUCCESS;\n");
  491. Printf(s_init, "}\n\n");
  492. Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
  493. "{\n",
  494. s_shutdown,
  495. "#ifdef ZTS\n"
  496. " ts_free_id(", module, "_globals_id);\n"
  497. "#endif\n"
  498. " return SUCCESS;\n"
  499. "}\n\n", NIL);
  500. Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
  501. Printf(s_init, "%s\n", r_shutdown);
  502. Printf(s_init, " return SUCCESS;\n");
  503. Printf(s_init, "}\n\n");
  504. Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module);
  505. Printf(s_init, "%s", pragma_phpinfo);
  506. Printf(s_init, "}\n");
  507. Printf(s_init, "/* end init section */\n");
  508. Printf(f_h, "#endif /* PHP_%s_H */\n", cap_module);
  509. Close(f_h);
  510. String *type_table = NewStringEmpty();
  511. SwigType_emit_type_table(f_runtime, type_table);
  512. Printf(s_header, "%s", type_table);
  513. Delete(type_table);
  514. /* Oh dear, more things being called in the wrong order. This whole
  515. * function really needs totally redoing.
  516. */
  517. if (directorsEnabled()) {
  518. Dump(f_directors_h, f_runtime_h);
  519. Printf(f_runtime_h, "\n");
  520. Printf(f_runtime_h, "#endif\n");
  521. Close(f_runtime_h);
  522. }
  523. Printf(s_header, "/* end header section */\n");
  524. Printf(s_wrappers, "/* end wrapper section */\n");
  525. Printf(s_vdecl, "/* end vdecl subsection */\n");
  526. Dump(f_runtime, f_begin);
  527. Printv(f_begin, s_header, NIL);
  528. if (directorsEnabled()) {
  529. Dump(f_directors, f_begin);
  530. }
  531. Printv(f_begin, s_vdecl, s_wrappers, NIL);
  532. Printv(f_begin, all_cs_entry, "\n\n", s_entry,
  533. " SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n"
  534. " SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n"
  535. "{NULL, NULL, NULL}\n};\n\n", NIL);
  536. Printv(f_begin, s_init, NIL);
  537. Delete(s_header);
  538. Delete(s_wrappers);
  539. Delete(s_init);
  540. Delete(s_vdecl);
  541. Delete(all_cs_entry);
  542. Delete(s_entry);
  543. Close(f_begin);
  544. Delete(f_runtime);
  545. Delete(f_begin);
  546. Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code);
  547. if (s_fakeoowrappers) {
  548. Printf(f_phpcode, "abstract class %s {", Len(prefix) ? prefix : module);
  549. Printf(f_phpcode, "%s", s_fakeoowrappers);
  550. Printf(f_phpcode, "}\n\n");
  551. Delete(s_fakeoowrappers);
  552. s_fakeoowrappers = NULL;
  553. }
  554. Printf(f_phpcode, "%s\n?>\n", s_phpclasses);
  555. Close(f_phpcode);
  556. return SWIG_OK;
  557. }
  558. /* Just need to append function names to function table to register with PHP. */
  559. void create_command(String *cname, String *iname) {
  560. // This is for the single main zend_function_entry record
  561. Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname);
  562. String * s = cs_entry;
  563. if (!s) s = s_entry;
  564. Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname);
  565. }
  566. /* ------------------------------------------------------------
  567. * dispatchFunction()
  568. * ------------------------------------------------------------ */
  569. void dispatchFunction(Node *n) {
  570. /* Last node in overloaded chain */
  571. int maxargs;
  572. String *tmp = NewStringEmpty();
  573. if (Swig_directorclass(n) && wrapperType == directorconstructor) {
  574. /* We have an extra 'this' parameter. */
  575. SetFlag(n, "wrap:this");
  576. }
  577. String *dispatch = Swig_overload_dispatch(n, "%s(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;", &maxargs);
  578. /* Generate a dispatch wrapper for all overloaded functions */
  579. Wrapper *f = NewWrapper();
  580. String *symname = Getattr(n, "sym:name");
  581. String *wname = Swig_name_wrapper(symname);
  582. create_command(symname, wname);
  583. Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
  584. Wrapper_add_local(f, "argc", "int argc");
  585. Printf(tmp, "zval **argv[%d]", maxargs);
  586. Wrapper_add_local(f, "argv", tmp);
  587. Printf(f->code, "argc = ZEND_NUM_ARGS();\n");
  588. Printf(f->code, "zend_get_parameters_array_ex(argc,argv);\n");
  589. Replaceall(dispatch, "$args", "self,args");
  590. Printv(f->code, dispatch, "\n", NIL);
  591. Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n");
  592. Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname);
  593. Printv(f->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n", NIL);
  594. Printv(f->code, "}\n", NIL);
  595. Wrapper_print(f, s_wrappers);
  596. DelWrapper(f);
  597. Delete(dispatch);
  598. Delete(tmp);
  599. Delete(wname);
  600. }
  601. /* ------------------------------------------------------------
  602. * functionWrapper()
  603. * ------------------------------------------------------------ */
  604. /* Helper method for PHP::functionWrapper */
  605. bool is_class(SwigType *t) {
  606. Node *n = classLookup(t);
  607. if (n) {
  608. String *r = Getattr(n, "php:proxy"); // Set by classDeclaration()
  609. if (!r)
  610. r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name
  611. if (r)
  612. return true;
  613. }
  614. return false;
  615. }
  616. virtual int functionWrapper(Node *n) {
  617. String *name = GetChar(n, "name");
  618. String *iname = GetChar(n, "sym:name");
  619. SwigType *d = Getattr(n, "type");
  620. ParmList *l = Getattr(n, "parms");
  621. String *nodeType = Getattr(n, "nodeType");
  622. int newobject = GetFlag(n, "feature:new");
  623. int constructor = (Cmp(nodeType, "constructor") == 0);
  624. Parm *p;
  625. int i;
  626. int numopt;
  627. String *tm;
  628. Wrapper *f;
  629. String *wname;
  630. int overloaded = 0;
  631. String *overname = 0;
  632. if (Cmp(nodeType, "destructor") == 0) {
  633. // We just generate the Zend List Destructor and let Zend manage the
  634. // reference counting. There's no explicit destructor, but the user can
  635. // just do `$obj = null;' to remove a reference to an object.
  636. return CreateZendListDestructor(n);
  637. }
  638. // Test for overloading;
  639. if (Getattr(n, "sym:overloaded")) {
  640. overloaded = 1;
  641. overname = Getattr(n, "sym:overname");
  642. } else {
  643. if (!addSymbol(iname, n))
  644. return SWIG_ERROR;
  645. }
  646. wname = Swig_name_wrapper(iname);
  647. if (overname) {
  648. Printf(wname, "%s", overname);
  649. }
  650. f = NewWrapper();
  651. numopt = 0;
  652. String *outarg = NewStringEmpty();
  653. String *cleanup = NewStringEmpty();
  654. // Not issued for overloaded functions.
  655. if (!overloaded) {
  656. create_command(iname, wname);
  657. }
  658. Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
  659. emit_parameter_variables(l, f);
  660. /* Attach standard typemaps */
  661. emit_attach_parmmaps(l, f);
  662. // wrap:parms is used by overload resolution.
  663. Setattr(n, "wrap:parms", l);
  664. int num_arguments = emit_num_arguments(l);
  665. int num_required = emit_num_required(l);
  666. numopt = num_arguments - num_required;
  667. if (wrapperType == directorconstructor)
  668. num_arguments++;
  669. if (num_arguments > 0) {
  670. String *args = NewStringEmpty();
  671. if (wrapperType == directorconstructor)
  672. Wrapper_add_local(f, "arg0", "zval *arg0");
  673. Printf(args, "zval **args[%d]", num_arguments);
  674. Wrapper_add_local(f, "args", args);
  675. Delete(args);
  676. args = NULL;
  677. }
  678. if (is_member_director(n)) {
  679. Wrapper_add_local(f, "director", "Swig::Director *director = 0");
  680. Printf(f->code, "director = dynamic_cast<Swig::Director*>(arg1);\n");
  681. Wrapper_add_local(f, "upcall", "bool upcall = false");
  682. Printf(f->code, "upcall = !director->swig_is_overridden_method((char *)\"%s\", (char *)\"%s\");\n",
  683. Swig_class_name(Swig_methodclass(n)), name);
  684. }
  685. // This generated code may be called:
  686. // 1) as an object method, or
  687. // 2) as a class-method/function (without a "this_ptr")
  688. // Option (1) has "this_ptr" for "this", option (2) needs it as
  689. // first parameter
  690. // NOTE: possible we ignore this_ptr as a param for native constructor
  691. Printf(f->code, "SWIG_ResetError();\n");
  692. if (numopt > 0) { // membervariable wrappers do not have optional args
  693. Wrapper_add_local(f, "arg_count", "int arg_count");
  694. Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n");
  695. Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments);
  696. Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n");
  697. Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n");
  698. } else {
  699. if (num_arguments == 0) {
  700. Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n");
  701. } else {
  702. Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments);
  703. }
  704. Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n");
  705. }
  706. if (wrapperType == directorconstructor)
  707. Printf(f->code, "arg0 = *args[0];\n \n");
  708. /* Now convert from PHP to C variables */
  709. // At this point, argcount if used is the number of deliberately passed args
  710. // not including this_ptr even if it is used.
  711. // It means error messages may be out by argbase with error
  712. // reports. We can either take argbase into account when raising
  713. // errors, or find a better way of dealing with _thisptr.
  714. // I would like, if objects are wrapped, to assume _thisptr is always
  715. // _this and not the first argument.
  716. // This may mean looking at Language::memberfunctionHandler
  717. int limit = num_arguments;
  718. if (wrapperType == directorconstructor)
  719. limit--;
  720. for (i = 0, p = l; i < limit; i++) {
  721. String *source;
  722. /* Skip ignored arguments */
  723. //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");}
  724. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  725. p = Getattr(p, "tmap:in:next");
  726. }
  727. SwigType *pt = Getattr(p, "type");
  728. if (wrapperType == directorconstructor) {
  729. source = NewStringf("args[%d]", i+1);
  730. } else {
  731. source = NewStringf("args[%d]", i);
  732. }
  733. String *ln = Getattr(p, "lname");
  734. /* Check if optional */
  735. if (i >= num_required) {
  736. Printf(f->code, "\tif(arg_count > %d) {\n", i);
  737. }
  738. if ((tm = Getattr(p, "tmap:in"))) {
  739. Replaceall(tm, "$source", source);
  740. Replaceall(tm, "$target", ln);
  741. Replaceall(tm, "$input", source);
  742. Setattr(p, "emit:input", source);
  743. Printf(f->code, "%s\n", tm);
  744. if (i == 0 && Getattr(p, "self")) {
  745. Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n");
  746. }
  747. p = Getattr(p, "tmap:in:next");
  748. if (i >= num_required) {
  749. Printf(f->code, "}\n");
  750. }
  751. continue;
  752. } else {
  753. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  754. }
  755. if (i >= num_required) {
  756. Printf(f->code, "\t}\n");
  757. }
  758. Delete(source);
  759. }
  760. Swig_director_emit_dynamic_cast(n, f);
  761. /* Insert constraint checking code */
  762. for (p = l; p;) {
  763. if ((tm = Getattr(p, "tmap:check"))) {
  764. Replaceall(tm, "$target", Getattr(p, "lname"));
  765. Printv(f->code, tm, "\n", NIL);
  766. p = Getattr(p, "tmap:check:next");
  767. } else {
  768. p = nextSibling(p);
  769. }
  770. }
  771. /* Insert cleanup code */
  772. for (i = 0, p = l; p; i++) {
  773. if ((tm = Getattr(p, "tmap:freearg"))) {
  774. Replaceall(tm, "$source", Getattr(p, "lname"));
  775. Printv(cleanup, tm, "\n", NIL);
  776. p = Getattr(p, "tmap:freearg:next");
  777. } else {
  778. p = nextSibling(p);
  779. }
  780. }
  781. /* Insert argument output code */
  782. bool hasargout = false;
  783. for (i = 0, p = l; p; i++) {
  784. if ((tm = Getattr(p, "tmap:argout"))) {
  785. hasargout = true;
  786. Replaceall(tm, "$source", Getattr(p, "lname"));
  787. // Replaceall(tm,"$input",Getattr(p,"lname"));
  788. Replaceall(tm, "$target", "return_value");
  789. Replaceall(tm, "$result", "return_value");
  790. Replaceall(tm, "$arg", Getattr(p, "emit:input"));
  791. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  792. Printv(outarg, tm, "\n", NIL);
  793. p = Getattr(p, "tmap:argout:next");
  794. } else {
  795. p = nextSibling(p);
  796. }
  797. }
  798. Setattr(n, "wrap:name", wname);
  799. /* emit function call */
  800. String *actioncode = emit_action(n);
  801. if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
  802. Replaceall(tm, "$input", "result");
  803. Replaceall(tm, "$source", "result");
  804. Replaceall(tm, "$target", "return_value");
  805. Replaceall(tm, "$result", "return_value");
  806. Replaceall(tm, "$owner", newobject ? "1" : "0");
  807. Printf(f->code, "%s\n", tm);
  808. } else {
  809. 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);
  810. }
  811. emit_return_variable(n, d, f);
  812. if (outarg) {
  813. Printv(f->code, outarg, NIL);
  814. }
  815. if (cleanup) {
  816. Printv(f->code, cleanup, NIL);
  817. }
  818. /* Look to see if there is any newfree cleanup code */
  819. if (GetFlag(n, "feature:new")) {
  820. if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
  821. Printf(f->code, "%s\n", tm);
  822. Delete(tm);
  823. }
  824. }
  825. /* See if there is any return cleanup code */
  826. if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
  827. Printf(f->code, "%s\n", tm);
  828. Delete(tm);
  829. }
  830. Printf(f->code, "return;\n");
  831. /* Error handling code */
  832. Printf(f->code, "fail:\n");
  833. Printv(f->code, cleanup, NIL);
  834. /* This could be zend_error_noreturn(), but that's buggy in PHP ~5.3 and
  835. * using zend_error() here shouldn't generate a warning, so just use that.
  836. * At worst this may result in slightly less good code.
  837. */
  838. Printv(f->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL);
  839. Printf(f->code, "}\n");
  840. Replaceall(f->code, "$cleanup", cleanup);
  841. Replaceall(f->code, "$symname", iname);
  842. Wrapper_print(f, s_wrappers);
  843. DelWrapper(f);
  844. f = NULL;
  845. if (overloaded && !Getattr(n, "sym:nextSibling")) {
  846. dispatchFunction(n);
  847. }
  848. Delete(wname);
  849. wname = NULL;
  850. if (!shadow) {
  851. return SWIG_OK;
  852. }
  853. // Handle getters and setters.
  854. if (wrapperType == membervar) {
  855. const char *p = Char(iname);
  856. if (strlen(p) > 4) {
  857. p += strlen(p) - 4;
  858. String *varname = Getattr(n, "membervariableHandler:sym:name");
  859. if (strcmp(p, "_get") == 0) {
  860. Setattr(shadow_get_vars, varname, iname);
  861. } else if (strcmp(p, "_set") == 0) {
  862. Setattr(shadow_set_vars, varname, iname);
  863. }
  864. }
  865. return SWIG_OK;
  866. }
  867. // Only look at non-overloaded methods and the last entry in each overload
  868. // chain (we check the last so that wrap:parms and wrap:name have been set
  869. // for them all).
  870. if (overloaded && Getattr(n, "sym:nextSibling") != 0)
  871. return SWIG_OK;
  872. if (!s_oowrappers)
  873. s_oowrappers = NewStringEmpty();
  874. if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard || wrapperType == staticmembervar) {
  875. bool handle_as_overload = false;
  876. String **arg_names;
  877. String **arg_values;
  878. // Method or static method or plain function.
  879. const char *methodname = 0;
  880. String *output = s_oowrappers;
  881. if (constructor) {
  882. class_has_ctor = true;
  883. // Skip the Foo:: prefix.
  884. char *ptr = strrchr(GetChar(Swig_methodclass(n), "sym:name"), ':');
  885. if (ptr) {
  886. ptr++;
  887. } else {
  888. ptr = GetChar(Swig_methodclass(n), "sym:name");
  889. }
  890. if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) {
  891. methodname = "__construct";
  892. } else {
  893. // The class has multiple constructors and this one is
  894. // renamed, so this will be a static factory function
  895. methodname = GetChar(n, "constructorHandler:sym:name");
  896. }
  897. } else if (wrapperType == memberfn) {
  898. methodname = Char(Getattr(n, "memberfunctionHandler:sym:name"));
  899. } else if (wrapperType == staticmemberfn) {
  900. methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name"));
  901. } else if (wrapperType == staticmembervar) {
  902. // Static member variable, wrapped as a function due to PHP limitations.
  903. methodname = Char(Getattr(n, "staticmembervariableHandler:sym:name"));
  904. } else { // wrapperType == standard
  905. methodname = Char(iname);
  906. if (!s_fakeoowrappers)
  907. s_fakeoowrappers = NewStringEmpty();
  908. output = s_fakeoowrappers;
  909. }
  910. bool really_overloaded = overloaded ? true : false;
  911. int min_num_of_arguments = emit_num_required(l);
  912. int max_num_of_arguments = emit_num_arguments(l);
  913. // For a function with default arguments, we end up with the fullest
  914. // parmlist in full_parmlist.
  915. ParmList *full_parmlist = l;
  916. Hash *ret_types = NewHash();
  917. Setattr(ret_types, d, d);
  918. bool non_void_return = (Cmp(d, "void") != 0);
  919. if (overloaded) {
  920. // Look at all the overloaded versions of this method in turn to
  921. // decide if it's really an overloaded method, or just one where some
  922. // parameters have default values.
  923. Node *o = Getattr(n, "sym:overloaded");
  924. while (o) {
  925. if (o == n) {
  926. o = Getattr(o, "sym:nextSibling");
  927. continue;
  928. }
  929. SwigType *d2 = Getattr(o, "type");
  930. if (!d2) {
  931. assert(constructor);
  932. } else if (!Getattr(ret_types, d2)) {
  933. Setattr(ret_types, d2, d2);
  934. non_void_return = non_void_return || (Cmp(d2, "void") != 0);
  935. }
  936. ParmList *l2 = Getattr(o, "wrap:parms");
  937. int num_arguments = emit_num_arguments(l2);
  938. int num_required = emit_num_required(l2);
  939. if (num_required < min_num_of_arguments)
  940. min_num_of_arguments = num_required;
  941. if (num_arguments > max_num_of_arguments) {
  942. max_num_of_arguments = num_arguments;
  943. full_parmlist = l2;
  944. }
  945. o = Getattr(o, "sym:nextSibling");
  946. }
  947. o = Getattr(n, "sym:overloaded");
  948. while (o) {
  949. if (o == n) {
  950. o = Getattr(o, "sym:nextSibling");
  951. continue;
  952. }
  953. ParmList *l2 = Getattr(o, "wrap:parms");
  954. Parm *p = l, *p2 = l2;
  955. if (wrapperType == memberfn) {
  956. p = nextSibling(p);
  957. p2 = nextSibling(p2);
  958. }
  959. while (p && p2) {
  960. if (Cmp(Getattr(p, "type"), Getattr(p2, "type")) != 0)
  961. break;
  962. if (Cmp(Getattr(p, "name"), Getattr(p2, "name")) != 0)
  963. break;
  964. String *value = Getattr(p, "value");
  965. String *value2 = Getattr(p2, "value");
  966. if (value && !value2)
  967. break;
  968. if (!value && value2)
  969. break;
  970. if (value) {
  971. if (Cmp(value, value2) != 0)
  972. break;
  973. }
  974. p = nextSibling(p);
  975. p2 = nextSibling(p2);
  976. }
  977. if (p && p2)
  978. break;
  979. // One parameter list is a prefix of the other, so check that all
  980. // remaining parameters of the longer list are optional.
  981. if (p2)
  982. p = p2;
  983. while (p && Getattr(p, "value"))
  984. p = nextSibling(p);
  985. if (p)
  986. break;
  987. o = Getattr(o, "sym:nextSibling");
  988. }
  989. if (!o) {
  990. // This "overloaded method" is really just one with default args.
  991. really_overloaded = false;
  992. if (l != full_parmlist) {
  993. l = full_parmlist;
  994. if (wrapperType == memberfn)
  995. l = nextSibling(l);
  996. }
  997. }
  998. }
  999. if (wrapperType == memberfn) {
  1000. // Allow for the "this" pointer.
  1001. --min_num_of_arguments;
  1002. --max_num_of_arguments;
  1003. }
  1004. arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *));
  1005. if (!arg_names) {
  1006. /* FIXME: How should this be handled? The rest of SWIG just seems
  1007. * to not bother checking for malloc failing! */
  1008. fprintf(stderr, "Malloc failed!\n");
  1009. exit(1);
  1010. }
  1011. for (i = 0; i < max_num_of_arguments; ++i) {
  1012. arg_names[i] = NULL;
  1013. }
  1014. arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *));
  1015. if (!arg_values) {
  1016. /* FIXME: How should this be handled? The rest of SWIG just seems
  1017. * to not bother checking for malloc failing! */
  1018. fprintf(stderr, "Malloc failed!\n");
  1019. exit(1);
  1020. }
  1021. for (i = 0; i < max_num_of_arguments; ++i) {
  1022. arg_values[i] = NULL;
  1023. }
  1024. Node *o;
  1025. if (overloaded) {
  1026. o = Getattr(n, "sym:overloaded");
  1027. } else {
  1028. o = n;
  1029. }
  1030. while (o) {
  1031. int argno = 0;
  1032. Parm *p = Getattr(o, "wrap:parms");
  1033. if (wrapperType == memberfn)
  1034. p = nextSibling(p);
  1035. while (p) {
  1036. if (GetInt(p, "tmap:in:numinputs") == 0) {
  1037. p = nextSibling(p);
  1038. continue;
  1039. }
  1040. assert(0 <= argno && argno < max_num_of_arguments);
  1041. String *&pname = arg_names[argno];
  1042. const char *pname_cstr = GetChar(p, "name");
  1043. // Just get rid of the C++ namespace part for now.
  1044. const char *ptr = NULL;
  1045. if (pname_cstr && (ptr = strrchr(pname_cstr, ':'))) {
  1046. pname_cstr = ptr + 1;
  1047. }
  1048. if (!pname_cstr) {
  1049. // Unnamed parameter, e.g. int foo(int);
  1050. } else if (!pname) {
  1051. pname = NewString(pname_cstr);
  1052. } else {
  1053. size_t len = strlen(pname_cstr);
  1054. size_t spc = 0;
  1055. size_t len_pname = strlen(Char(pname));
  1056. while (spc + len <= len_pname) {
  1057. if (strncmp(pname_cstr, Char(pname) + spc, len) == 0) {
  1058. char ch = ((char *) Char(pname))[spc + len];
  1059. if (ch == '\0' || ch == ' ') {
  1060. // Already have this pname_cstr.
  1061. pname_cstr = NULL;
  1062. break;
  1063. }
  1064. }
  1065. char *p = strchr(Char(pname) + spc, ' ');
  1066. if (!p)
  1067. break;
  1068. spc = (p + 4) - Char(pname);
  1069. }
  1070. if (pname_cstr) {
  1071. Printf(pname, " or_%s", pname_cstr);
  1072. }
  1073. }
  1074. String *value = NewString(Getattr(p, "value"));
  1075. if (Len(value)) {
  1076. /* Check that value is a valid constant in PHP (and adjust it if
  1077. * necessary, or replace it with "?" if it's just not valid). */
  1078. SwigType *type = Getattr(p, "type");
  1079. switch (SwigType_type(type)) {
  1080. case T_BOOL: {
  1081. if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0)
  1082. break;
  1083. char *p;
  1084. errno = 0;
  1085. int n = strtol(Char(value), &p, 0);
  1086. Clear(value);
  1087. if (errno || *p) {
  1088. Append(value, "?");
  1089. } else if (n) {
  1090. Append(value, "true");
  1091. } else {
  1092. Append(value, "false");
  1093. }
  1094. break;
  1095. }
  1096. case T_CHAR:
  1097. case T_SCHAR:
  1098. case T_SHORT:
  1099. case T_INT:
  1100. case T_LONG: {
  1101. char *p;
  1102. errno = 0;
  1103. unsigned int n = strtol(Char(value), &p, 0);
  1104. (void) n;
  1105. if (errno || *p) {
  1106. Clear(value);
  1107. Append(value, "?");
  1108. }
  1109. break;
  1110. }
  1111. case T_UCHAR:
  1112. case T_USHORT:
  1113. case T_UINT:
  1114. case T_ULONG: {
  1115. char *p;
  1116. errno = 0;
  1117. unsigned int n = strtoul(Char(value), &p, 0);
  1118. (void) n;
  1119. if (errno || *p) {
  1120. Clear(value);
  1121. Append(value, "?");
  1122. }
  1123. break;
  1124. }
  1125. case T_FLOAT:
  1126. case T_DOUBLE:{
  1127. char *p;
  1128. errno = 0;
  1129. /* FIXME: strtod is locale dependent... */
  1130. double val = strtod(Char(value), &p);
  1131. if (errno || *p) {
  1132. Clear(value);
  1133. Append(value, "?");
  1134. } else if (strchr(Char(value), '.') == 0) {
  1135. // Ensure value is a double constant, not an integer one.
  1136. Append(value, ".0");
  1137. double val2 = strtod(Char(value), &p);
  1138. if (errno || *p || val != val2) {
  1139. Clear(value);
  1140. Append(value, "?");
  1141. }
  1142. }
  1143. break;
  1144. }
  1145. case T_REFERENCE:
  1146. case T_USER:
  1147. case T_ARRAY:
  1148. Clear(value);
  1149. Append(value, "?");
  1150. break;
  1151. case T_STRING:
  1152. if (Len(value) < 2) {
  1153. // How can a string (including "" be less than 2 characters?)
  1154. Clear(value);
  1155. Append(value, "?");
  1156. } else {
  1157. const char *v = Char(value);
  1158. if (v[0] != '"' || v[Len(value) - 1] != '"') {
  1159. Clear(value);
  1160. Append(value, "?");
  1161. }
  1162. // Strings containing "$" require special handling, but we do
  1163. // that later.
  1164. }
  1165. break;
  1166. case T_VOID:
  1167. assert(false);
  1168. break;
  1169. case T_POINTER: {
  1170. const char *v = Char(value);
  1171. if (v[0] == '(') {
  1172. // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc.
  1173. v += strcspn(v + 1, "*()") + 1;
  1174. if (*v == '*') {
  1175. do {
  1176. v++;
  1177. v += strspn(v, " \t");
  1178. } while (*v == '*');
  1179. if (*v++ == ')') {
  1180. v += strspn(v, " \t");
  1181. String * old = value;
  1182. value = NewString(v);
  1183. Delete(old);
  1184. }
  1185. }
  1186. }
  1187. if (Strcmp(value, "NULL") == 0 ||
  1188. Strcmp(value, "0") == 0 ||
  1189. Strcmp(value, "0L") == 0) {
  1190. Clear(value);
  1191. Append(value, "null");
  1192. } else {
  1193. Clear(value);
  1194. Append(value, "?");
  1195. }
  1196. break;
  1197. }
  1198. }
  1199. if (!arg_values[argno]) {
  1200. arg_values[argno] = value;
  1201. value = NULL;
  1202. } else if (Cmp(arg_values[argno], value) != 0) {
  1203. // If a parameter has two different default values in
  1204. // different overloaded forms of the function, we can't
  1205. // set its default in PHP. Flag this by setting its
  1206. // default to `?'.
  1207. Delete(arg_values[argno]);
  1208. arg_values[argno] = NewString("?");
  1209. }
  1210. } else if (arg_values[argno]) {
  1211. // This argument already has a default value in another overloaded
  1212. // form, but doesn't in this form. So don't try to do anything
  1213. // clever, just let the C wrappers resolve the overload and set the
  1214. // default values.
  1215. //
  1216. // This handling is safe, but I'm wondering if it may be overly
  1217. // conservative (FIXME) in some cases. It seems it's only bad when
  1218. // there's an overloaded form with the appropriate number of
  1219. // parameters which doesn't want the default value, but I need to
  1220. // think about this more.
  1221. Delete(arg_values[argno]);
  1222. arg_values[argno] = NewString("?");
  1223. }
  1224. Delete(value);
  1225. p = nextSibling(p);
  1226. ++argno;
  1227. }
  1228. if (!really_overloaded)
  1229. break;
  1230. o = Getattr(o, "sym:nextSibling");
  1231. }
  1232. /* Clean up any parameters which haven't yet got names, or whose
  1233. * names clash. */
  1234. Hash *seen = NewHash();
  1235. /* We need $this to refer to the current class, so can't allow it
  1236. * to be used as a parameter. */
  1237. Setattr(seen, "this", seen);
  1238. /* We use $r to store the return value, so disallow that as a parameter
  1239. * name in case the user uses the "call-time pass-by-reference" feature
  1240. * (it's deprecated and off by default in PHP5, but we want to be
  1241. * maximally portable). Similarly we use $c for the classname or new
  1242. * stdClass object.
  1243. */
  1244. Setattr(seen, "r", seen);
  1245. Setattr(seen, "c", seen);
  1246. for (int argno = 0; argno < max_num_of_arguments; ++argno) {
  1247. String *&pname = arg_names[argno];
  1248. if (pname) {
  1249. Replaceall(pname, " ", "_");
  1250. } else {
  1251. /* We get here if the SWIG .i file has "int foo(int);" */
  1252. pname = NewStringEmpty();
  1253. Printf(pname, "arg%d", argno + 1);
  1254. }
  1255. // Check if we've already used this parameter name.
  1256. while (Getattr(seen, pname)) {
  1257. // Append "_" to clashing names until they stop clashing...
  1258. Printf(pname, "_");
  1259. }
  1260. Setattr(seen, Char(pname), seen);
  1261. if (arg_values[argno] && Cmp(arg_values[argno], "?") == 0) {
  1262. handle_as_overload = true;
  1263. }
  1264. }
  1265. Delete(seen);
  1266. seen = NULL;
  1267. String *invoke = NewStringEmpty();
  1268. String *prepare = NewStringEmpty();
  1269. String *args = NewStringEmpty();
  1270. if (!handle_as_overload && !(really_overloaded && max_num_of_arguments > min_num_of_arguments)) {
  1271. Printf(invoke, "%s(", iname);
  1272. if (wrapperType == memberfn) {
  1273. Printf(invoke, "$this->%s", SWIG_PTR);
  1274. }
  1275. for (int i = 0; i < max_num_of_arguments; ++i) {
  1276. if (i)
  1277. Printf(args, ",");
  1278. if (i || wrapperType == memberfn)
  1279. Printf(invoke, ",");
  1280. String *value = arg_values[i];
  1281. if (value) {
  1282. const char *v = Char(value);
  1283. if (v[0] == '"') {
  1284. /* In a PHP double quoted string, $ needs to be escaped as \$. */
  1285. Replaceall(value, "$", "\\$");
  1286. }
  1287. Printf(args, "$%s=%s", arg_names[i], value);
  1288. } else {
  1289. Printf(args, "$%s", arg_names[i]);
  1290. }
  1291. Printf(invoke, "$%s", arg_names[i]);
  1292. }
  1293. Printf(invoke, ")");
  1294. } else {
  1295. int i;
  1296. for (i = 0; i < min_num_of_arguments; ++i) {
  1297. if (i)
  1298. Printf(args, ",");
  1299. Printf(args, "$%s", arg_names[i]);
  1300. }
  1301. String *invoke_args = NewStringEmpty();
  1302. if (wrapperType == memberfn) {
  1303. Printf(invoke_args, "$this->%s", SWIG_PTR);
  1304. if (min_num_of_arguments > 0)
  1305. Printf(invoke_args, ",");
  1306. }
  1307. Printf(invoke_args, "%s", args);
  1308. bool had_a_case = false;
  1309. int last_handled_i = i - 1;
  1310. for (; i < max_num_of_arguments; ++i) {
  1311. if (i)
  1312. Printf(args, ",");
  1313. const char *value = Char(arg_values[i]);
  1314. // FIXME: (really_overloaded && handle_as_overload) is perhaps a
  1315. // little conservative, but it doesn't hit any cases that it
  1316. // shouldn't for Xapian at least (and we need it to handle
  1317. // "Enquire::get_mset()" correctly).
  1318. bool non_php_default = ((really_overloaded && handle_as_overload) ||
  1319. !value || strcmp(value, "?") == 0);
  1320. if (non_php_default)
  1321. value = "null";
  1322. Printf(args, "$%s=%s", arg_names[i], value);
  1323. if (non_php_default) {
  1324. if (!had_a_case) {
  1325. Printf(prepare, "\t\tswitch (func_num_args()) {\n");
  1326. had_a_case = true;
  1327. }
  1328. Printf(prepare, "\t\t");
  1329. while (last_handled_i < i) {
  1330. Printf(prepare, "case %d: ", ++last_handled_i);
  1331. }
  1332. if (non_void_return) {
  1333. if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) {
  1334. Append(prepare, "$r=");
  1335. } else {
  1336. Printf(prepare, "$this->%s=", SWIG_PTR);
  1337. }
  1338. }
  1339. if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) {
  1340. Printf(prepare, "%s(%s); break;\n", iname, invoke_args);
  1341. } else if (!i) {
  1342. Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args);
  1343. } else {
  1344. Printf(prepare, "%s($_this, %s); break;\n", iname, invoke_args);
  1345. }
  1346. }
  1347. if (i || wrapperType == memberfn)
  1348. Printf(invoke_args, ",");
  1349. Printf(invoke_args, "$%s", arg_names[i]);
  1350. }
  1351. Printf(prepare, "\t\t");
  1352. if (had_a_case)
  1353. Printf(prepare, "default: ");
  1354. if (non_void_return) {
  1355. if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) {
  1356. Append(prepare, "$r=");
  1357. } else {
  1358. Printf(prepare, "$this->%s=", SWIG_PTR);
  1359. }
  1360. }
  1361. if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) {
  1362. Printf(prepare, "%s(%s);\n", iname, invoke_args);
  1363. } else {
  1364. Printf(prepare, "%s($_this, %s);\n", iname, invoke_args);
  1365. }
  1366. if (had_a_case)
  1367. Printf(prepare, "\t\t}\n");
  1368. Delete(invoke_args);
  1369. Printf(invoke, "$r");
  1370. }
  1371. Printf(output, "\n");
  1372. // If it's a member function or a class constructor...
  1373. if (wrapperType == memberfn || (constructor && current_class)) {
  1374. String *acc = NewString(Getattr(n, "access"));
  1375. // If a base has the same method with public access, then PHP
  1376. // requires to have it here as public as well
  1377. Node *bases = Getattr(Swig_methodclass(n), "bases");
  1378. if (bases && Strcmp(acc, "public") != 0) {
  1379. String *warnmsg = 0;
  1380. int haspublicbase = 0;
  1381. Iterator i = First(bases);
  1382. while (i.item) {
  1383. Node *j = firstChild(i.item);
  1384. while (j) {
  1385. if (Strcmp(Getattr(j, "name"), Getattr(n, "name")) != 0) {
  1386. j = nextSibling(j);
  1387. continue;
  1388. }
  1389. if (Strcmp(nodeType(j), "cdecl") == 0) {
  1390. if (!Getattr(j, "access") || checkAttribute(j, "access", "public")) {
  1391. haspublicbase = 1;
  1392. }
  1393. } else if (Strcmp(nodeType(j), "using") == 0 && firstChild(j) && Strcmp(nodeType(firstChild(j)), "cdecl") == 0) {
  1394. if (!Getattr(firstChild(j), "access") || checkAttribute(firstChild(j), "access", "public")) {
  1395. haspublicbase = 1;
  1396. }
  1397. }
  1398. if (haspublicbase) {
  1399. 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"));
  1400. break;
  1401. }
  1402. j = nextSibling(j);
  1403. }
  1404. i = Next(i);
  1405. if (haspublicbase) {
  1406. break;
  1407. }
  1408. }
  1409. if (Getattr(n, "access") && haspublicbase) {
  1410. Delete(acc);
  1411. acc = NewStringEmpty(); // implicitly public
  1412. Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg));
  1413. Delete(warnmsg);
  1414. }
  1415. }
  1416. if (Cmp(acc, "public") == 0) {
  1417. // The default visibility for methods is public, so don't specify
  1418. // that explicitly to keep the wrapper size down.
  1419. Delete(acc);
  1420. acc = NewStringEmpty();
  1421. } else if (Cmp(acc, "") != 0) {
  1422. Append(acc, " ");
  1423. }
  1424. if (constructor) {
  1425. const char * arg0;
  1426. if (max_num_of_arguments > 0) {
  1427. arg0 = Char(arg_names[0]);
  1428. } else {
  1429. arg0 = "res";
  1430. Delete(args);
  1431. args = NewString("$res=null");
  1432. }
  1433. String *mangled_type = SwigType_manglestr(Getattr(n, "type"));
  1434. Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
  1435. Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type);
  1436. Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0);
  1437. Printf(output, "\t\t\treturn;\n");
  1438. Printf(output, "\t\t}\n");
  1439. } else {
  1440. Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
  1441. }
  1442. Delete(acc);
  1443. } else if (wrapperType == staticmembervar) {
  1444. // We're called twice for a writable static member variable - first
  1445. // with "foo_set" and then with "foo_get" - so generate half the
  1446. // wrapper function each time.
  1447. //
  1448. // For a const static member, we only get called once.
  1449. static bool started = false;
  1450. if (!started) {
  1451. Printf(output, "\tstatic function %s() {\n", methodname);
  1452. if (max_num_of_arguments) {
  1453. // Setter.
  1454. Printf(output, "\t\tif (func_num_args()) {\n");
  1455. Printf(output, "\t\t\t%s(func_get_arg(0));\n", iname);
  1456. Printf(output, "\t\t\treturn;\n");
  1457. Printf(output, "\t\t}\n");
  1458. started = true;
  1459. goto done;
  1460. }
  1461. }
  1462. started = false;
  1463. } else {
  1464. Printf(output, "\tstatic function %s(%s) {\n", methodname, args);
  1465. }
  1466. if (!newobject)
  1467. Printf(output, "%s", prepare);
  1468. if (constructor) {
  1469. if (!directorsEnabled() || !Swig_directorclass(n)) {
  1470. if (!Len(prepare)) {
  1471. if (strcmp(methodname, "__construct") == 0) {
  1472. Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke);
  1473. } else {
  1474. String *classname = Swig_class_name(current_class);
  1475. Printf(output, "\t\treturn new %s(%s);\n", classname, invoke);
  1476. }
  1477. }
  1478. } else {
  1479. Node *parent = Swig_methodclass(n);
  1480. String *classname = Swig_class_name(parent);
  1481. Printf(output, "\t\tif (get_class($this) === '%s%s') {\n", prefix, classname);
  1482. Printf(output, "\t\t\t$_this = null;\n");
  1483. Printf(output, "\t\t} else {\n");
  1484. Printf(output, "\t\t\t$_this = $this;\n");
  1485. Printf(output, "\t\t}\n");
  1486. if (!Len(prepare)) {
  1487. if (num_arguments > 1) {
  1488. Printf(output, "\t\t$this->%s=%s($_this, %s);\n", SWIG_PTR, iname, args);
  1489. } else {
  1490. Printf(output, "\t\t$this->%s=%s($_this);\n", SWIG_PTR, iname);
  1491. }
  1492. }
  1493. }
  1494. Printf(output, "%s", prepare);
  1495. } else if (!non_void_return && !hasargout) {
  1496. if (Cmp(invoke, "$r") != 0)
  1497. Printf(output, "\t\t%s;\n", invoke);
  1498. } else if (is_class(d)) {
  1499. if (Cmp(invoke, "$r") != 0)
  1500. Printf(output, "\t\t$r=%s;\n", invoke);
  1501. if (Len(ret_types) == 1) {
  1502. /* If it has an abstract base, then we can't create a new
  1503. * base object. */
  1504. int hasabstractbase = 0;
  1505. Node *bases = Getattr(Swig_methodclass(n), "bases");
  1506. if (bases) {
  1507. Iterator i = First(bases);
  1508. while(i.item) {
  1509. if (Getattr(i.item, "abstract")) {
  1510. hasabstractbase = 1;
  1511. break;
  1512. }
  1513. i = Next(i);
  1514. }
  1515. }
  1516. if (newobject || !hasabstractbase) {
  1517. /*
  1518. * _p_Foo -> Foo, _p_ns__Bar -> Bar
  1519. * TODO: do this in a more elegant way
  1520. */
  1521. Printf(output, "\t\tif (is_resource($r)) {\n");
  1522. if (Getattr(classLookup(Getattr(n, "type")), "module")) {
  1523. if (Len(prefix) == 0) {
  1524. Printf(output, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n");
  1525. } else {
  1526. 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);
  1527. }
  1528. Printf(output, "\t\t\tif (!class_exists($c)) {\n");
  1529. Printf(output, "\t\t\t\treturn new %s%s($r);\n", prefix, Getattr(classLookup(d), "sym:name"));
  1530. Printf(output, "\t\t\t}\n");
  1531. Printf(output, "\t\t\treturn new $c($r);\n");
  1532. } else {
  1533. Printf(output, "\t\t\t$c = new stdClass();\n");
  1534. Printf(output, "\t\t\t$c->"SWIG_PTR" = $r;\n");
  1535. Printf(output, "\t\t\treturn $c;\n");
  1536. }
  1537. Printf(output, "\t\t}\n\t\treturn $r;\n");
  1538. } else {
  1539. Printf(output, "\t\t$this->%s = $r;\n", SWIG_PTR);
  1540. Printf(output, "\t\treturn $this;\n");
  1541. }
  1542. } else {
  1543. Printf(output, "\t\tif (!is_resource($r)) return $r;\n");
  1544. Printf(output, "\t\tswitch (get_resource_type($r)) {\n");
  1545. Iterator i = First(ret_types);
  1546. while (i.item) {
  1547. SwigType *ret_type = i.item;
  1548. i = Next(i);
  1549. String *mangled = NewString("_p");
  1550. Printf(mangled, "%s", SwigType_manglestr(ret_type));
  1551. Node *class_node = Getattr(zend_types, mangled);
  1552. if (!class_node) {
  1553. /* This is needed when we're returning a pointer to a type
  1554. * rather than returning the type by value or reference. */
  1555. class_node = current_class;
  1556. Delete(mangled);
  1557. mangled = NewString(SwigType_manglestr(ret_type));
  1558. class_node = Getattr(zend_types, mangled);
  1559. if (!class_node) {
  1560. // Return type isn't an object, so will be handled by the
  1561. // !is_resource() check before the switch.
  1562. continue;
  1563. }
  1564. }
  1565. Printf(output, "\t\t");
  1566. if (i.item) {
  1567. Printf(output, "case '%s': ", mangled);
  1568. } else {
  1569. Printf(output, "default: ");
  1570. }
  1571. const char *classname = GetChar(class_node, "sym:name");
  1572. if (!classname)
  1573. classname = GetChar(class_node, "name");
  1574. if (classname)
  1575. Printf(output, "return new %s%s($r);\n", prefix, classname);
  1576. else
  1577. Printf(output, "return $r;\n");
  1578. Delete(mangled);
  1579. }
  1580. Printf(output, "\t\t}\n");
  1581. }
  1582. } else {
  1583. Printf(output, "\t\treturn %s;\n", invoke);
  1584. }
  1585. Printf(output, "\t}\n");
  1586. done:
  1587. Delete(prepare);
  1588. Delete(invoke);
  1589. free(arg_values);
  1590. Delete(args);
  1591. args = NULL;
  1592. for (int i = 0; i < max_num_of_arguments; ++i) {
  1593. Delete(arg_names[i]);
  1594. }
  1595. free(arg_names);
  1596. arg_names = NULL;
  1597. }
  1598. return SWIG_OK;
  1599. }
  1600. /* ------------------------------------------------------------
  1601. * globalvariableHandler()
  1602. * ------------------------------------------------------------ */
  1603. virtual int globalvariableHandler(Node *n) {
  1604. char *name = GetChar(n, "name");
  1605. char *iname = GetChar(n, "sym:name");
  1606. SwigType *t = Getattr(n, "type");
  1607. String *tm;
  1608. /* First do the wrappers such as name_set(), name_get()
  1609. * as provided by the baseclass's implementation of variableWrapper
  1610. */
  1611. if (Language::globalvariableHandler(n) == SWIG_NOWRAP) {
  1612. return SWIG_NOWRAP;
  1613. }
  1614. if (!addSymbol(iname, n))
  1615. return SWIG_ERROR;
  1616. /* First link C variables to PHP */
  1617. tm = Swig_typemap_lookup("varinit", n, name, 0);
  1618. if (tm) {
  1619. Replaceall(tm, "$target", name);
  1620. Printf(s_vinit, "%s\n", tm);
  1621. } else {
  1622. Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
  1623. }
  1624. /* Now generate PHP -> C sync blocks */
  1625. /*
  1626. tm = Swig_typemap_lookup("varin", n, name, 0);
  1627. if(tm) {
  1628. Replaceall(tm, "$symname", iname);
  1629. Printf(f_c->code, "%s\n", tm);
  1630. } else {
  1631. Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
  1632. }
  1633. */
  1634. /* Now generate C -> PHP sync blocks */
  1635. /*
  1636. if(!GetFlag(n,"feature:immutable")) {
  1637. tm = Swig_typemap_lookup("varout", n, name, 0);
  1638. if(tm) {
  1639. Replaceall(tm, "$symname", iname);
  1640. Printf(f_php->code, "%s\n", tm);
  1641. } else {
  1642. Swig_error(input_file, line_number, "Unable to link with type %s\n", SwigType_str(t, 0));
  1643. }
  1644. }
  1645. */
  1646. return SWIG_OK;
  1647. }
  1648. /* ------------------------------------------------------------
  1649. * constantWrapper()
  1650. * ------------------------------------------------------------ */
  1651. virtual int constantWrapper(Node *n) {
  1652. String *name = GetChar(n, "name");
  1653. String *iname = GetChar(n, "sym:name");
  1654. SwigType *type = Getattr(n, "type");
  1655. String *rawval = Getattr(n, "rawval");
  1656. String *value = rawval ? rawval : Getattr(n, "value");
  1657. String *tm;
  1658. if (!addSymbol(iname, n))
  1659. return SWIG_ERROR;
  1660. SwigType_remember(type);
  1661. if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
  1662. Replaceall(tm, "$source", value);
  1663. Replaceall(tm, "$target", name);
  1664. Replaceall(tm, "$value", value);
  1665. Printf(s_cinit, "%s\n", tm);
  1666. }
  1667. if (shadow) {
  1668. String *enumvalue = GetChar(n, "enumvalue");
  1669. String *set_to = iname;
  1670. if (!enumvalue) {
  1671. enumvalue = GetChar(n, "enumvalueex");
  1672. }
  1673. if (enumvalue) {
  1674. // Check for a simple constant expression which is valid in PHP.
  1675. // If we find one, initialise the const member with it; otherwise
  1676. // we initialise it using the C/C++ wrapped constant.
  1677. const char *p;
  1678. for (p = Char(enumvalue); *p; ++p) {
  1679. if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) {
  1680. // FIXME: enhance to handle `<previous_enum> + 1' which is what
  1681. // we get for enums that don't have an explicit value set.
  1682. break;
  1683. }
  1684. }
  1685. if (!*p) set_to = enumvalue;
  1686. }
  1687. if (wrapping_member_constant) {
  1688. if (!s_oowrappers)
  1689. s_oowrappers = NewStringEmpty();
  1690. Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, set_to);
  1691. } else {
  1692. if (!s_fakeoowrappers)
  1693. s_fakeoowrappers = NewStringEmpty();
  1694. Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", iname, set_to);
  1695. }
  1696. }
  1697. return SWIG_OK;
  1698. }
  1699. /*
  1700. * PHP::pragma()
  1701. *
  1702. * Pragma directive.
  1703. *
  1704. * %pragma(php) code="String" # Includes a string in the .php file
  1705. * %pragma(php) include="file.php" # Includes a file in the .php file
  1706. */
  1707. virtual int pragmaDirective(Node *n) {
  1708. if (!ImportMode) {
  1709. String *lang = Getattr(n, "lang");
  1710. String *type = Getattr(n, "name");
  1711. String *value = Getattr(n, "value");
  1712. if (Strcmp(lang, "php") == 0 || Strcmp(lang, "php4") == 0) {
  1713. if (Strcmp(type, "code") == 0) {
  1714. if (value) {
  1715. Printf(pragma_code, "%s\n", value);
  1716. }
  1717. } else if (Strcmp(type, "include") == 0) {
  1718. if (value) {
  1719. Printf(pragma_incl, "include '%s';\n", value);
  1720. }
  1721. } else if (Strcmp(type, "phpinfo") == 0) {
  1722. if (value) {
  1723. Printf(pragma_phpinfo, "%s\n", value);
  1724. }
  1725. } else {
  1726. Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type);
  1727. }
  1728. }
  1729. }
  1730. return Language::pragmaDirective(n);
  1731. }
  1732. /* ------------------------------------------------------------
  1733. * classDeclaration()
  1734. * ------------------------------------------------------------ */
  1735. virtual int classDeclaration(Node *n) {
  1736. if (!Getattr(n, "feature:onlychildren")) {
  1737. String *symname = Getattr(n, "sym:name");
  1738. Setattr(n, "php:proxy", symname);
  1739. }
  1740. return Language::classDeclaration(n);
  1741. }
  1742. /* ------------------------------------------------------------
  1743. * classHandler()
  1744. * ------------------------------------------------------------ */
  1745. virtual int classHandler(Node *n) {
  1746. constructors = 0;
  1747. current_class = n;
  1748. if (shadow) {
  1749. char *rename = GetChar(n, "sym:name");
  1750. if (!addSymbol(rename, n))
  1751. return SWIG_ERROR;
  1752. shadow_classname = NewString(rename);
  1753. shadow_get_vars = NewHash();
  1754. shadow_set_vars = NewHash();
  1755. /* Deal with inheritance */
  1756. List *baselist = Getattr(n, "bases");
  1757. if (baselist) {
  1758. Iterator base = First(baselist);
  1759. while (base.item && GetFlag(base.item, "feature:ignore")) {
  1760. base = Next(base);
  1761. }
  1762. base = Next(base);
  1763. if (base.item) {
  1764. /* Warn about multiple inheritance for additional base class(es) */
  1765. while (base.item) {
  1766. if (GetFlag(base.item, "feature:ignore")) {
  1767. base = Next(base);
  1768. continue;
  1769. }
  1770. String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
  1771. String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
  1772. Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number,
  1773. "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname);
  1774. base = Next(base);
  1775. }
  1776. }
  1777. }
  1778. }
  1779. classnode = n;
  1780. Language::classHandler(n);
  1781. classnode = 0;
  1782. if (shadow) {
  1783. DOH *key;
  1784. List *baselist = Getattr(n, "bases");
  1785. Iterator ki, base;
  1786. if (baselist) {
  1787. base = First(baselist);
  1788. while (base.item && GetFlag(base.item, "feature:ignore")) {
  1789. base = Next(base);
  1790. }
  1791. } else {
  1792. base.item = NULL;
  1793. }
  1794. if (Getattr(n, "abstract") && !GetFlag(n, "feature:notabstract")) {
  1795. Printf(s_phpc