PageRenderTime 33ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/closed/gsoc2009-vmiklos/Source/Modules/php.cxx

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