PageRenderTime 65ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/gsoc2008-cherylfoil/Source/Modules/php.cxx

#
C++ | 2064 lines | 1640 code | 198 blank | 226 comment | 278 complexity | 678cf60574cb5c9d2bb85cdd3e4301a2 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0

Large files files are truncated, but you can click here to view the full 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. * php4.cxx
  10. *
  11. * Php language module for SWIG.
  12. * -----------------------------------------------------------------------------
  13. */
  14. /* FIXME: PHP5 OO wrapping TODO list:
  15. *
  16. * Short term:
  17. *
  18. * Sort out auto-renaming of method and class names which are reserved
  19. * words (e.g. empty, clone, exception, etc.)
  20. *
  21. * Sort out wrapping of static member variables in OO PHP5.
  22. *
  23. * Medium term:
  24. *
  25. * Handle default parameters on overloaded methods in PHP where possible.
  26. * (Mostly done - just need to handle cases of overloaded methods with
  27. * default parameters...)
  28. * This is an optimisation - we could handle this case using a PHP
  29. * default value, but currently we treat it as we would for a default
  30. * value which is a compound C++ expression (i.e. as if we had a
  31. * method with two overloaded forms instead of a single method with
  32. * a default parameter value).
  33. *
  34. * Long term:
  35. *
  36. * Sort out locale-dependent behaviour of strtod() - it's harmless unless
  37. * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably
  38. * OK currently at least.
  39. */
  40. /*
  41. * TODO: Replace remaining stderr messages with Swig_error or Swig_warning
  42. * (may need to add more WARN_PHP_xxx codes...)
  43. */
  44. char cvsroot_php4_cxx[] = "$Id: php.cxx 11900 2010-03-05 23:43:39Z wsfulton $";
  45. #include "swigmod.h"
  46. #include <ctype.h>
  47. #include <errno.h>
  48. static const char *usage = (char *) "\
  49. PHP Options (available with -php5)\n\
  50. -cppext - cpp file extension (default to .cpp)\n\
  51. -noproxy - Don't generate proxy classes.\n\
  52. -prefix <prefix> - Prepend <prefix> to all class names in PHP5 wrappers\n\
  53. \n";
  54. /* The original class wrappers for PHP4 store the pointer to the C++ class in
  55. * the object property _cPtr. If we use the same name for the member variable
  56. * which we put the pointer to the C++ class in, then the flat function
  57. * wrappers will automatically pull it out without any changes being required.
  58. * FIXME: Isn't using a leading underscore a bit suspect here?
  59. */
  60. #define SWIG_PTR "_cPtr"
  61. static int constructors = 0;
  62. static String *NOTCLASS = NewString("Not a class");
  63. static Node *classnode = 0;
  64. static String *module = 0;
  65. static String *cap_module = 0;
  66. static String *prefix = 0;
  67. static String *shadow_classname = 0;
  68. static File *f_runtime = 0;
  69. static File *f_h = 0;
  70. static File *f_phpcode = 0;
  71. static String *phpfilename = 0;
  72. static String *s_header;
  73. static String *s_wrappers;
  74. static String *s_init;
  75. static String *r_init; // RINIT user code
  76. static String *s_shutdown; // MSHUTDOWN user code
  77. static String *r_shutdown; // RSHUTDOWN user code
  78. static String *s_vinit; // varinit initialization code.
  79. static String *s_vdecl;
  80. static String *s_cinit; // consttab initialization code.
  81. static String *s_oinit;
  82. static String *s_entry;
  83. static String *cs_entry;
  84. static String *all_cs_entry;
  85. static String *pragma_incl;
  86. static String *pragma_code;
  87. static String *pragma_phpinfo;
  88. static String *s_oowrappers;
  89. static String *s_fakeoowrappers;
  90. static String *s_phpclasses;
  91. /* Variables for using PHP classes */
  92. static Node *current_class = 0;
  93. static Hash *shadow_get_vars;
  94. static Hash *shadow_set_vars;
  95. static Hash *zend_types = 0;
  96. static int shadow = 1;
  97. static bool class_has_ctor = false;
  98. static String *wrapping_member_constant = NULL;
  99. // These static variables are used to pass some state from Handlers into functionWrapper
  100. static enum {
  101. standard = 0,
  102. memberfn,
  103. staticmemberfn,
  104. membervar,
  105. staticmembervar,
  106. constructor,
  107. destructor
  108. } wrapperType = standard;
  109. extern "C" {
  110. static void (*r_prevtracefunc) (SwigType *t, String *mangled, String *clientdata) = 0;
  111. }
  112. void SwigPHP_emit_resource_registrations() {
  113. Iterator ki;
  114. if (!zend_types)
  115. return;
  116. ki = First(zend_types);
  117. if (ki.key)
  118. Printf(s_oinit, "\n/* Register resource destructors for pointer types */\n");
  119. while (ki.key) {
  120. DOH *key = ki.key;
  121. Node *class_node = ki.item;
  122. String *human_name = key;
  123. // Write out destructor function header
  124. Printf(s_wrappers, "/* NEW Destructor style */\nstatic ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key);
  125. // write out body
  126. if ((class_node != NOTCLASS)) {
  127. String *destructor = Getattr(class_node, "destructor");
  128. human_name = Getattr(class_node, "sym:name");
  129. if (!human_name)
  130. human_name = Getattr(class_node, "name");
  131. // Do we have a known destructor for this type?
  132. if (destructor) {
  133. Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key);
  134. } else {
  135. Printf(s_wrappers, " /* No destructor for class %s */\n", human_name);
  136. }
  137. } else {
  138. Printf(s_wrappers, " /* No destructor for simple type %s */\n", key);
  139. }
  140. // close function
  141. Printf(s_wrappers, "}\n");
  142. // declare le_swig_<mangled> to store php registration
  143. Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name);
  144. // register with php
  145. Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key);
  146. // store php type in class struct
  147. Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key);
  148. ki = Next(ki);
  149. }
  150. }
  151. class PHP:public Language {
  152. int php_version;
  153. public:
  154. PHP(int php_version_):php_version(php_version_) {
  155. }
  156. /* Test to see if a type corresponds to something wrapped with a shadow class. */
  157. String *is_shadow(SwigType *t) {
  158. String *r = 0;
  159. Node *n = classLookup(t);
  160. if (n) {
  161. r = Getattr(n, "php:proxy"); // Set by classDeclaration()
  162. if (!r) {
  163. r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name
  164. }
  165. }
  166. return r;
  167. }
  168. /* ------------------------------------------------------------
  169. * main()
  170. * ------------------------------------------------------------ */
  171. virtual void main(int argc, char *argv[]) {
  172. SWIG_library_directory("php");
  173. SWIG_config_cppext("cpp");
  174. for (int i = 1; i < argc; i++) {
  175. if (strcmp(argv[i], "-prefix") == 0) {
  176. if (argv[i + 1]) {
  177. prefix = NewString(argv[i + 1]);
  178. Swig_mark_arg(i);
  179. Swig_mark_arg(i + 1);
  180. i++;
  181. } else {
  182. Swig_arg_error();
  183. }
  184. } else if (strcmp(argv[i], "-cppext") == 0) {
  185. if (argv[i + 1]) {
  186. SWIG_config_cppext(argv[i + 1]);
  187. Swig_mark_arg(i);
  188. Swig_mark_arg(i + 1);
  189. i++;
  190. } else {
  191. Swig_arg_error();
  192. }
  193. } else if ((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) {
  194. shadow = 0;
  195. Swig_mark_arg(i);
  196. } else if (strcmp(argv[i], "-help") == 0) {
  197. fputs(usage, stdout);
  198. } else if (strcmp(argv[i], "-make") == 0 ||
  199. strcmp(argv[i], "-withc") == 0 ||
  200. strcmp(argv[i], "-withcxx") == 0) {
  201. Printf(stderr, "*** %s is no longer supported.\n", argv[i]);
  202. SWIG_exit(EXIT_FAILURE);
  203. } else if (strcmp(argv[i], "-phpfull") == 0 ||
  204. strcmp(argv[i], "-withlibs") == 0 ||
  205. strcmp(argv[i], "-withincs") == 0) {
  206. Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]);
  207. SWIG_exit(EXIT_FAILURE);
  208. } else if (strcmp(argv[i], "-dlname") == 0) {
  209. Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n");
  210. SWIG_exit(EXIT_FAILURE);
  211. }
  212. }
  213. Preprocessor_define("SWIGPHP 1", 0);
  214. Preprocessor_define("SWIGPHP5 1", 0);
  215. SWIG_typemap_lang("php4");
  216. SWIG_config_file("php.swg");
  217. allow_overloading();
  218. }
  219. /* ------------------------------------------------------------
  220. * top()
  221. * ------------------------------------------------------------ */
  222. virtual int top(Node *n) {
  223. String *filen;
  224. String *s_type;
  225. /* Initialize all of the output files */
  226. String *outfile = Getattr(n, "outfile");
  227. /* main output file */
  228. f_runtime = NewFile(outfile, "w");
  229. if (!f_runtime) {
  230. FileErrorDisplay(outfile);
  231. SWIG_exit(EXIT_FAILURE);
  232. }
  233. Swig_banner(f_runtime);
  234. /* sections of the output file */
  235. s_init = NewString("/* init section */\n");
  236. r_init = NewString("/* rinit section */\n");
  237. s_shutdown = NewString("/* shutdown section */\n");
  238. r_shutdown = NewString("/* rshutdown section */\n");
  239. s_header = NewString("/* header section */\n");
  240. s_wrappers = NewString("/* wrapper section */\n");
  241. s_type = NewStringEmpty();
  242. /* subsections of the init section */
  243. s_vinit = NewString("/* vinit subsection */\n");
  244. s_vdecl = NewString("/* vdecl subsection */\n");
  245. s_cinit = NewString("/* cinit subsection */\n");
  246. s_oinit = NewString("/* oinit subsection */\n");
  247. pragma_phpinfo = NewStringEmpty();
  248. s_phpclasses = NewString("/* PHP Proxy Classes */\n");
  249. /* Register file targets with the SWIG file handler */
  250. Swig_register_filebyname("runtime", f_runtime);
  251. Swig_register_filebyname("init", s_init);
  252. Swig_register_filebyname("rinit", r_init);
  253. Swig_register_filebyname("shutdown", s_shutdown);
  254. Swig_register_filebyname("rshutdown", r_shutdown);
  255. Swig_register_filebyname("header", s_header);
  256. Swig_register_filebyname("wrapper", s_wrappers);
  257. /* Set the module name */
  258. module = Copy(Getattr(n, "name"));
  259. cap_module = NewStringf("%(upper)s", module);
  260. if (!prefix)
  261. prefix = NewStringEmpty();
  262. /* PHP module file */
  263. filen = NewStringEmpty();
  264. Printv(filen, SWIG_output_directory(), module, ".php", NIL);
  265. phpfilename = NewString(filen);
  266. f_phpcode = NewFile(filen, "w");
  267. if (!f_phpcode) {
  268. FileErrorDisplay(filen);
  269. SWIG_exit(EXIT_FAILURE);
  270. }
  271. Printf(f_phpcode, "<?php\n\n");
  272. Swig_banner(f_phpcode);
  273. Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n");
  274. Printf(f_phpcode, "if (!extension_loaded(\"%s\")) {\n", module);
  275. Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n");
  276. Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module);
  277. Printf(f_phpcode, " } else {\n");
  278. Printf(f_phpcode, " // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.\n");
  279. Printf(f_phpcode, " if (PHP_SHLIB_SUFFIX === 'dylib') {\n");
  280. Printf(f_phpcode, " if (!dl('%s.so')) return;\n", module);
  281. Printf(f_phpcode, " } else {\n");
  282. Printf(f_phpcode, " if (!dl('%s.'.PHP_SHLIB_SUFFIX)) return;\n", module);
  283. Printf(f_phpcode, " }\n");
  284. Printf(f_phpcode, " }\n");
  285. Printf(f_phpcode, "}\n\n");
  286. /* sub-sections of the php file */
  287. pragma_code = NewStringEmpty();
  288. pragma_incl = NewStringEmpty();
  289. /* Initialize the rest of the module */
  290. Printf(s_oinit, "ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, %s_destroy_globals);\n", module, module, module);
  291. /* start the header section */
  292. Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module);
  293. Printf(s_header, "const char *error_msg;\n");
  294. Printf(s_header, "int error_code;\n");
  295. Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module);
  296. Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module);
  297. Printf(s_header, "#ifdef ZTS\n");
  298. Printf(s_header, "#define SWIG_ErrorMsg() TSRMG(%s_globals_id, zend_%s_globals *, error_msg )\n", module, module);
  299. Printf(s_header, "#define SWIG_ErrorCode() TSRMG(%s_globals_id, zend_%s_globals *, error_code )\n", module, module);
  300. Printf(s_header, "#else\n");
  301. Printf(s_header, "#define SWIG_ErrorMsg() (%s_globals.error_msg)\n", module);
  302. Printf(s_header, "#define SWIG_ErrorCode() (%s_globals.error_code)\n", module);
  303. Printf(s_header, "#endif\n\n");
  304. Printf(s_header, "static void %s_init_globals(zend_%s_globals *globals ) {\n", module, module);
  305. Printf(s_header, " globals->error_msg = default_error_msg;\n");
  306. Printf(s_header, " globals->error_code = default_error_code;\n");
  307. Printf(s_header, "}\n");
  308. Printf(s_header, "static void %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module);
  309. Printf(s_header, "\n");
  310. Printf(s_header, "static void SWIG_ResetError() {\n");
  311. Printf(s_header, " TSRMLS_FETCH();\n");
  312. Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n");
  313. Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n");
  314. Printf(s_header, "}\n");
  315. Printf(s_header, "#define SWIG_name \"%s\"\n", module);
  316. /* Printf(s_header,"#ifdef HAVE_CONFIG_H\n");
  317. Printf(s_header,"#include \"config.h\"\n");
  318. Printf(s_header,"#endif\n\n");
  319. */
  320. Printf(s_header, "#ifdef __cplusplus\n");
  321. Printf(s_header, "extern \"C\" {\n");
  322. Printf(s_header, "#endif\n");
  323. Printf(s_header, "#include \"php.h\"\n");
  324. Printf(s_header, "#include \"php_ini.h\"\n");
  325. Printf(s_header, "#include \"ext/standard/info.h\"\n");
  326. Printf(s_header, "#include \"php_%s.h\"\n", module);
  327. Printf(s_header, "#ifdef __cplusplus\n");
  328. Printf(s_header, "}\n");
  329. Printf(s_header, "#endif\n\n");
  330. /* Create the .h file too */
  331. filen = NewStringEmpty();
  332. Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL);
  333. f_h = NewFile(filen, "w");
  334. if (!f_h) {
  335. FileErrorDisplay(filen);
  336. SWIG_exit(EXIT_FAILURE);
  337. }
  338. Swig_banner(f_h);
  339. Printf(f_h, "\n\n");
  340. Printf(f_h, "#ifndef PHP_%s_H\n", cap_module);
  341. Printf(f_h, "#define PHP_%s_H\n\n", cap_module);
  342. Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module);
  343. Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module);
  344. Printf(f_h, "#ifdef PHP_WIN32\n");
  345. Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module);
  346. Printf(f_h, "#else\n");
  347. Printf(f_h, "# define PHP_%s_API\n", cap_module);
  348. Printf(f_h, "#endif\n\n");
  349. Printf(f_h, "#ifdef ZTS\n");
  350. Printf(f_h, "#include \"TSRM.h\"\n");
  351. Printf(f_h, "#endif\n\n");
  352. Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module);
  353. Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module);
  354. Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module);
  355. Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module);
  356. Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n\n", module);
  357. /* start the function entry section */
  358. s_entry = NewString("/* entry subsection */\n");
  359. /* holds all the per-class function entry sections */
  360. all_cs_entry = NewString("/* class entry subsection */\n");
  361. cs_entry = NULL;
  362. Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n");
  363. Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module);
  364. /* start the init section */
  365. Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n" "#if ZEND_MODULE_API_NO > 20010900\n" " STANDARD_MODULE_HEADER,\n" "#endif\n", NIL);
  366. Printf(s_init, " (char*)\"%s\",\n", module);
  367. Printf(s_init, " %s_functions,\n", module);
  368. Printf(s_init, " PHP_MINIT(%s),\n", module);
  369. Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module);
  370. Printf(s_init, " PHP_RINIT(%s),\n", module);
  371. Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module);
  372. Printf(s_init, " PHP_MINFO(%s),\n", module);
  373. Printf(s_init, "#if ZEND_MODULE_API_NO > 20010900\n");
  374. Printf(s_init, " NO_VERSION_YET,\n");
  375. Printf(s_init, "#endif\n");
  376. Printf(s_init, " STANDARD_MODULE_PROPERTIES\n");
  377. Printf(s_init, "};\n");
  378. Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module);
  379. Printf(s_init, "#ifdef __cplusplus\n");
  380. Printf(s_init, "extern \"C\" {\n");
  381. Printf(s_init, "#endif\n");
  382. // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE
  383. // in PHP5 has "extern "C" { ... }" around it so we can't do that.
  384. Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module);
  385. Printf(s_init, "#ifdef __cplusplus\n");
  386. Printf(s_init, "}\n");
  387. Printf(s_init, "#endif\n\n");
  388. /* We have to register the constants before they are (possibly) used
  389. * by the pointer typemaps. This all needs re-arranging really as
  390. * things are being called in the wrong order
  391. */
  392. Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module);
  393. /* Emit all of the code */
  394. Language::top(n);
  395. SwigPHP_emit_resource_registrations();
  396. // Printv(s_init,s_resourcetypes,NIL);
  397. /* We need this after all classes written out by ::top */
  398. Printf(s_oinit, "CG(active_class_entry) = NULL;\n");
  399. Printf(s_oinit, "/* end oinit subsection */\n");
  400. Printf(s_init, "%s\n", s_oinit);
  401. /* Constants generated during top call */
  402. Printf(s_cinit, "/* end cinit subsection */\n");
  403. Printf(s_init, "%s\n", s_cinit);
  404. Clear(s_cinit);
  405. Delete(s_cinit);
  406. Printf(s_init, " return SUCCESS;\n");
  407. Printf(s_init, "}\n\n");
  408. // Now do REQUEST init which holds any user specified %rinit, and also vinit
  409. Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module);
  410. Printf(s_init, "%s\n", r_init);
  411. /* finish our init section which will have been used by class wrappers */
  412. Printf(s_vinit, "/* end vinit subsection */\n");
  413. Printf(s_init, "%s\n", s_vinit);
  414. Clear(s_vinit);
  415. Delete(s_vinit);
  416. Printf(s_init, " return SUCCESS;\n");
  417. Printf(s_init, "}\n\n");
  418. Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
  419. "{\n",
  420. s_shutdown,
  421. "#ifdef ZTS\n"
  422. " ts_free_id(", module, "_globals_id);\n"
  423. "#endif\n"
  424. " return SUCCESS;\n"
  425. "}\n\n", NIL);
  426. Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
  427. Printf(s_init, "%s\n", r_shutdown);
  428. Printf(s_init, " return SUCCESS;\n");
  429. Printf(s_init, "}\n\n");
  430. Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module);
  431. Printf(s_init, "%s", pragma_phpinfo);
  432. Printf(s_init, "}\n");
  433. Printf(s_init, "/* end init section */\n");
  434. Printf(f_h, "#endif /* PHP_%s_H */\n", cap_module);
  435. Close(f_h);
  436. String *type_table = NewStringEmpty();
  437. SwigType_emit_type_table(f_runtime, type_table);
  438. Printf(s_header, "%s", type_table);
  439. Delete(type_table);
  440. /* Oh dear, more things being called in the wrong order. This whole
  441. * function really needs totally redoing.
  442. */
  443. Printf(s_header, "/* end header section */\n");
  444. Printf(s_wrappers, "/* end wrapper section */\n");
  445. Printf(s_vdecl, "/* end vdecl subsection */\n");
  446. Printv(f_runtime, s_header, s_vdecl, s_wrappers, NIL);
  447. Printv(f_runtime, all_cs_entry, "\n\n", s_entry, "{NULL, NULL, NULL}\n};\n\n", NIL);
  448. Printv(f_runtime, s_init, NIL);
  449. Delete(s_header);
  450. Delete(s_wrappers);
  451. Delete(s_init);
  452. Delete(s_vdecl);
  453. Delete(all_cs_entry);
  454. Delete(s_entry);
  455. Close(f_runtime);
  456. Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code);
  457. if (s_fakeoowrappers) {
  458. Printf(f_phpcode, "abstract class %s {", Len(prefix) ? prefix : module);
  459. Printf(f_phpcode, "%s", s_fakeoowrappers);
  460. Printf(f_phpcode, "}\n\n");
  461. Delete(s_fakeoowrappers);
  462. s_fakeoowrappers = NULL;
  463. }
  464. Printf(f_phpcode, "%s\n?>\n", s_phpclasses);
  465. Close(f_phpcode);
  466. return SWIG_OK;
  467. }
  468. /* Just need to append function names to function table to register with PHP. */
  469. void create_command(String *cname, String *iname) {
  470. // This is for the single main zend_function_entry record
  471. Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname);
  472. String * s = cs_entry;
  473. if (!s) s = s_entry;
  474. Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname);
  475. }
  476. /* ------------------------------------------------------------
  477. * dispatchFunction()
  478. * ------------------------------------------------------------ */
  479. void dispatchFunction(Node *n) {
  480. /* Last node in overloaded chain */
  481. int maxargs;
  482. String *tmp = NewStringEmpty();
  483. String *dispatch = Swig_overload_dispatch(n, "return %s(INTERNAL_FUNCTION_PARAM_PASSTHRU);", &maxargs);
  484. /* Generate a dispatch wrapper for all overloaded functions */
  485. Wrapper *f = NewWrapper();
  486. String *symname = Getattr(n, "sym:name");
  487. String *wname = Swig_name_wrapper(symname);
  488. create_command(symname, wname);
  489. Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
  490. Wrapper_add_local(f, "argc", "int argc");
  491. Printf(tmp, "zval **argv[%d]", maxargs);
  492. Wrapper_add_local(f, "argv", tmp);
  493. Printf(f->code, "argc = ZEND_NUM_ARGS();\n");
  494. Printf(f->code, "zend_get_parameters_array_ex(argc,argv);\n");
  495. Replaceall(dispatch, "$args", "self,args");
  496. Printv(f->code, dispatch, "\n", NIL);
  497. Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n");
  498. Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname);
  499. Printv(f->code, "zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg());\n", NIL);
  500. Printv(f->code, "}\n", NIL);
  501. Wrapper_print(f, s_wrappers);
  502. DelWrapper(f);
  503. Delete(dispatch);
  504. Delete(tmp);
  505. Delete(wname);
  506. }
  507. /* ------------------------------------------------------------
  508. * functionWrapper()
  509. * ------------------------------------------------------------ */
  510. /* Helper method for PHP::functionWrapper */
  511. bool is_class(SwigType *t) {
  512. Node *n = classLookup(t);
  513. if (n) {
  514. String *r = Getattr(n, "php:proxy"); // Set by classDeclaration()
  515. if (!r)
  516. r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name
  517. if (r)
  518. return true;
  519. }
  520. return false;
  521. }
  522. virtual int functionWrapper(Node *n) {
  523. String *name = GetChar(n, "name");
  524. String *iname = GetChar(n, "sym:name");
  525. SwigType *d = Getattr(n, "type");
  526. ParmList *l = Getattr(n, "parms");
  527. String *nodeType = Getattr(n, "nodeType");
  528. int newobject = GetFlag(n, "feature:new");
  529. Parm *p;
  530. int i;
  531. int numopt;
  532. String *tm;
  533. Wrapper *f;
  534. String *wname;
  535. int overloaded = 0;
  536. String *overname = 0;
  537. if (Cmp(nodeType, "destructor") == 0) {
  538. // We just generate the Zend List Destructor and let Zend manage the
  539. // reference counting. There's no explicit destructor, but the user can
  540. // just do `$obj = null;' to remove a reference to an object.
  541. return CreateZendListDestructor(n);
  542. }
  543. // Test for overloading;
  544. if (Getattr(n, "sym:overloaded")) {
  545. overloaded = 1;
  546. overname = Getattr(n, "sym:overname");
  547. } else {
  548. if (!addSymbol(iname, n))
  549. return SWIG_ERROR;
  550. }
  551. wname = Swig_name_wrapper(iname);
  552. if (overname) {
  553. Printf(wname, "%s", overname);
  554. }
  555. f = NewWrapper();
  556. numopt = 0;
  557. String *outarg = NewStringEmpty();
  558. String *cleanup = NewStringEmpty();
  559. // Not issued for overloaded functions or static member variables.
  560. if (!overloaded && wrapperType != staticmembervar) {
  561. create_command(iname, wname);
  562. }
  563. Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL);
  564. emit_parameter_variables(l, f);
  565. /* Attach standard typemaps */
  566. emit_attach_parmmaps(l, f);
  567. // wrap:parms is used by overload resolution.
  568. Setattr(n, "wrap:parms", l);
  569. int num_arguments = emit_num_arguments(l);
  570. int num_required = emit_num_required(l);
  571. numopt = num_arguments - num_required;
  572. if (num_arguments > 0) {
  573. String *args = NewStringf("zval **args[%d]", num_arguments);
  574. Wrapper_add_local(f, "args", args);
  575. Delete(args);
  576. args = NULL;
  577. }
  578. // This generated code may be called:
  579. // 1) as an object method, or
  580. // 2) as a class-method/function (without a "this_ptr")
  581. // Option (1) has "this_ptr" for "this", option (2) needs it as
  582. // first parameter
  583. // NOTE: possible we ignore this_ptr as a param for native constructor
  584. Printf(f->code, "SWIG_ResetError();\n");
  585. if (numopt > 0) { // membervariable wrappers do not have optional args
  586. Wrapper_add_local(f, "arg_count", "int arg_count");
  587. Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n");
  588. Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments);
  589. Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n");
  590. Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n");
  591. } else {
  592. if (num_arguments == 0) {
  593. Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n");
  594. } else {
  595. Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments);
  596. }
  597. Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n");
  598. }
  599. /* Now convert from php to C variables */
  600. // At this point, argcount if used is the number of deliberately passed args
  601. // not including this_ptr even if it is used.
  602. // It means error messages may be out by argbase with error
  603. // reports. We can either take argbase into account when raising
  604. // errors, or find a better way of dealing with _thisptr.
  605. // I would like, if objects are wrapped, to assume _thisptr is always
  606. // _this and not the first argument.
  607. // This may mean looking at Language::memberfunctionHandler
  608. for (i = 0, p = l; i < num_arguments; i++) {
  609. String *source;
  610. /* Skip ignored arguments */
  611. //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");}
  612. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  613. p = Getattr(p, "tmap:in:next");
  614. }
  615. SwigType *pt = Getattr(p, "type");
  616. source = NewStringf("args[%d]", i);
  617. String *ln = Getattr(p, "lname");
  618. /* Check if optional */
  619. if (i >= num_required) {
  620. Printf(f->code, "\tif(arg_count > %d) {\n", i);
  621. }
  622. if ((tm = Getattr(p, "tmap:in"))) {
  623. Replaceall(tm, "$source", source);
  624. Replaceall(tm, "$target", ln);
  625. Replaceall(tm, "$input", source);
  626. Setattr(p, "emit:input", source);
  627. Printf(f->code, "%s\n", tm);
  628. if (i == 0 && Getattr(p, "self")) {
  629. Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n");
  630. }
  631. p = Getattr(p, "tmap:in:next");
  632. if (i >= num_required) {
  633. Printf(f->code, "}\n");
  634. }
  635. continue;
  636. } else {
  637. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  638. }
  639. if (i >= num_required) {
  640. Printf(f->code, "\t}\n");
  641. }
  642. Delete(source);
  643. }
  644. /* Insert constraint checking code */
  645. for (p = l; p;) {
  646. if ((tm = Getattr(p, "tmap:check"))) {
  647. Replaceall(tm, "$target", Getattr(p, "lname"));
  648. Printv(f->code, tm, "\n", NIL);
  649. p = Getattr(p, "tmap:check:next");
  650. } else {
  651. p = nextSibling(p);
  652. }
  653. }
  654. /* Insert cleanup code */
  655. for (i = 0, p = l; p; i++) {
  656. if ((tm = Getattr(p, "tmap:freearg"))) {
  657. Replaceall(tm, "$source", Getattr(p, "lname"));
  658. Printv(cleanup, tm, "\n", NIL);
  659. p = Getattr(p, "tmap:freearg:next");
  660. } else {
  661. p = nextSibling(p);
  662. }
  663. }
  664. /* Insert argument output code */
  665. for (i = 0, p = l; p; i++) {
  666. if ((tm = Getattr(p, "tmap:argout"))) {
  667. Replaceall(tm, "$source", Getattr(p, "lname"));
  668. // Replaceall(tm,"$input",Getattr(p,"lname"));
  669. Replaceall(tm, "$target", "return_value");
  670. Replaceall(tm, "$result", "return_value");
  671. Replaceall(tm, "$arg", Getattr(p, "emit:input"));
  672. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  673. Printv(outarg, tm, "\n", NIL);
  674. p = Getattr(p, "tmap:argout:next");
  675. } else {
  676. p = nextSibling(p);
  677. }
  678. }
  679. Setattr(n, "wrap:name", wname);
  680. /* emit function call */
  681. String *actioncode = emit_action(n);
  682. if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
  683. Replaceall(tm, "$input", "result");
  684. Replaceall(tm, "$source", "result");
  685. Replaceall(tm, "$target", "return_value");
  686. Replaceall(tm, "$result", "return_value");
  687. Replaceall(tm, "$owner", newobject ? "1" : "0");
  688. Printf(f->code, "%s\n", tm);
  689. } else {
  690. 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);
  691. }
  692. emit_return_variable(n, d, f);
  693. if (outarg) {
  694. Printv(f->code, outarg, NIL);
  695. }
  696. if (cleanup) {
  697. Printv(f->code, cleanup, NIL);
  698. }
  699. /* Look to see if there is any newfree cleanup code */
  700. if (GetFlag(n, "feature:new")) {
  701. if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
  702. Printf(f->code, "%s\n", tm);
  703. Delete(tm);
  704. }
  705. }
  706. /* See if there is any return cleanup code */
  707. if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
  708. Printf(f->code, "%s\n", tm);
  709. Delete(tm);
  710. }
  711. Printf(f->code, "return;\n");
  712. /* Error handling code */
  713. Printf(f->code, "fail:\n");
  714. Printv(f->code, cleanup, NIL);
  715. Printv(f->code, "zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg());", NIL);
  716. Printf(f->code, "}\n");
  717. Replaceall(f->code, "$cleanup", cleanup);
  718. Replaceall(f->code, "$symname", iname);
  719. Wrapper_print(f, s_wrappers);
  720. if (overloaded && !Getattr(n, "sym:nextSibling")) {
  721. dispatchFunction(n);
  722. }
  723. Delete(wname);
  724. wname = NULL;
  725. if (!(shadow && php_version == 5)) {
  726. DelWrapper(f);
  727. return SWIG_OK;
  728. }
  729. // Handle getters and setters.
  730. if (wrapperType == membervar) {
  731. const char *p = Char(iname);
  732. if (strlen(p) > 4) {
  733. p += strlen(p) - 4;
  734. String *varname = Getattr(n, "membervariableHandler:sym:name");
  735. if (strcmp(p, "_get") == 0) {
  736. Setattr(shadow_get_vars, varname, iname);
  737. } else if (strcmp(p, "_set") == 0) {
  738. Setattr(shadow_set_vars, varname, iname);
  739. }
  740. }
  741. }
  742. // Only look at non-overloaded methods and the last entry in each overload
  743. // chain (we check the last so that wrap:parms and wrap:name have been set
  744. // for them all).
  745. if (overloaded && Getattr(n, "sym:nextSibling") != 0)
  746. return SWIG_OK;
  747. if (!s_oowrappers)
  748. s_oowrappers = NewStringEmpty();
  749. if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard) {
  750. bool handle_as_overload = false;
  751. String **arg_names;
  752. String **arg_values;
  753. // Method or static method or plain function.
  754. const char *methodname = 0;
  755. String *output = s_oowrappers;
  756. if (newobject) {
  757. class_has_ctor = true;
  758. methodname = "__construct";
  759. } else if (wrapperType == memberfn) {
  760. methodname = Char(Getattr(n, "memberfunctionHandler:sym:name"));
  761. } else if (wrapperType == staticmemberfn) {
  762. methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name"));
  763. } else { // wrapperType == standard
  764. methodname = Char(iname);
  765. if (!s_fakeoowrappers)
  766. s_fakeoowrappers = NewStringEmpty();
  767. output = s_fakeoowrappers;
  768. }
  769. bool really_overloaded = overloaded ? true : false;
  770. int min_num_of_arguments = emit_num_required(l);
  771. int max_num_of_arguments = emit_num_arguments(l);
  772. // For a function with default arguments, we end up with the fullest
  773. // parmlist in full_parmlist.
  774. ParmList *full_parmlist = l;
  775. Hash *ret_types = NewHash();
  776. Setattr(ret_types, d, d);
  777. if (overloaded) {
  778. // Look at all the overloaded versions of this method in turn to
  779. // decide if it's really an overloaded method, or just one where some
  780. // parameters have default values.
  781. Node *o = Getattr(n, "sym:overloaded");
  782. while (o) {
  783. if (o == n) {
  784. o = Getattr(o, "sym:nextSibling");
  785. continue;
  786. }
  787. SwigType *d2 = Getattr(o, "type");
  788. if (!d2) {
  789. assert(constructor);
  790. } else if (!Getattr(ret_types, d2)) {
  791. Setattr(ret_types, d2, d2);
  792. }
  793. ParmList *l2 = Getattr(o, "wrap:parms");
  794. int num_arguments = emit_num_arguments(l2);
  795. int num_required = emit_num_required(l2);
  796. if (num_required < min_num_of_arguments)
  797. min_num_of_arguments = num_required;
  798. if (num_arguments > max_num_of_arguments) {
  799. max_num_of_arguments = num_arguments;
  800. full_parmlist = l2;
  801. }
  802. o = Getattr(o, "sym:nextSibling");
  803. }
  804. o = Getattr(n, "sym:overloaded");
  805. while (o) {
  806. if (o == n) {
  807. o = Getattr(o, "sym:nextSibling");
  808. continue;
  809. }
  810. ParmList *l2 = Getattr(o, "wrap:parms");
  811. Parm *p = l, *p2 = l2;
  812. if (wrapperType == memberfn) {
  813. p = nextSibling(p);
  814. p2 = nextSibling(p2);
  815. }
  816. while (p && p2) {
  817. if (Cmp(Getattr(p, "type"), Getattr(p2, "type")) != 0)
  818. break;
  819. if (Cmp(Getattr(p, "name"), Getattr(p2, "name")) != 0)
  820. break;
  821. String *value = Getattr(p, "value");
  822. String *value2 = Getattr(p2, "value");
  823. if (value && !value2)
  824. break;
  825. if (!value && value2)
  826. break;
  827. if (value) {
  828. if (Cmp(value, value2) != 0)
  829. break;
  830. }
  831. p = nextSibling(p);
  832. p2 = nextSibling(p2);
  833. }
  834. if (p && p2)
  835. break;
  836. // One parameter list is a prefix of the other, so check that all
  837. // remaining parameters of the longer list are optional.
  838. if (p2)
  839. p = p2;
  840. while (p && Getattr(p, "value"))
  841. p = nextSibling(p);
  842. if (p)
  843. break;
  844. o = Getattr(o, "sym:nextSibling");
  845. }
  846. if (!o) {
  847. // This "overloaded method" is really just one with default args.
  848. really_overloaded = false;
  849. if (l != full_parmlist) {
  850. l = full_parmlist;
  851. if (wrapperType == memberfn)
  852. l = nextSibling(l);
  853. }
  854. }
  855. }
  856. if (wrapperType == memberfn) {
  857. // Allow for the "this" pointer.
  858. --min_num_of_arguments;
  859. --max_num_of_arguments;
  860. }
  861. arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *));
  862. if (!arg_names) {
  863. /* FIXME: How should this be handled? The rest of SWIG just seems
  864. * to not bother checking for malloc failing! */
  865. fprintf(stderr, "Malloc failed!\n");
  866. exit(1);
  867. }
  868. for (i = 0; i < max_num_of_arguments; ++i) {
  869. arg_names[i] = NULL;
  870. }
  871. arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *));
  872. if (!arg_values) {
  873. /* FIXME: How should this be handled? The rest of SWIG just seems
  874. * to not bother checking for malloc failing! */
  875. fprintf(stderr, "Malloc failed!\n");
  876. exit(1);
  877. }
  878. for (i = 0; i < max_num_of_arguments; ++i) {
  879. arg_values[i] = NULL;
  880. }
  881. Node *o;
  882. if (overloaded) {
  883. o = Getattr(n, "sym:overloaded");
  884. } else {
  885. o = n;
  886. }
  887. while (o) {
  888. int argno = 0;
  889. Parm *p = Getattr(o, "wrap:parms");
  890. if (wrapperType == memberfn)
  891. p = nextSibling(p);
  892. while (p) {
  893. if (GetInt(p, "tmap:in:numinputs") == 0) {
  894. p = nextSibling(p);
  895. continue;
  896. }
  897. assert(0 <= argno && argno < max_num_of_arguments);
  898. String *&pname = arg_names[argno];
  899. const char *pname_cstr = GetChar(p, "name");
  900. if (!pname_cstr) {
  901. // Unnamed parameter, e.g. int foo(int);
  902. } else if (pname == NULL) {
  903. pname = NewString(pname_cstr);
  904. } else {
  905. size_t len = strlen(pname_cstr);
  906. size_t spc = 0;
  907. size_t len_pname = strlen(Char(pname));
  908. while (spc + len <= len_pname) {
  909. if (strncmp(pname_cstr, Char(pname) + spc, len) == 0) {
  910. char ch = ((char *) Char(pname))[spc + len];
  911. if (ch == '\0' || ch == ' ') {
  912. // Already have this pname_cstr.
  913. pname_cstr = NULL;
  914. break;
  915. }
  916. }
  917. char *p = strchr(Char(pname) + spc, ' ');
  918. if (!p)
  919. break;
  920. spc = (p + 4) - Char(pname);
  921. }
  922. if (pname_cstr) {
  923. Printf(pname, " or_%s", pname_cstr);
  924. }
  925. }
  926. String *value = NewString(Getattr(p, "value"));
  927. if (Len(value)) {
  928. /* Check that value is a valid constant in PHP (and adjust it if
  929. * necessary, or replace it with "?" if it's just not valid). */
  930. SwigType *type = Getattr(p, "type");
  931. switch (SwigType_type(type)) {
  932. case T_BOOL: {
  933. if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0)
  934. break;
  935. char *p;
  936. errno = 0;
  937. int n = strtol(Char(value), &p, 0);
  938. Clear(value);
  939. if (errno || *p) {
  940. Append(value, "?");
  941. } else if (n) {
  942. Append(value, "true");
  943. } else {
  944. Append(value, "false");
  945. }
  946. break;
  947. }
  948. case T_CHAR:
  949. case T_SCHAR:
  950. case T_SHORT:
  951. case T_INT:
  952. case T_LONG: {
  953. char *p;
  954. errno = 0;
  955. (void) strtol(Char(value), &p, 0);
  956. if (errno || *p) {
  957. Clear(value);
  958. Append(value, "?");
  959. }
  960. break;
  961. }
  962. case T_UCHAR:
  963. case T_USHORT:
  964. case T_UINT:
  965. case T_ULONG: {
  966. char *p;
  967. errno = 0;
  968. (void) strtoul(Char(value), &p, 0);
  969. if (errno || *p) {
  970. Clear(value);
  971. Append(value, "?");
  972. }
  973. break;
  974. }
  975. case T_FLOAT:
  976. case T_DOUBLE:{
  977. char *p;
  978. errno = 0;
  979. /* FIXME: strtod is locale dependent... */
  980. double val = strtod(Char(value), &p);
  981. if (errno || *p) {
  982. Clear(value);
  983. Append(value, "?");
  984. } else if (strchr(Char(value), '.') == NULL) {
  985. // Ensure value is a double constant, not an integer one.
  986. Append(value, ".0");
  987. double val2 = strtod(Char(value), &p);
  988. if (errno || *p || val != val2) {
  989. Clear(value);
  990. Append(value, "?");
  991. }
  992. }
  993. break;
  994. }
  995. case T_REFERENCE:
  996. case T_USER:
  997. case T_ARRAY:
  998. Clear(value);
  999. Append(value, "?");
  1000. break;
  1001. case T_STRING:
  1002. if (Len(value) < 2) {
  1003. // How can a string (including "" be less than 2 characters?)
  1004. Clear(value);
  1005. Append(value, "?");
  1006. } else {
  1007. const char *v = Char(value);
  1008. if (v[0] != '"' || v[Len(value) - 1] != '"') {
  1009. Clear(value);
  1010. Append(value, "?");
  1011. }
  1012. // Strings containing "$" require special handling, but we do
  1013. // that later.
  1014. }
  1015. break;
  1016. case T_VOID:
  1017. assert(false);
  1018. break;
  1019. case T_POINTER: {
  1020. const char *v = Char(value);
  1021. if (v[0] == '(') {
  1022. // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc.
  1023. v += strcspn(v + 1, "*()") + 1;
  1024. if (*v == '*') {
  1025. do {
  1026. v++;
  1027. v += strspn(v, " \t");
  1028. } while (*v == '*');
  1029. if (*v++ == ')') {
  1030. v += strspn(v, " \t");
  1031. String * old = value;
  1032. value = NewString(v);
  1033. Delete(old);
  1034. }
  1035. }
  1036. }
  1037. if (Strcmp(value, "NULL") == 0 ||
  1038. Strcmp(value, "0") == 0 ||
  1039. Strcmp(value, "0L") == 0) {
  1040. Clear(value);
  1041. Append(value, "null");
  1042. } else {
  1043. Clear(value);
  1044. Append(value, "?");
  1045. }
  1046. break;
  1047. }
  1048. }
  1049. if (!arg_values[argno]) {
  1050. arg_values[argno] = value;
  1051. value = NULL;
  1052. } else if (Cmp(arg_values[argno], value) != 0) {
  1053. // If a parameter has two different default values in
  1054. // different overloaded forms of the function, we can't
  1055. // set its default in PHP. Flag this by setting its
  1056. // default to `?'.
  1057. Delete(arg_values[argno]);
  1058. arg_values[argno] = NewString("?");
  1059. }
  1060. } else if (arg_values[argno]) {
  1061. // This argument already has a default value in another overloaded
  1062. // form, but doesn't in this form. So don't try to do anything
  1063. // clever, just let the C wrappers resolve the overload and set the
  1064. // default values.
  1065. //
  1066. // This handling is safe, but I'm wondering if it may be overly
  1067. // conservative (FIXME) in some cases. It seems it's only bad when
  1068. // there's an overloaded form with the appropriate number of
  1069. // parameters which doesn't want the default value, but I need to
  1070. // think about this more.
  1071. Delete(arg_values[argno]);
  1072. arg_values[argno] = NewString("?");
  1073. }
  1074. Delete(value);
  1075. p = nextSibling(p);
  1076. ++argno;
  1077. }
  1078. if (!really_overloaded)
  1079. break;
  1080. o = Getattr(o, "sym:nextSibling");
  1081. }
  1082. /* Clean up any parameters which haven't yet got names, or whose
  1083. * names clash. */
  1084. Hash *seen = NewHash();
  1085. /* We need $this to refer to the current class, so can't allow it
  1086. * to be used as a parameter. */
  1087. Setattr(seen, "this", seen);
  1088. /* We use $r to store the return value, so disallow that as a parameter
  1089. * name in case the user uses the "call-time pass-by-reference" feature
  1090. * (it's deprecated and off by default in PHP5, but we want to be
  1091. * maximally portable).
  1092. */
  1093. Setattr(seen, "r", seen);
  1094. for (int argno = 0; argno < max_num_of_arguments; ++argno) {
  1095. String *&pname = arg_names[argno];
  1096. if (pname) {
  1097. Replaceall(pname, " ", "_");
  1098. } else {
  1099. /* We get here if the SWIG .i file has "int foo(int);" */
  1100. pname = NewStringEmpty();
  1101. Printf(pname, "arg%d", argno + 1);
  1102. }
  1103. // Check if we've already used this parameter name.
  1104. while (Getattr(seen, pname)) {
  1105. // Append "_" to clashing names until they stop clashing...
  1106. Printf(pname, "_");
  1107. }
  1108. Setattr(seen, Char(pname), seen);
  1109. if (arg_values[argno] && Cmp(arg_values[argno], "?") == 0) {
  1110. handle_as_overload = true;
  1111. }
  1112. }
  1113. Delete(seen);
  1114. seen = NULL;
  1115. String *invoke = NewStringEmpty();
  1116. String *prepare = NewStringEmpty();
  1117. String *args = NewStringEmpty();
  1118. if (!handle_as_overload && !(really_overloaded && max_num_of_arguments > min_num_of_arguments)) {
  1119. Printf(invoke, "%s(", iname);
  1120. if (wrapperType == memberfn) {
  1121. Printf(invoke, "$this->%s", SWIG_PTR);
  1122. }
  1123. for (int i = 0; i < max_num_of_arguments; ++i) {
  1124. if (i)
  1125. Printf(args, ",");
  1126. if (i || wrapperType == memberfn)
  1127. Printf(invoke, ",");
  1128. String *value = arg_values[i];
  1129. if (value) {
  1130. const char *v = Char(value);
  1131. if (v[0] == '"') {
  1132. /* In a PHP double quoted string, $ needs to be escaped as \$. */
  1133. Replaceall(value, "$", "\\$");
  1134. }
  1135. Printf(args, "$%s=%s", arg_names[i], value);
  1136. } else {
  1137. Printf(args, "$%s", arg_names[i]);
  1138. }
  1139. Printf(invoke, "$%s", arg_names[i]);
  1140. }
  1141. Printf(invoke, ")");
  1142. } else {
  1143. int i;
  1144. for (i = 0; i < min_num_of_arguments; ++i) {
  1145. if (i)
  1146. Printf(args, ",");
  1147. Printf(args, "$%s", arg_names[i]);
  1148. }
  1149. String *invoke_args = NewStringEmpty();
  1150. if (wrapperType == memberfn) {
  1151. Printf(invoke_args, "$this->%s", SWIG_PTR);
  1152. if (min_num_of_arguments > 0)
  1153. Printf(invoke_args, ",");
  1154. }
  1155. Printf(invoke_args, "%s", args);
  1156. bool had_a_case = false;
  1157. int last_handled_i = i - 1;
  1158. for (; i < max_num_of_arguments; ++i) {
  1159. if (i)
  1160. Printf(args, ",");
  1161. const char *value = Char(arg_values[i]);
  1162. // FIXME: (really_overloaded && handle_as_overload) is perhaps a
  1163. // little conservative, but it doesn't hit any cases that it
  1164. // shouldn't for Xapian at least (and we need it to handle
  1165. // "Enquire::get_mset()" correctly).
  1166. bool non_php_default = ((really_overloaded && handle_as_overload) ||
  1167. !value || strcmp(value, "?") == 0);
  1168. if (non_php_default)
  1169. value = "null";
  1170. Printf(args, "$%s=%s", arg_names[i], value);
  1171. if (non_php_default) {
  1172. if (!had_a_case) {
  1173. Printf(prepare, "\t\tswitch (func_num_args()) {\n");
  1174. had_a_case = true;
  1175. }
  1176. Printf(prepare, "\t\t");
  1177. while (last_handled_i < i) {
  1178. Printf(prepare, "case %d: ", ++last_handled_i);
  1179. }
  1180. if (Cmp(d, "void") != 0)
  1181. Printf(prepare, "$r=");
  1182. Printf(prepare, "%s(%s); break;\n", iname, invoke_args);
  1183. }
  1184. if (i || wrapperType == memberfn)
  1185. Printf(invoke_args, ",");
  1186. Printf(invoke_args, "$%s", arg_names[i]);
  1187. }
  1188. Printf(prepare, "\t\t");
  1189. if (had_a_case)
  1190. Printf(prepare, "default: ");
  1191. if (Cmp(d, "void") != 0)
  1192. Printf(prepare, "$r=");
  1193. Printf(prepare, "%s(%s);\n", iname, invoke_args);
  1194. if (had_a_case)
  1195. Printf(prepare, "\t\t}\n");
  1196. Delete(invoke_args);
  1197. Printf(invoke, "$r");
  1198. }
  1199. Printf(output, "\n");
  1200. // If it's a member function or a class constructor...
  1201. if (wrapperType == memberfn || (newobject && current_class)) {
  1202. Printf(output, "\tfunction %s(%s) {\n", methodname, args);
  1203. // We don't need this code if the wrapped class has a copy ctor
  1204. // since the flat function new_CLASSNAME will handle it for us.
  1205. if (newobject && !Getattr(current_class, "allocate:copy_constructor")) {
  1206. SwigType *t = Getattr(current_class, "classtype");
  1207. String *mangled_type = SwigType_manglestr(SwigType_ltype(t));
  1208. Printf(s_oowrappers, "\t\tif (is_resource($%s) && get_resource_type($%s) == \"_p%s\") {\n", arg_names[0], arg_names[0], mangled_type);
  1209. Printf(s_oowrappers, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg_names[0]);
  1210. Printf(s_oowrappers, "\t\t\treturn;\n");
  1211. Printf(s_oowrappers, "\t\t}\n");
  1212. }
  1213. } else {
  1214. Printf(output, "\tstatic function %s(%s) {\n", methodname, args);
  1215. }
  1216. Delete(args);
  1217. args = NULL;
  1218. for (int i = 0; i < max_num_of_arguments; ++i) {
  1219. Delete(arg_names[i]);
  1220. }
  1221. free(arg_names);
  1222. arg_names = NULL;
  1223. Printf(output, "%s", prepare);
  1224. if (newobject) {
  1225. Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke);
  1226. } else if (Cmp(d, "void") == 0) {
  1227. if (Cmp(invoke, "$r") != 0)
  1228. Printf(output, "\t\t%s;\n", invoke);
  1229. } else if (is_class(d)) {
  1230. if (Cmp(invoke, "$r") != 0)
  1231. Printf(output, "\t\t$r=%s;\n", invoke);
  1232. if (Len(ret_types) == 1) {
  1233. Printf(output, "\t\treturn is_resource($r) ? new %s%s($r) : $r;\n", prefix, Getattr(classLookup(d), "sym:name"));
  1234. } else {
  1235. Printf(output, "\t\tif (!is_resource($r)) return $r;\n");
  1236. Printf(output, "\t\tswitch (get_resource_type($r)) {\n");
  1237. Iterator i = First(ret_types);
  1238. while (i.item) {
  1239. SwigType *ret_type = i.item;
  1240. i = Next(i);
  1241. Printf(output, "\t\t");
  1242. String *mangled = NewString("_p");
  1243. Printf(mangled, "%s", SwigType_manglestr(ret_type));
  1244. Node *class_node = Getattr(zend_types, mangled);
  1245. if (!class_node) {
  1246. /* This is needed when we're returning a pointer to a type
  1247. * rather than returning the type by value or reference. */
  1248. class_node = current_class;
  1249. Delete(mangled);
  1250. mangled = NewString(SwigType_manglestr(ret_type));
  1251. class_node = Getattr(zend_types, mangled);
  1252. }
  1253. if (i.item) {
  1254. Printf(output, "case \"%s\": ", mangled);
  1255. } else {
  1256. Printf(output, "default: ");
  1257. }
  1258. const char *classname = GetChar(class_node, "sym:name");
  1259. if (!classname)
  1260. classname = GetChar(class_node, "name");
  1261. if (classname)
  1262. Printf(output, "return new %s%s($r);\n", prefix, classname);
  1263. else
  1264. Printf(output, "return $r;\n");
  1265. Delete(mangled);
  1266. }
  1267. Printf(output, "\t\t}\n");
  1268. }
  1269. } else {
  1270. Printf(output, "\t\treturn %s;\n", invoke);
  1271. }
  1272. Printf(output, "\t}\n");
  1273. Delete(prepare);
  1274. Delete(invoke);
  1275. free(arg_values);
  1276. }
  1277. DelWrapper(f);
  1278. return SWIG_OK;
  1279. }
  1280. /* ------------------------------------------------------------
  1281. * globalvariableHandler()
  1282. * ------------------------------------------------------------ */
  1283. virtual int globalvariableHandler(Node *n) {
  1284. char *name = GetChar(n, "name");
  1285. char *iname = GetChar(n, "sym:name");
  1286. SwigType *t = Getattr(n, "type");
  1287. String *tm;
  1288. /* First do the wrappers such as name_set(), name_get()
  1289. * as provided by the baseclass's implementation of variableWrapper
  1290. */
  1291. if (Language::globalvariableHandler(n) == SWIG_NOWRAP) {
  1292. return SWIG_NOWRAP;
  1293. }
  1294. if (!addSymbol(iname, n))
  1295. return SWIG_ERROR;
  1296. SwigType_remember(t);
  1297. /* First link C variables to PHP */
  1298. tm = Swig_typemap_lookup("varinit", n, name, 0);
  1299. if (tm) {
  1300. Replaceall(tm, "$target", name);
  1301. Printf(s_vinit, "%s\n", tm);
  1302. } else {
  1303. Printf(stderr, "%s: Line %d, Unable to link with type %s\n", input_file, line_number, SwigType_str(t, 0));
  1304. }
  1305. /* Now generate PHP -> C sync blocks */
  1306. /*
  1307. tm = Swig_typemap_lookup("varin", n, name, 0);
  1308. if(tm) {
  1309. Replaceall(tm, "$symname", iname);
  1310. Printf(f_c->code, "%s\n", tm);
  1311. } else {
  1312. Printf(stderr,"%s: Line %d, Unable to link with type %s\n",
  1313. input_file, line_number, SwigType_str(t, 0));
  1314. }
  1315. */
  1316. /* Now generate C -> PHP sync blocks */
  1317. /*
  1318. if(!GetFlag(n,"feature:immutable")) {
  1319. tm = Swig_typemap_lookup("varout", n, name, 0);
  1320. if(tm) {
  1321. Replaceall(tm, "$symname", iname);
  1322. Printf(f_php->code, "%s\n", tm);
  1323. } else {
  1324. Printf(stderr,"%s: Line %d, Unable to link with type %s\n",
  1325. input_file, line_number, SwigType_str(t, 0));
  1326. }
  1327. }
  1328. */
  1329. return SWIG_OK;
  1330. }
  1331. /* ------------------------------------------------------------
  1332. * constantWrapper()
  1333. * ------------------------------------------------------------ */
  1334. virtual int constantWrapper(Node *n) {
  1335. String *name = GetChar(n, "name");
  1336. String *iname = GetChar(n, "sym:name");
  1337. SwigType *type = Getattr(n, "type");
  1338. String *rawval = Getattr(n, "rawval");
  1339. String *value = rawval ? rawval : Getattr(n, "value");
  1340. String *tm;
  1341. if (!addSymbol(iname, n))
  1342. return SWIG_ERROR;
  1343. SwigType_remember(type);
  1344. if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) {
  1345. Replaceall(tm, "$source", value);
  1346. Replaceall(tm, "$target", name);
  1347. Replaceall(tm, "$value", value);
  1348. Printf(s_cinit, "%s\n", tm);
  1349. }
  1350. if (shadow && php_version == 5) {
  1351. String *enumvalue = GetChar(n, "enumvalue");
  1352. String *set_to = iname;
  1353. if (!enumvalue) {
  1354. enumvalue = GetChar(n, "enumvalueex");
  1355. }
  1356. if (enumvalue) {
  1357. // Check for a simple constant expression which is valid in PHP.
  1358. // If we find one, initialise the const member with it; otherwise
  1359. // we initialise it using the C/C++ wrapped constant.
  1360. const char *p;
  1361. for (p = Char(enumvalue); *p; ++p) {
  1362. if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) {
  1363. // FIXME: enhance to handle `<previous_enum> + 1' which is what
  1364. // we get for enums that don't have an explicit value set.
  1365. break;
  1366. }
  1367. }
  1368. if (!*p) set_to = enumvalue;
  1369. }
  1370. if (wrapping_member_constant) {
  1371. if (!s_oowrappers)
  1372. s_oowrappers = NewStringEmpty();
  1373. Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant,

Large files files are truncated, but you can click here to view the full file