PageRenderTime 64ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/rel-1-3-30rc1-afterbeautify/SWIG/Source/Modules/php4.cxx

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