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

/branches/yziquel-ocaml/Source/Modules/php.cxx

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

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