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 11/* FIXME: PHP5 OO wrapping TODO list: 12 * 13 * Medium term: 14 * 15 * Handle default parameters on overloaded methods in PHP where possible. 16 * (Mostly done - just need to handle cases of overloaded methods with 17 * default parameters...) 18 * This is an optimisation - we could handle this case using a PHP 19 * default value, but currently we treat it as we would for a default 20 * value which is a compound C++ expression (i.e. as if we had a 21 * method with two overloaded forms instead of a single method with 22 * a default parameter value). 23 * 24 * Long term: 25 * 26 * Sort out locale-dependent behaviour of strtod() - it's harmless unless 27 * SWIG ever sets the locale and DOH/base.c calls atof, so we're probably 28 * OK currently at least. 29 */ 30 31/* 32 * TODO: Replace remaining stderr messages with Swig_error or Swig_warning 33 * (may need to add more WARN_PHP_xxx codes...) 34 */ 35 36char cvsroot_php_cxx[] = "$Id: php.cxx 11637 2009-08-18 16:23:23Z vmiklos $"; 37 38#include "swigmod.h" 39 40#include <ctype.h> 41#include <errno.h> 42 43static const char *usage = (char *) "\ 44PHP Options (available with -php)\n\ 45 -cppext - cpp file extension (default to .cpp)\n\ 46 -noproxy - Don't generate proxy classes.\n\ 47 -prefix <prefix> - Prepend <prefix> to all class names in PHP wrappers\n\ 48\n"; 49 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 58/* This is the name of the hash where the variables existing only in PHP 59 * classes are stored. 60 */ 61#define SWIG_DATA "_pData" 62 63static int constructors = 0; 64static String *NOTCLASS = NewString("Not a class"); 65static Node *classnode = 0; 66static String *module = 0; 67static String *cap_module = 0; 68static String *prefix = 0; 69 70static String *shadow_classname = 0; 71 72static File *f_begin = 0; 73static File *f_runtime = 0; 74static File *f_runtime_h = 0; 75static File *f_h = 0; 76static File *f_phpcode = 0; 77static File *f_directors = 0; 78static File *f_directors_h = 0; 79static String *phpfilename = 0; 80 81static String *s_header; 82static String *s_wrappers; 83static String *s_init; 84static String *r_init; // RINIT user code 85static String *s_shutdown; // MSHUTDOWN user code 86static String *r_shutdown; // RSHUTDOWN user code 87static String *s_vinit; // varinit initialization code. 88static String *s_vdecl; 89static String *s_cinit; // consttab initialization code. 90static String *s_oinit; 91static String *s_entry; 92static String *cs_entry; 93static String *all_cs_entry; 94static String *pragma_incl; 95static String *pragma_code; 96static String *pragma_phpinfo; 97static String *s_oowrappers; 98static String *s_fakeoowrappers; 99static String *s_phpclasses; 100 101/* Variables for using PHP classes */ 102static Node *current_class = 0; 103 104static Hash *shadow_get_vars; 105static Hash *shadow_set_vars; 106static Hash *zend_types = 0; 107 108static int shadow = 1; 109 110static bool class_has_ctor = false; 111static String *wrapping_member_constant = NULL; 112 113// These static variables are used to pass some state from Handlers into functionWrapper 114static enum { 115 standard = 0, 116 memberfn, 117 staticmemberfn, 118 membervar, 119 staticmembervar, 120 constructor, 121 directorconstructor 122} wrapperType = standard; 123 124extern "C" { 125 static void (*r_prevtracefunc) (SwigType *t, String *mangled, String *clientdata) = 0; 126} 127 128static void SwigPHP_emit_resource_registrations() { 129 Iterator ki; 130 131 if (!zend_types) 132 return; 133 134 ki = First(zend_types); 135 if (ki.key) 136 Printf(s_oinit, "\n/* Register resource destructors for pointer types */\n"); 137 while (ki.key) { 138 DOH *key = ki.key; 139 Node *class_node = ki.item; 140 String *human_name = key; 141 142 // Write out destructor function header 143 Printf(s_wrappers, "static ZEND_RSRC_DTOR_FUNC(_wrap_destroy%s) {\n", key); 144 145 // write out body 146 if (class_node != NOTCLASS) { 147 String *destructor = Getattr(class_node, "destructor"); 148 human_name = Getattr(class_node, "sym:name"); 149 if (!human_name) 150 human_name = Getattr(class_node, "name"); 151 // Do we have a known destructor for this type? 152 if (destructor) { 153 Printf(s_wrappers, " %s(rsrc, SWIGTYPE%s->name TSRMLS_CC);\n", destructor, key); 154 } else { 155 Printf(s_wrappers, " /* No destructor for class %s */\n", human_name); 156 Printf(s_wrappers, " efree(rsrc->ptr);\n"); 157 } 158 } else { 159 Printf(s_wrappers, " /* No destructor for simple type %s */\n", key); 160 Printf(s_wrappers, " efree(rsrc->ptr);\n"); 161 } 162 163 // close function 164 Printf(s_wrappers, "}\n"); 165 166 // declare le_swig_<mangled> to store php registration 167 Printf(s_vdecl, "static int le_swig_%s=0; /* handle for %s */\n", key, human_name); 168 169 // register with php 170 Printf(s_oinit, "le_swig_%s=zend_register_list_destructors_ex" 171 "(_wrap_destroy%s,NULL,(char *)(SWIGTYPE%s->name),module_number);\n", key, key, key); 172 173 // store php type in class struct 174 Printf(s_oinit, "SWIG_TypeClientData(SWIGTYPE%s,&le_swig_%s);\n", key, key); 175 176 ki = Next(ki); 177 } 178} 179 180class PHP : public Language { 181public: 182 PHP() { 183 director_language = 1; 184 } 185 186 /* ------------------------------------------------------------ 187 * main() 188 * ------------------------------------------------------------ */ 189 190 virtual void main(int argc, char *argv[]) { 191 SWIG_library_directory("php"); 192 SWIG_config_cppext("cpp"); 193 194 for (int i = 1; i < argc; i++) { 195 if (strcmp(argv[i], "-prefix") == 0) { 196 if (argv[i + 1]) { 197 prefix = NewString(argv[i + 1]); 198 Swig_mark_arg(i); 199 Swig_mark_arg(i + 1); 200 i++; 201 } else { 202 Swig_arg_error(); 203 } 204 } else if (strcmp(argv[i], "-cppext") == 0) { 205 if (argv[i + 1]) { 206 SWIG_config_cppext(argv[i + 1]); 207 Swig_mark_arg(i); 208 Swig_mark_arg(i + 1); 209 i++; 210 } else { 211 Swig_arg_error(); 212 } 213 } else if ((strcmp(argv[i], "-noshadow") == 0) || (strcmp(argv[i], "-noproxy") == 0)) { 214 shadow = 0; 215 Swig_mark_arg(i); 216 } else if (strcmp(argv[i], "-help") == 0) { 217 fputs(usage, stdout); 218 } else if (strcmp(argv[i], "-make") == 0 || 219 strcmp(argv[i], "-withc") == 0 || 220 strcmp(argv[i], "-withcxx") == 0) { 221 Printf(stderr, "*** %s is no longer supported.\n", argv[i]); 222 SWIG_exit(EXIT_FAILURE); 223 } else if (strcmp(argv[i], "-phpfull") == 0 || 224 strcmp(argv[i], "-withlibs") == 0 || 225 strcmp(argv[i], "-withincs") == 0) { 226 Printf(stderr, "*** %s is no longer supported.\n*** We recommend building as a dynamically loadable module.\n", argv[i]); 227 SWIG_exit(EXIT_FAILURE); 228 } else if (strcmp(argv[i], "-dlname") == 0) { 229 Printf(stderr, "*** -dlname is no longer supported.\n*** If you want to change the module name, use -module instead.\n"); 230 SWIG_exit(EXIT_FAILURE); 231 } 232 } 233 234 Preprocessor_define("SWIGPHP 1", 0); 235 // SWIGPHP5 is deprecated, and no longer documented. 236 Preprocessor_define("SWIGPHP5 1", 0); 237 SWIG_typemap_lang("php"); 238 SWIG_config_file("php.swg"); 239 allow_overloading(); 240 } 241 242 /* ------------------------------------------------------------ 243 * top() 244 * ------------------------------------------------------------ */ 245 246 virtual int top(Node *n) { 247 248 String *filen; 249 String *s_type; 250 251 /* Check if directors are enabled for this module. */ 252 Node *mod = Getattr(n, "module"); 253 if (mod) { 254 Node *options = Getattr(mod, "options"); 255 if (options && Getattr(options, "directors")) { 256 allow_directors(); 257 } 258 } 259 260 /* Set comparison with null for ConstructorToFunction */ 261 setSubclassInstanceCheck(NewString("$arg->type != IS_NULL")); 262 263 /* Initialize all of the output files */ 264 String *outfile = Getattr(n, "outfile"); 265 String *outfile_h = Getattr(n, "outfile_h"); 266 267 /* main output file */ 268 f_begin = NewFile(outfile, "w", SWIG_output_files()); 269 if (!f_begin) { 270 FileErrorDisplay(outfile); 271 SWIG_exit(EXIT_FAILURE); 272 } 273 f_runtime = NewStringEmpty(); 274 275 /* sections of the output file */ 276 s_init = NewString("/* init section */\n"); 277 r_init = NewString("/* rinit section */\n"); 278 s_shutdown = NewString("/* shutdown section */\n"); 279 r_shutdown = NewString("/* rshutdown section */\n"); 280 s_header = NewString("/* header section */\n"); 281 s_wrappers = NewString("/* wrapper section */\n"); 282 s_type = NewStringEmpty(); 283 /* subsections of the init section */ 284 s_vinit = NewString("/* vinit subsection */\n"); 285 s_vdecl = NewString("/* vdecl subsection */\n"); 286 s_cinit = NewString("/* cinit subsection */\n"); 287 s_oinit = NewString("/* oinit subsection */\n"); 288 pragma_phpinfo = NewStringEmpty(); 289 s_phpclasses = NewString("/* PHP Proxy Classes */\n"); 290 f_directors_h = NewStringEmpty(); 291 f_directors = NewStringEmpty(); 292 293 if (directorsEnabled()) { 294 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); 295 if (!f_runtime_h) { 296 FileErrorDisplay(outfile_h); 297 SWIG_exit(EXIT_FAILURE); 298 } 299 } 300 301 /* Register file targets with the SWIG file handler */ 302 Swig_register_filebyname("begin", f_begin); 303 Swig_register_filebyname("runtime", f_runtime); 304 Swig_register_filebyname("init", s_init); 305 Swig_register_filebyname("rinit", r_init); 306 Swig_register_filebyname("shutdown", s_shutdown); 307 Swig_register_filebyname("rshutdown", r_shutdown); 308 Swig_register_filebyname("header", s_header); 309 Swig_register_filebyname("wrapper", s_wrappers); 310 Swig_register_filebyname("director", f_directors); 311 Swig_register_filebyname("director_h", f_directors_h); 312 313 Swig_banner(f_begin); 314 315 Printf(f_runtime, "\n"); 316 Printf(f_runtime, "#define SWIGPHP\n"); 317 Printf(f_runtime, "\n"); 318 319 if (directorsEnabled()) { 320 Printf(f_runtime, "#define SWIG_DIRECTORS\n"); 321 } 322 323 /* Set the module name */ 324 module = Copy(Getattr(n, "name")); 325 cap_module = NewStringf("%(upper)s", module); 326 if (!prefix) 327 prefix = NewStringEmpty(); 328 329 if (directorsEnabled()) { 330 Swig_banner(f_directors_h); 331 Printf(f_directors_h, "\n"); 332 Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", cap_module); 333 Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", cap_module); 334 335 Printf(f_directors, "\n#include \"%s\"\n\n", Swig_file_filename(outfile_h)); 336 } 337 338 /* PHP module file */ 339 filen = NewStringEmpty(); 340 Printv(filen, SWIG_output_directory(), module, ".php", NIL); 341 phpfilename = NewString(filen); 342 343 f_phpcode = NewFile(filen, "w", SWIG_output_files()); 344 if (!f_phpcode) { 345 FileErrorDisplay(filen); 346 SWIG_exit(EXIT_FAILURE); 347 } 348 349 Printf(f_phpcode, "<?php\n\n"); 350 351 Swig_banner(f_phpcode); 352 353 Printf(f_phpcode, "\n"); 354 Printf(f_phpcode, "// Try to load our extension if it's not already loaded.\n"); 355 Printf(f_phpcode, "if (!extension_loaded('%s')) {\n", module); 356 Printf(f_phpcode, " if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {\n"); 357 Printf(f_phpcode, " if (!dl('php_%s.dll')) return;\n", module); 358 Printf(f_phpcode, " } else {\n"); 359 Printf(f_phpcode, " // PHP_SHLIB_SUFFIX gives 'dylib' on MacOS X but modules are 'so'.\n"); 360 Printf(f_phpcode, " if (PHP_SHLIB_SUFFIX === 'dylib') {\n"); 361 Printf(f_phpcode, " if (!dl('%s.so')) return;\n", module); 362 Printf(f_phpcode, " } else {\n"); 363 Printf(f_phpcode, " if (!dl('%s.'.PHP_SHLIB_SUFFIX)) return;\n", module); 364 Printf(f_phpcode, " }\n"); 365 Printf(f_phpcode, " }\n"); 366 Printf(f_phpcode, "}\n\n"); 367 368 /* sub-sections of the php file */ 369 pragma_code = NewStringEmpty(); 370 pragma_incl = NewStringEmpty(); 371 372 /* Initialize the rest of the module */ 373 374 Printf(s_oinit, "ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, %s_destroy_globals);\n", module, module, module); 375 376 /* start the header section */ 377 Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module); 378 Printf(s_header, "const char *error_msg;\n"); 379 Printf(s_header, "int error_code;\n"); 380 Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module); 381 Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module); 382 Printf(s_header, "#ifdef ZTS\n"); 383 Printf(s_header, "#define SWIG_ErrorMsg() TSRMG(%s_globals_id, zend_%s_globals *, error_msg )\n", module, module); 384 Printf(s_header, "#define SWIG_ErrorCode() TSRMG(%s_globals_id, zend_%s_globals *, error_code )\n", module, module); 385 Printf(s_header, "#else\n"); 386 Printf(s_header, "#define SWIG_ErrorMsg() (%s_globals.error_msg)\n", module); 387 Printf(s_header, "#define SWIG_ErrorCode() (%s_globals.error_code)\n", module); 388 Printf(s_header, "#endif\n\n"); 389 390 Printf(s_header, "static void %s_init_globals(zend_%s_globals *globals ) {\n", module, module); 391 Printf(s_header, " globals->error_msg = default_error_msg;\n"); 392 Printf(s_header, " globals->error_code = default_error_code;\n"); 393 Printf(s_header, "}\n"); 394 395 Printf(s_header, "static void %s_destroy_globals(zend_%s_globals * globals) { (void)globals; }\n", module, module); 396 397 Printf(s_header, "\n"); 398 Printf(s_header, "static void SWIG_ResetError() {\n"); 399 Printf(s_header, " TSRMLS_FETCH();\n"); 400 Printf(s_header, " SWIG_ErrorMsg() = default_error_msg;\n"); 401 Printf(s_header, " SWIG_ErrorCode() = default_error_code;\n"); 402 Printf(s_header, "}\n"); 403 404 Append(s_header, "\n"); 405 Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_alter_newobject) {\n", module); 406 Append(s_header, " zval **args[2];\n"); 407 Append(s_header, " swig_object_wrapper *value;\n"); 408 Append(s_header, " int type;\n"); 409 Append(s_header, " int thisown;\n"); 410 Append(s_header, "\n"); 411 Append(s_header, " SWIG_ResetError();\n"); 412 Append(s_header, " if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {\n"); 413 Append(s_header, " WRONG_PARAM_COUNT;\n"); 414 Append(s_header, " }\n"); 415 Append(s_header, "\n"); 416 Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); 417 Append(s_header, " value->newobject = zval_is_true(*args[1]);\n"); 418 Append(s_header, "\n"); 419 Append(s_header, " return;\n"); 420 Append(s_header, "}\n"); 421 Printf(s_header, "ZEND_NAMED_FUNCTION(_wrap_swig_%s_get_newobject) {\n", module); 422 Append(s_header, " zval **args[1];\n"); 423 Append(s_header, " swig_object_wrapper *value;\n"); 424 Append(s_header, " int type;\n"); 425 Append(s_header, "\n"); 426 Append(s_header, " SWIG_ResetError();\n"); 427 Append(s_header, " if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_array_ex(1, args) != SUCCESS) {\n"); 428 Append(s_header, " WRONG_PARAM_COUNT;\n"); 429 Append(s_header, " }\n"); 430 Append(s_header, "\n"); 431 Append(s_header, " value = (swig_object_wrapper *) zend_list_find((*args[0])->value.lval, &type);\n"); 432 Append(s_header, " RETVAL_LONG(value->newobject);\n"); 433 Append(s_header, "\n"); 434 Append(s_header, " return;\n"); 435 Append(s_header, "}\n"); 436 437 Printf(s_header, "#define SWIG_name \"%s\"\n", module); 438 /* Printf(s_header,"#ifdef HAVE_CONFIG_H\n"); 439 Printf(s_header,"#include \"config.h\"\n"); 440 Printf(s_header,"#endif\n\n"); 441 */ 442 Printf(s_header, "#ifdef __cplusplus\n"); 443 Printf(s_header, "extern \"C\" {\n"); 444 Printf(s_header, "#endif\n"); 445 Printf(s_header, "#include \"php.h\"\n"); 446 Printf(s_header, "#include \"php_ini.h\"\n"); 447 Printf(s_header, "#include \"ext/standard/info.h\"\n"); 448 Printf(s_header, "#include \"php_%s.h\"\n", module); 449 Printf(s_header, "#ifdef __cplusplus\n"); 450 Printf(s_header, "}\n"); 451 Printf(s_header, "#endif\n\n"); 452 453 if (directorsEnabled()) { 454 // Insert director runtime 455 Swig_insert_file("director.swg", s_header); 456 } 457 458 /* Create the .h file too */ 459 filen = NewStringEmpty(); 460 Printv(filen, SWIG_output_directory(), "php_", module, ".h", NIL); 461 f_h = NewFile(filen, "w", SWIG_output_files()); 462 if (!f_h) { 463 FileErrorDisplay(filen); 464 SWIG_exit(EXIT_FAILURE); 465 } 466 467 Swig_banner(f_h); 468 469 Printf(f_h, "\n"); 470 Printf(f_h, "#ifndef PHP_%s_H\n", cap_module); 471 Printf(f_h, "#define PHP_%s_H\n\n", cap_module); 472 Printf(f_h, "extern zend_module_entry %s_module_entry;\n", module); 473 Printf(f_h, "#define phpext_%s_ptr &%s_module_entry\n\n", module, module); 474 Printf(f_h, "#ifdef PHP_WIN32\n"); 475 Printf(f_h, "# define PHP_%s_API __declspec(dllexport)\n", cap_module); 476 Printf(f_h, "#else\n"); 477 Printf(f_h, "# define PHP_%s_API\n", cap_module); 478 Printf(f_h, "#endif\n\n"); 479 Printf(f_h, "#ifdef ZTS\n"); 480 Printf(f_h, "#include \"TSRM.h\"\n"); 481 Printf(f_h, "#endif\n\n"); 482 Printf(f_h, "PHP_MINIT_FUNCTION(%s);\n", module); 483 Printf(f_h, "PHP_MSHUTDOWN_FUNCTION(%s);\n", module); 484 Printf(f_h, "PHP_RINIT_FUNCTION(%s);\n", module); 485 Printf(f_h, "PHP_RSHUTDOWN_FUNCTION(%s);\n", module); 486 Printf(f_h, "PHP_MINFO_FUNCTION(%s);\n\n", module); 487 488 /* start the function entry section */ 489 s_entry = NewString("/* entry subsection */\n"); 490 491 /* holds all the per-class function entry sections */ 492 all_cs_entry = NewString("/* class entry subsection */\n"); 493 cs_entry = NULL; 494 495 Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n"); 496 Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module); 497 498 /* start the init section */ 499 Append(s_init, "#if ZEND_MODULE_API_NO <= 20090626\n"); 500 Append(s_init, "#undef ZEND_MODULE_BUILD_ID\n"); 501 Append(s_init, "#define ZEND_MODULE_BUILD_ID (char*)\"API\" ZEND_TOSTR(ZEND_MODULE_API_NO) ZEND_BUILD_TS ZEND_BUILD_DEBUG ZEND_BUILD_SYSTEM ZEND_BUILD_EXTRA\n"); 502 Append(s_init, "#endif\n"); 503 Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n" "#if ZEND_MODULE_API_NO > 20010900\n" " STANDARD_MODULE_HEADER,\n" "#endif\n", NIL); 504 Printf(s_init, " (char*)\"%s\",\n", module); 505 Printf(s_init, " %s_functions,\n", module); 506 Printf(s_init, " PHP_MINIT(%s),\n", module); 507 Printf(s_init, " PHP_MSHUTDOWN(%s),\n", module); 508 Printf(s_init, " PHP_RINIT(%s),\n", module); 509 Printf(s_init, " PHP_RSHUTDOWN(%s),\n", module); 510 Printf(s_init, " PHP_MINFO(%s),\n", module); 511 Printf(s_init, "#if ZEND_MODULE_API_NO > 20010900\n"); 512 Printf(s_init, " NO_VERSION_YET,\n"); 513 Printf(s_init, "#endif\n"); 514 Printf(s_init, " STANDARD_MODULE_PROPERTIES\n"); 515 Printf(s_init, "};\n"); 516 Printf(s_init, "zend_module_entry* SWIG_module_entry = &%s_module_entry;\n\n", module); 517 518 Printf(s_init, "#ifdef __cplusplus\n"); 519 Printf(s_init, "extern \"C\" {\n"); 520 Printf(s_init, "#endif\n"); 521 // We want to write "SWIGEXPORT ZEND_GET_MODULE(%s)" but ZEND_GET_MODULE 522 // in PHP5 has "extern "C" { ... }" around it so we can't do that. 523 Printf(s_init, "SWIGEXPORT zend_module_entry *get_module(void) { return &%s_module_entry; }\n", module); 524 Printf(s_init, "#ifdef __cplusplus\n"); 525 Printf(s_init, "}\n"); 526 Printf(s_init, "#endif\n\n"); 527 528 /* We have to register the constants before they are (possibly) used 529 * by the pointer typemaps. This all needs re-arranging really as 530 * things are being called in the wrong order 531 */ 532 Printf(s_init, "#define SWIG_php_minit PHP_MINIT_FUNCTION(%s)\n", module); 533 534 /* Emit all of the code */ 535 Language::top(n); 536 537 SwigPHP_emit_resource_registrations(); 538 // Printv(s_init,s_resourcetypes,NIL); 539 /* We need this after all classes written out by ::top */ 540 Printf(s_oinit, "CG(active_class_entry) = NULL;\n"); 541 Printf(s_oinit, "/* end oinit subsection */\n"); 542 Printf(s_init, "%s\n", s_oinit); 543 544 /* Constants generated during top call */ 545 Printf(s_cinit, "/* end cinit subsection */\n"); 546 Printf(s_init, "%s\n", s_cinit); 547 Clear(s_cinit); 548 Delete(s_cinit); 549 550 Printf(s_init, " return SUCCESS;\n"); 551 Printf(s_init, "}\n\n"); 552 553 // Now do REQUEST init which holds any user specified %rinit, and also vinit 554 Printf(s_init, "PHP_RINIT_FUNCTION(%s)\n{\n", module); 555 Printf(s_init, "%s\n", r_init); 556 557 /* finish our init section which will have been used by class wrappers */ 558 Printf(s_vinit, "/* end vinit subsection */\n"); 559 Printf(s_init, "%s\n", s_vinit); 560 Clear(s_vinit); 561 Delete(s_vinit); 562 563 Printf(s_init, " return SUCCESS;\n"); 564 Printf(s_init, "}\n\n"); 565 566 Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n" 567 "{\n", 568 s_shutdown, 569 "#ifdef ZTS\n" 570 " ts_free_id(", module, "_globals_id);\n" 571 "#endif\n" 572 " return SUCCESS;\n" 573 "}\n\n", NIL); 574 575 Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module); 576 Printf(s_init, "%s\n", r_shutdown); 577 Printf(s_init, " return SUCCESS;\n"); 578 Printf(s_init, "}\n\n"); 579 580 Printf(s_init, "PHP_MINFO_FUNCTION(%s)\n{\n", module); 581 Printf(s_init, "%s", pragma_phpinfo); 582 Printf(s_init, "}\n"); 583 Printf(s_init, "/* end init section */\n"); 584 585 Printf(f_h, "#endif /* PHP_%s_H */\n", cap_module); 586 587 Close(f_h); 588 589 String *type_table = NewStringEmpty(); 590 SwigType_emit_type_table(f_runtime, type_table); 591 Printf(s_header, "%s", type_table); 592 Delete(type_table); 593 594 /* Oh dear, more things being called in the wrong order. This whole 595 * function really needs totally redoing. 596 */ 597 598 if (directorsEnabled()) { 599 Dump(f_directors_h, f_runtime_h); 600 Printf(f_runtime_h, "\n"); 601 Printf(f_runtime_h, "#endif\n"); 602 Close(f_runtime_h); 603 } 604 605 Printf(s_header, "/* end header section */\n"); 606 Printf(s_wrappers, "/* end wrapper section */\n"); 607 Printf(s_vdecl, "/* end vdecl subsection */\n"); 608 609 Dump(f_runtime, f_begin); 610 Printv(f_begin, s_header, NIL); 611 if (directorsEnabled()) { 612 Dump(f_directors, f_begin); 613 } 614 Printv(f_begin, s_vdecl, s_wrappers, NIL); 615 Printv(f_begin, all_cs_entry, "\n\n", s_entry, 616 " SWIG_ZEND_NAMED_FE(swig_", module, "_alter_newobject,_wrap_swig_", module, "_alter_newobject,NULL)\n" 617 " SWIG_ZEND_NAMED_FE(swig_", module, "_get_newobject,_wrap_swig_", module, "_get_newobject,NULL)\n" 618 "{NULL, NULL, NULL}\n};\n\n", NIL); 619 Printv(f_begin, s_init, NIL); 620 Delete(s_header); 621 Delete(s_wrappers); 622 Delete(s_init); 623 Delete(s_vdecl); 624 Delete(all_cs_entry); 625 Delete(s_entry); 626 Close(f_begin); 627 Delete(f_runtime); 628 Delete(f_begin); 629 630 Printf(f_phpcode, "%s\n%s\n", pragma_incl, pragma_code); 631 if (s_fakeoowrappers) { 632 Printf(f_phpcode, "abstract class %s {", Len(prefix) ? prefix : module); 633 Printf(f_phpcode, "%s", s_fakeoowrappers); 634 Printf(f_phpcode, "}\n\n"); 635 Delete(s_fakeoowrappers); 636 s_fakeoowrappers = NULL; 637 } 638 Printf(f_phpcode, "%s\n?>\n", s_phpclasses); 639 Close(f_phpcode); 640 641 return SWIG_OK; 642 } 643 644 /* Just need to append function names to function table to register with PHP. */ 645 void create_command(String *cname, String *iname) { 646 // This is for the single main zend_function_entry record 647 Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname); 648 String * s = cs_entry; 649 if (!s) s = s_entry; 650 Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname); 651 } 652 653 /* ------------------------------------------------------------ 654 * dispatchFunction() 655 * ------------------------------------------------------------ */ 656 void dispatchFunction(Node *n) { 657 /* Last node in overloaded chain */ 658 659 int maxargs; 660 String *tmp = NewStringEmpty(); 661 if (Swig_directorclass(n) && wrapperType == directorconstructor) { 662 /* We have an extra 'this' parameter. */ 663 SetFlag(n, "wrap:this"); 664 } 665 String *dispatch = Swig_overload_dispatch(n, "return %s(INTERNAL_FUNCTION_PARAM_PASSTHRU);", &maxargs); 666 667 /* Generate a dispatch wrapper for all overloaded functions */ 668 669 Wrapper *f = NewWrapper(); 670 String *symname = Getattr(n, "sym:name"); 671 String *wname = Swig_name_wrapper(symname); 672 673 create_command(symname, wname); 674 Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); 675 676 Wrapper_add_local(f, "argc", "int argc"); 677 678 Printf(tmp, "zval **argv[%d]", maxargs); 679 Wrapper_add_local(f, "argv", tmp); 680 681 Printf(f->code, "argc = ZEND_NUM_ARGS();\n"); 682 683 Printf(f->code, "zend_get_parameters_array_ex(argc,argv);\n"); 684 685 Replaceall(dispatch, "$args", "self,args"); 686 687 Printv(f->code, dispatch, "\n", NIL); 688 689 Printf(f->code, "SWIG_ErrorCode() = E_ERROR;\n"); 690 Printf(f->code, "SWIG_ErrorMsg() = \"No matching function for overloaded '%s'\";\n", symname); 691 Printv(f->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n", NIL); 692 693 Printv(f->code, "}\n", NIL); 694 Wrapper_print(f, s_wrappers); 695 696 DelWrapper(f); 697 Delete(dispatch); 698 Delete(tmp); 699 Delete(wname); 700 } 701 702 /* ------------------------------------------------------------ 703 * functionWrapper() 704 * ------------------------------------------------------------ */ 705 706 /* Helper method for PHP::functionWrapper */ 707 bool is_class(SwigType *t) { 708 Node *n = classLookup(t); 709 if (n) { 710 String *r = Getattr(n, "php:proxy"); // Set by classDeclaration() 711 if (!r) 712 r = Getattr(n, "sym:name"); // Not seen by classDeclaration yet, but this is the name 713 if (r) 714 return true; 715 } 716 return false; 717 } 718 719 virtual int functionWrapper(Node *n) { 720 String *name = GetChar(n, "name"); 721 String *iname = GetChar(n, "sym:name"); 722 SwigType *d = Getattr(n, "type"); 723 ParmList *l = Getattr(n, "parms"); 724 String *nodeType = Getattr(n, "nodeType"); 725 int newobject = GetFlag(n, "feature:new"); 726 int constructor = (Cmp(nodeType, "constructor") == 0); 727 728 Parm *p; 729 int i; 730 int numopt; 731 String *tm; 732 Wrapper *f; 733 734 String *wname; 735 int overloaded = 0; 736 String *overname = 0; 737 738 if (Cmp(nodeType, "destructor") == 0) { 739 // We just generate the Zend List Destructor and let Zend manage the 740 // reference counting. There's no explicit destructor, but the user can 741 // just do `$obj = null;' to remove a reference to an object. 742 return CreateZendListDestructor(n); 743 } 744 // Test for overloading; 745 if (Getattr(n, "sym:overloaded")) { 746 overloaded = 1; 747 overname = Getattr(n, "sym:overname"); 748 } else { 749 if (!addSymbol(iname, n)) 750 return SWIG_ERROR; 751 } 752 753 wname = Swig_name_wrapper(iname); 754 if (overname) { 755 Printf(wname, "%s", overname); 756 } 757 758 f = NewWrapper(); 759 numopt = 0; 760 761 String *outarg = NewStringEmpty(); 762 String *cleanup = NewStringEmpty(); 763 764 // Not issued for overloaded functions. 765 if (!overloaded) { 766 create_command(iname, wname); 767 } 768 Printv(f->def, "ZEND_NAMED_FUNCTION(", wname, ") {\n", NIL); 769 770 emit_parameter_variables(l, f); 771 /* Attach standard typemaps */ 772 773 emit_attach_parmmaps(l, f); 774 775 // wrap:parms is used by overload resolution. 776 Setattr(n, "wrap:parms", l); 777 778 int num_arguments = emit_num_arguments(l); 779 int num_required = emit_num_required(l); 780 numopt = num_arguments - num_required; 781 782 if (wrapperType == directorconstructor) 783 num_arguments++; 784 785 if (num_arguments > 0) { 786 String *args = NewStringEmpty(); 787 if (wrapperType == directorconstructor) 788 Wrapper_add_local(f, "arg0", "zval *arg0"); 789 Printf(args, "zval **args[%d]", num_arguments); 790 Wrapper_add_local(f, "args", args); 791 Delete(args); 792 args = NULL; 793 } 794 if (is_member_director(n)) { 795 Wrapper_add_local(f, "director", "Swig::Director *director = 0"); 796 Printf(f->code, "director = dynamic_cast<Swig::Director*>(arg1);\n"); 797 Wrapper_add_local(f, "upcall", "bool upcall = false"); 798 Printf(f->code, "upcall = !director->is_overriden_method((char *)\"%s\", (char *)\"%s\");\n", 799 Swig_class_name(Swig_methodclass(n)), name); 800 } 801 802 // This generated code may be called: 803 // 1) as an object method, or 804 // 2) as a class-method/function (without a "this_ptr") 805 // Option (1) has "this_ptr" for "this", option (2) needs it as 806 // first parameter 807 808 // NOTE: possible we ignore this_ptr as a param for native constructor 809 810 Printf(f->code, "SWIG_ResetError();\n"); 811 812 if (numopt > 0) { // membervariable wrappers do not have optional args 813 Wrapper_add_local(f, "arg_count", "int arg_count"); 814 Printf(f->code, "arg_count = ZEND_NUM_ARGS();\n"); 815 Printf(f->code, "if(arg_count<%d || arg_count>%d ||\n", num_required, num_arguments); 816 Printf(f->code, " zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)\n"); 817 Printf(f->code, "\tWRONG_PARAM_COUNT;\n\n"); 818 } else { 819 if (num_arguments == 0) { 820 Printf(f->code, "if(ZEND_NUM_ARGS() != 0) {\n"); 821 } else { 822 Printf(f->code, "if(ZEND_NUM_ARGS() != %d || zend_get_parameters_array_ex(%d, args) != SUCCESS) {\n", num_arguments, num_arguments); 823 } 824 Printf(f->code, "WRONG_PARAM_COUNT;\n}\n\n"); 825 } 826 if (wrapperType == directorconstructor) 827 Printf(f->code, "arg0 = *args[0];\n \n"); 828 829 /* Now convert from PHP to C variables */ 830 // At this point, argcount if used is the number of deliberately passed args 831 // not including this_ptr even if it is used. 832 // It means error messages may be out by argbase with error 833 // reports. We can either take argbase into account when raising 834 // errors, or find a better way of dealing with _thisptr. 835 // I would like, if objects are wrapped, to assume _thisptr is always 836 // _this and not the first argument. 837 // This may mean looking at Language::memberfunctionHandler 838 839 int limit = num_arguments; 840 if (wrapperType == directorconstructor) 841 limit--; 842 for (i = 0, p = l; i < limit; i++) { 843 String *source; 844 845 /* Skip ignored arguments */ 846 //while (Getattr(p,"tmap:ignore")) { p = Getattr(p,"tmap:ignore:next");} 847 while (checkAttribute(p, "tmap:in:numinputs", "0")) { 848 p = Getattr(p, "tmap:in:next"); 849 } 850 851 SwigType *pt = Getattr(p, "type"); 852 853 if (wrapperType == directorconstructor) { 854 source = NewStringf("args[%d]", i+1); 855 } else { 856 source = NewStringf("args[%d]", i); 857 } 858 859 String *ln = Getattr(p, "lname"); 860 861 /* Check if optional */ 862 if (i >= num_required) { 863 Printf(f->code, "\tif(arg_count > %d) {\n", i); 864 } 865 866 if ((tm = Getattr(p, "tmap:in"))) { 867 Replaceall(tm, "$source", source); 868 Replaceall(tm, "$target", ln); 869 Replaceall(tm, "$input", source); 870 Setattr(p, "emit:input", source); 871 Printf(f->code, "%s\n", tm); 872 if (i == 0 && Getattr(p, "self")) { 873 Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n"); 874 } 875 p = Getattr(p, "tmap:in:next"); 876 if (i >= num_required) { 877 Printf(f->code, "}\n"); 878 } 879 continue; 880 } else { 881 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); 882 } 883 if (i >= num_required) { 884 Printf(f->code, "\t}\n"); 885 } 886 Delete(source); 887 } 888 889 Swig_director_emit_dynamic_cast(n, f); 890 891 /* Insert constraint checking code */ 892 for (p = l; p;) { 893 if ((tm = Getattr(p, "tmap:check"))) { 894 Replaceall(tm, "$target", Getattr(p, "lname")); 895 Printv(f->code, tm, "\n", NIL); 896 p = Getattr(p, "tmap:check:next"); 897 } else { 898 p = nextSibling(p); 899 } 900 } 901 902 /* Insert cleanup code */ 903 for (i = 0, p = l; p; i++) { 904 if ((tm = Getattr(p, "tmap:freearg"))) { 905 Replaceall(tm, "$source", Getattr(p, "lname")); 906 Printv(cleanup, tm, "\n", NIL); 907 p = Getattr(p, "tmap:freearg:next"); 908 } else { 909 p = nextSibling(p); 910 } 911 } 912 913 /* Insert argument output code */ 914 for (i = 0, p = l; p; i++) { 915 if ((tm = Getattr(p, "tmap:argout"))) { 916 Replaceall(tm, "$source", Getattr(p, "lname")); 917 // Replaceall(tm,"$input",Getattr(p,"lname")); 918 Replaceall(tm, "$target", "return_value"); 919 Replaceall(tm, "$result", "return_value"); 920 Replaceall(tm, "$arg", Getattr(p, "emit:input")); 921 Replaceall(tm, "$input", Getattr(p, "emit:input")); 922 Printv(outarg, tm, "\n", NIL); 923 p = Getattr(p, "tmap:argout:next"); 924 } else { 925 p = nextSibling(p); 926 } 927 } 928 929 Setattr(n, "wrap:name", wname); 930 931 /* emit function call */ 932 String *actioncode = emit_action(n); 933 934 if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) { 935 Replaceall(tm, "$input", "result"); 936 Replaceall(tm, "$source", "result"); 937 Replaceall(tm, "$target", "return_value"); 938 Replaceall(tm, "$result", "return_value"); 939 Replaceall(tm, "$owner", newobject ? "1" : "0"); 940 Printf(f->code, "%s\n", tm); 941 } else { 942 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); 943 } 944 emit_return_variable(n, d, f); 945 946 if (outarg) { 947 Printv(f->code, outarg, NIL); 948 } 949 950 if (cleanup) { 951 Printv(f->code, cleanup, NIL); 952 } 953 954 /* Look to see if there is any newfree cleanup code */ 955 if (GetFlag(n, "feature:new")) { 956 if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) { 957 Printf(f->code, "%s\n", tm); 958 Delete(tm); 959 } 960 } 961 962 /* See if there is any return cleanup code */ 963 if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) { 964 Printf(f->code, "%s\n", tm); 965 Delete(tm); 966 } 967 968 Printf(f->code, "return;\n"); 969 970 /* Error handling code */ 971 Printf(f->code, "fail:\n"); 972 Printv(f->code, cleanup, NIL); 973 Printv(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL); 974 975 Printf(f->code, "}\n"); 976 977 Replaceall(f->code, "$cleanup", cleanup); 978 Replaceall(f->code, "$symname", iname); 979 980 Wrapper_print(f, s_wrappers); 981 DelWrapper(f); 982 f = NULL; 983 984 if (overloaded && !Getattr(n, "sym:nextSibling")) { 985 dispatchFunction(n); 986 } 987 988 Delete(wname); 989 wname = NULL; 990 991 if (!shadow) { 992 return SWIG_OK; 993 } 994 995 // Handle getters and setters. 996 if (wrapperType == membervar) { 997 const char *p = Char(iname); 998 if (strlen(p) > 4) { 999 p += strlen(p) - 4; 1000 String *varname = Getattr(n, "membervariableHandler:sym:name"); 1001 if (strcmp(p, "_get") == 0) { 1002 Setattr(shadow_get_vars, varname, iname); 1003 } else if (strcmp(p, "_set") == 0) { 1004 Setattr(shadow_set_vars, varname, iname); 1005 } 1006 } 1007 return SWIG_OK; 1008 } 1009 1010 // Only look at non-overloaded methods and the last entry in each overload 1011 // chain (we check the last so that wrap:parms and wrap:name have been set 1012 // for them all). 1013 if (overloaded && Getattr(n, "sym:nextSibling") != 0) 1014 return SWIG_OK; 1015 1016 if (!s_oowrappers) 1017 s_oowrappers = NewStringEmpty(); 1018 1019 if (newobject || wrapperType == memberfn || wrapperType == staticmemberfn || wrapperType == standard || wrapperType == staticmembervar) { 1020 bool handle_as_overload = false; 1021 String **arg_names; 1022 String **arg_values; 1023 // Method or static method or plain function. 1024 const char *methodname = 0; 1025 String *output = s_oowrappers; 1026 if (constructor) { 1027 class_has_ctor = true; 1028 // Skip the Foo:: prefix. 1029 char *ptr = strrchr(GetChar(Swig_methodclass(n), "sym:name"), ':'); 1030 if (ptr) { 1031 ptr++; 1032 } else { 1033 ptr = GetChar(Swig_methodclass(n), "sym:name"); 1034 } 1035 if (strcmp(ptr, GetChar(n, "constructorHandler:sym:name")) == 0) { 1036 methodname = "__construct"; 1037 } else { 1038 // The class has multiple constructors and this one is 1039 // renamed, so this will be a static factory function 1040 methodname = GetChar(n, "constructorHandler:sym:name"); 1041 } 1042 } else if (wrapperType == memberfn) { 1043 methodname = Char(Getattr(n, "memberfunctionHandler:sym:name")); 1044 } else if (wrapperType == staticmemberfn) { 1045 methodname = Char(Getattr(n, "staticmemberfunctionHandler:sym:name")); 1046 } else if (wrapperType == staticmembervar) { 1047 // Static member variable, wrapped as a function due to PHP limitations. 1048 methodname = Char(Getattr(n, "staticmembervariableHandler:sym:name")); 1049 } else { // wrapperType == standard 1050 methodname = Char(iname); 1051 if (!s_fakeoowrappers) 1052 s_fakeoowrappers = NewStringEmpty(); 1053 output = s_fakeoowrappers; 1054 } 1055 1056 bool really_overloaded = overloaded ? true : false; 1057 int min_num_of_arguments = emit_num_required(l); 1058 int max_num_of_arguments = emit_num_arguments(l); 1059 1060 // For a function with default arguments, we end up with the fullest 1061 // parmlist in full_parmlist. 1062 ParmList *full_parmlist = l; 1063 Hash *ret_types = NewHash(); 1064 Setattr(ret_types, d, d); 1065 1066 if (overloaded) { 1067 // Look at all the overloaded versions of this method in turn to 1068 // decide if it's really an overloaded method, or just one where some 1069 // parameters have default values. 1070 Node *o = Getattr(n, "sym:overloaded"); 1071 while (o) { 1072 if (o == n) { 1073 o = Getattr(o, "sym:nextSibling"); 1074 continue; 1075 } 1076 1077 SwigType *d2 = Getattr(o, "type"); 1078 if (!d2) { 1079 assert(constructor); 1080 } else if (!Getattr(ret_types, d2)) { 1081 Setattr(ret_types, d2, d2); 1082 } 1083 1084 ParmList *l2 = Getattr(o, "wrap:parms"); 1085 int num_arguments = emit_num_arguments(l2); 1086 int num_required = emit_num_required(l2); 1087 if (num_required < min_num_of_arguments) 1088 min_num_of_arguments = num_required; 1089 1090 if (num_arguments > max_num_of_arguments) { 1091 max_num_of_arguments = num_arguments; 1092 full_parmlist = l2; 1093 } 1094 o = Getattr(o, "sym:nextSibling"); 1095 } 1096 1097 o = Getattr(n, "sym:overloaded"); 1098 while (o) { 1099 if (o == n) { 1100 o = Getattr(o, "sym:nextSibling"); 1101 continue; 1102 } 1103 1104 ParmList *l2 = Getattr(o, "wrap:parms"); 1105 Parm *p = l, *p2 = l2; 1106 if (wrapperType == memberfn) { 1107 p = nextSibling(p); 1108 p2 = nextSibling(p2); 1109 } 1110 while (p && p2) { 1111 if (Cmp(Getattr(p, "type"), Getattr(p2, "type")) != 0) 1112 break; 1113 if (Cmp(Getattr(p, "name"), Getattr(p2, "name")) != 0) 1114 break; 1115 String *value = Getattr(p, "value"); 1116 String *value2 = Getattr(p2, "value"); 1117 if (value && !value2) 1118 break; 1119 if (!value && value2) 1120 break; 1121 if (value) { 1122 if (Cmp(value, value2) != 0) 1123 break; 1124 } 1125 p = nextSibling(p); 1126 p2 = nextSibling(p2); 1127 } 1128 if (p && p2) 1129 break; 1130 // One parameter list is a prefix of the other, so check that all 1131 // remaining parameters of the longer list are optional. 1132 if (p2) 1133 p = p2; 1134 while (p && Getattr(p, "value")) 1135 p = nextSibling(p); 1136 if (p) 1137 break; 1138 o = Getattr(o, "sym:nextSibling"); 1139 } 1140 if (!o) { 1141 // This "overloaded method" is really just one with default args. 1142 really_overloaded = false; 1143 if (l != full_parmlist) { 1144 l = full_parmlist; 1145 if (wrapperType == memberfn) 1146 l = nextSibling(l); 1147 } 1148 } 1149 } 1150 1151 if (wrapperType == memberfn) { 1152 // Allow for the "this" pointer. 1153 --min_num_of_arguments; 1154 --max_num_of_arguments; 1155 } 1156 1157 arg_names = (String **) malloc(max_num_of_arguments * sizeof(String *)); 1158 if (!arg_names) { 1159 /* FIXME: How should this be handled? The rest of SWIG just seems 1160 * to not bother checking for malloc failing! */ 1161 fprintf(stderr, "Malloc failed!\n"); 1162 exit(1); 1163 } 1164 for (i = 0; i < max_num_of_arguments; ++i) { 1165 arg_names[i] = NULL; 1166 } 1167 1168 arg_values = (String **) malloc(max_num_of_arguments * sizeof(String *)); 1169 if (!arg_values) { 1170 /* FIXME: How should this be handled? The rest of SWIG just seems 1171 * to not bother checking for malloc failing! */ 1172 fprintf(stderr, "Malloc failed!\n"); 1173 exit(1); 1174 } 1175 for (i = 0; i < max_num_of_arguments; ++i) { 1176 arg_values[i] = NULL; 1177 } 1178 1179 Node *o; 1180 if (overloaded) { 1181 o = Getattr(n, "sym:overloaded"); 1182 } else { 1183 o = n; 1184 } 1185 while (o) { 1186 int argno = 0; 1187 Parm *p = Getattr(o, "wrap:parms"); 1188 if (wrapperType == memberfn) 1189 p = nextSibling(p); 1190 while (p) { 1191 if (GetInt(p, "tmap:in:numinputs") == 0) { 1192 p = nextSibling(p); 1193 continue; 1194 } 1195 assert(0 <= argno && argno < max_num_of_arguments); 1196 String *&pname = arg_names[argno]; 1197 const char *pname_cstr = GetChar(p, "name"); 1198 // Just get rid of the C++ namespace part for now. 1199 const char *ptr = NULL; 1200 if (pname_cstr && (ptr = strrchr(pname_cstr, ':'))) { 1201 pname_cstr = ptr + 1; 1202 } 1203 if (!pname_cstr) { 1204 // Unnamed parameter, e.g. int foo(int); 1205 } else if (pname == NULL) { 1206 pname = NewString(pname_cstr); 1207 } else { 1208 size_t len = strlen(pname_cstr); 1209 size_t spc = 0; 1210 size_t len_pname = strlen(Char(pname)); 1211 while (spc + len <= len_pname) { 1212 if (strncmp(pname_cstr, Char(pname) + spc, len) == 0) { 1213 char ch = ((char *) Char(pname))[spc + len]; 1214 if (ch == '\0' || ch == ' ') { 1215 // Already have this pname_cstr. 1216 pname_cstr = NULL; 1217 break; 1218 } 1219 } 1220 char *p = strchr(Char(pname) + spc, ' '); 1221 if (!p) 1222 break; 1223 spc = (p + 4) - Char(pname); 1224 } 1225 if (pname_cstr) { 1226 Printf(pname, " or_%s", pname_cstr); 1227 } 1228 } 1229 String *value = NewString(Getattr(p, "value")); 1230 if (Len(value)) { 1231 /* Check that value is a valid constant in PHP (and adjust it if 1232 * necessary, or replace it with "?" if it's just not valid). */ 1233 SwigType *type = Getattr(p, "type"); 1234 switch (SwigType_type(type)) { 1235 case T_BOOL: { 1236 if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0) 1237 break; 1238 char *p; 1239 errno = 0; 1240 int n = strtol(Char(value), &p, 0); 1241 Clear(value); 1242 if (errno || *p) { 1243 Append(value, "?"); 1244 } else if (n) { 1245 Append(value, "true"); 1246 } else { 1247 Append(value, "false"); 1248 } 1249 break; 1250 } 1251 case T_CHAR: 1252 case T_SCHAR: 1253 case T_SHORT: 1254 case T_INT: 1255 case T_LONG: { 1256 char *p; 1257 errno = 0; 1258 unsigned int n = strtol(Char(value), &p, 0); 1259 (void) n; 1260 if (errno || *p) { 1261 Clear(value); 1262 Append(value, "?"); 1263 } 1264 break; 1265 } 1266 case T_UCHAR: 1267 case T_USHORT: 1268 case T_UINT: 1269 case T_ULONG: { 1270 char *p; 1271 errno = 0; 1272 unsigned int n = strtoul(Char(value), &p, 0); 1273 (void) n; 1274 if (errno || *p) { 1275 Clear(value); 1276 Append(value, "?"); 1277 } 1278 break; 1279 } 1280 case T_FLOAT: 1281 case T_DOUBLE:{ 1282 char *p; 1283 errno = 0; 1284 /* FIXME: strtod is locale dependent... */ 1285 double val = strtod(Char(value), &p); 1286 if (errno || *p) { 1287 Clear(value); 1288 Append(value, "?"); 1289 } else if (strchr(Char(value), '.') == NULL) { 1290 // Ensure value is a double constant, not an integer one. 1291 Append(value, ".0"); 1292 double val2 = strtod(Char(value), &p); 1293 if (errno || *p || val != val2) { 1294 Clear(value); 1295 Append(value, "?"); 1296 } 1297 } 1298 break; 1299 } 1300 case T_REFERENCE: 1301 case T_USER: 1302 case T_ARRAY: 1303 Clear(value); 1304 Append(value, "?"); 1305 break; 1306 case T_STRING: 1307 if (Len(value) < 2) { 1308 // How can a string (including "" be less than 2 characters?) 1309 Clear(value); 1310 Append(value, "?"); 1311 } else { 1312 const char *v = Char(value); 1313 if (v[0] != '"' || v[Len(value) - 1] != '"') { 1314 Clear(value); 1315 Append(value, "?"); 1316 } 1317 // Strings containing "$" require special handling, but we do 1318 // that later. 1319 } 1320 break; 1321 case T_VOID: 1322 assert(false); 1323 break; 1324 case T_POINTER: { 1325 const char *v = Char(value); 1326 if (v[0] == '(') { 1327 // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc. 1328 v += strcspn(v + 1, "*()") + 1; 1329 if (*v == '*') { 1330 do { 1331 v++; 1332 v += strspn(v, " \t"); 1333 } while (*v == '*'); 1334 if (*v++ == ')') { 1335 v += strspn(v, " \t"); 1336 String * old = value; 1337 value = NewString(v); 1338 Delete(old); 1339 } 1340 } 1341 } 1342 if (Strcmp(value, "NULL") == 0 || 1343 Strcmp(value, "0") == 0 || 1344 Strcmp(value, "0L") == 0) { 1345 Clear(value); 1346 Append(value, "null"); 1347 } else { 1348 Clear(value); 1349 Append(value, "?"); 1350 } 1351 break; 1352 } 1353 } 1354 1355 if (!arg_values[argno]) { 1356 arg_values[argno] = value; 1357 value = NULL; 1358 } else if (Cmp(arg_values[argno], value) != 0) { 1359 // If a parameter has two different default values in 1360 // different overloaded forms of the function, we can't 1361 // set its default in PHP. Flag this by setting its 1362 // default to `?'. 1363 Delete(arg_values[argno]); 1364 arg_values[argno] = NewString("?"); 1365 } 1366 } else if (arg_values[argno]) { 1367 // This argument already has a default value in another overloaded 1368 // form, but doesn't in this form. So don't try to do anything 1369 // clever, just let the C wrappers resolve the overload and set the 1370 // default values. 1371 // 1372 // This handling is safe, but I'm wondering if it may be overly 1373 // conservative (FIXME) in some cases. It seems it's only bad when 1374 // there's an overloaded form with the appropriate number of 1375 // parameters which doesn't want the default value, but I need to 1376 // think about this more. 1377 Delete(arg_values[argno]); 1378 arg_values[argno] = NewString("?"); 1379 } 1380 Delete(value); 1381 p = nextSibling(p); 1382 ++argno; 1383 } 1384 if (!really_overloaded) 1385 break; 1386 o = Getattr(o, "sym:nextSibling"); 1387 } 1388 1389 /* Clean up any parameters which haven't yet got names, or whose 1390 * names clash. */ 1391 Hash *seen = NewHash(); 1392 /* We need $this to refer to the current class, so can't allow it 1393 * to be used as a parameter. */ 1394 Setattr(seen, "this", seen); 1395 /* We use $r to store the return value, so disallow that as a parameter 1396 * name in case the user uses the "call-time pass-by-reference" feature 1397 * (it's deprecated and off by default in PHP5, but we want to be 1398 * maximally portable). Similarly we use $c for the classname or new 1399 * stdClass object. 1400 */ 1401 Setattr(seen, "r", seen); 1402 Setattr(seen, "c", seen); 1403 1404 for (int argno = 0; argno < max_num_of_arguments; ++argno) { 1405 String *&pname = arg_names[argno]; 1406 if (pname) { 1407 Replaceall(pname, " ", "_"); 1408 } else { 1409 /* We get here if the SWIG .i file has "int foo(int);" */ 1410 pname = NewStringEmpty(); 1411 Printf(pname, "arg%d", argno + 1); 1412 } 1413 // Check if we've already used this parameter name. 1414 while (Getattr(seen, pname)) { 1415 // Append "_" to clashing names until they stop clashing... 1416 Printf(pname, "_"); 1417 } 1418 Setattr(seen, Char(pname), seen); 1419 1420 if (arg_values[argno] && Cmp(arg_values[argno], "?") == 0) { 1421 handle_as_overload = true; 1422 } 1423 } 1424 Delete(seen); 1425 seen = NULL; 1426 1427 String *invoke = NewStringEmpty(); 1428 String *prepare = NewStringEmpty(); 1429 String *args = NewStringEmpty(); 1430 1431 if (!handle_as_overload && !(really_overloaded && max_num_of_arguments > min_num_of_arguments)) { 1432 Printf(invoke, "%s(", iname); 1433 if (wrapperType == memberfn) { 1434 Printf(invoke, "$this->%s", SWIG_PTR); 1435 } 1436 for (int i = 0; i < max_num_of_arguments; ++i) { 1437 if (i) 1438 Printf(args, ","); 1439 if (i || wrapperType == memberfn) 1440 Printf(invoke, ","); 1441 String *value = arg_values[i]; 1442 if (value) { 1443 const char *v = Char(value); 1444 if (v[0] == '"') { 1445 /* In a PHP double quoted string, $ needs to be escaped as \$. */ 1446 Replaceall(value, "$", "\\$"); 1447 } 1448 Printf(args, "$%s=%s", arg_names[i], value); 1449 } else { 1450 Printf(args, "$%s", arg_names[i]); 1451 } 1452 Printf(invoke, "$%s", arg_names[i]); 1453 } 1454 Printf(invoke, ")"); 1455 } else { 1456 int i; 1457 for (i = 0; i < min_num_of_arguments; ++i) { 1458 if (i) 1459 Printf(args, ","); 1460 Printf(args, "$%s", arg_names[i]); 1461 } 1462 String *invoke_args = NewStringEmpty(); 1463 if (wrapperType == memberfn) { 1464 Printf(invoke_args, "$this->%s", SWIG_PTR); 1465 if (min_num_of_arguments > 0) 1466 Printf(invoke_args, ","); 1467 } 1468 Printf(invoke_args, "%s", args); 1469 bool had_a_case = false; 1470 int last_handled_i = i - 1; 1471 for (; i < max_num_of_arguments; ++i) { 1472 if (i) 1473 Printf(args, ","); 1474 const char *value = Char(arg_values[i]); 1475 // FIXME: (really_overloaded && handle_as_overload) is perhaps a 1476 // little conservative, but it doesn't hit any cases that it 1477 // shouldn't for Xapian at least (and we need it to handle 1478 // "Enquire::get_mset()" correctly). 1479 bool non_php_default = ((really_overloaded && handle_as_overload) || 1480 !value || strcmp(value, "?") == 0); 1481 if (non_php_default) 1482 value = "null"; 1483 Printf(args, "$%s=%s", arg_names[i], value); 1484 if (non_php_default) { 1485 if (!had_a_case) { 1486 Printf(prepare, "\t\tswitch (func_num_args()) {\n"); 1487 had_a_case = true; 1488 } 1489 Printf(prepare, "\t\t"); 1490 while (last_handled_i < i) { 1491 Printf(prepare, "case %d: ", ++last_handled_i); 1492 } 1493 if (Cmp(d, "void") != 0) { 1494 if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { 1495 Append(prepare, "$r="); 1496 } else { 1497 Printf(prepare, "$this->%s=", SWIG_PTR); 1498 } 1499 } 1500 if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { 1501 Printf(prepare, "%s(%s); break;\n", iname, invoke_args); 1502 } else if (!i) { 1503 Printf(prepare, "%s($_this%s); break;\n", iname, invoke_args); 1504 } else { 1505 Printf(prepare, "%s($_this, %s); break;\n", iname, invoke_args); 1506 } 1507 } 1508 if (i || wrapperType == memberfn) 1509 Printf(invoke_args, ","); 1510 Printf(invoke_args, "$%s", arg_names[i]); 1511 } 1512 Printf(prepare, "\t\t"); 1513 if (had_a_case) 1514 Printf(prepare, "default: "); 1515 if (Cmp(d, "void") != 0) { 1516 if ((!directorsEnabled() || !Swig_directorclass(n)) && !newobject) { 1517 Append(prepare, "$r="); 1518 } else { 1519 Printf(prepare, "$this->%s=", SWIG_PTR); 1520 } 1521 } 1522 1523 if (!directorsEnabled() || !Swig_directorclass(n) || !newobject) { 1524 Printf(prepare, "%s(%s);\n", iname, invoke_args); 1525 } else { 1526 Printf(prepare, "%s($_this, %s);\n", iname, invoke_args); 1527 } 1528 if (had_a_case) 1529 Printf(prepare, "\t\t}\n"); 1530 Delete(invoke_args); 1531 Printf(invoke, "$r"); 1532 } 1533 1534 Printf(output, "\n"); 1535 // If it's a member function or a class constructor... 1536 if (wrapperType == memberfn || (constructor && current_class)) { 1537 String *acc = NewString(Getattr(n, "access")); 1538 // If a base has the same method with public access, then PHP 1539 // requires to have it here as public as well 1540 Node *bases = Getattr(Swig_methodclass(n), "bases"); 1541 if (bases && Strcmp(acc, "public") != 0) { 1542 String *warnmsg = 0; 1543 int haspublicbase = 0; 1544 Iterator i = First(bases); 1545 while (i.item) { 1546 Node *j = firstChild(i.item); 1547 while (j) { 1548 if (Strcmp(Getattr(j, "name"), Getattr(n, "name")) != 0) { 1549 j = nextSibling(j); 1550 continue; 1551 } 1552 if (Strcmp(nodeType(j), "cdecl") == 0) { 1553 if (!Getattr(j, "access") || checkAttribute(j, "access", "public")) { 1554 haspublicbase = 1; 1555 } 1556 } else if (Strcmp(nodeType(j), "using") == 0 && firstChild(j) && Strcmp(nodeType(firstChild(j)), "cdecl") == 0) { 1557 if (!Getattr(firstChild(j), "access") || checkAttribute(firstChild(j), "access", "public")) { 1558 haspublicbase = 1; 1559 } 1560 } 1561 if (haspublicbase) { 1562 warnmsg = NewStringf("Modifying the access of '%s::%s' to public, as the base '%s' has it as public as well.\n", Getattr(current_class, "classtype"), Getattr(n, "name"), Getattr(i.item, "classtype")); 1563 break; 1564 } 1565 j = nextSibling(j); 1566 } 1567 i = Next(i); 1568 if (haspublicbase) { 1569 break; 1570 } 1571 } 1572 if (Getattr(n, "access") && haspublicbase) { 1573 Delete(acc); 1574 acc = NewString("public"); 1575 Swig_warning(WARN_PHP_PUBLIC_BASE, input_file, line_number, Char(warnmsg)); 1576 Delete(warnmsg); 1577 } 1578 } 1579 if (Cmp(acc, "") != 0) { 1580 Append(acc, " "); 1581 } 1582 if (constructor) { 1583 const char * arg0; 1584 if (max_num_of_arguments > 0) { 1585 arg0 = Char(arg_names[0]); 1586 } else { 1587 arg0 = "res"; 1588 Delete(args); 1589 args = NewString("$res=null"); 1590 } 1591 SwigType *t = Getattr(current_class, "classtype"); 1592 String *mangled_type = SwigType_manglestr(SwigType_ltype(t)); 1593 Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); 1594 Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '_p%s') {\n", arg0, arg0, mangled_type); 1595 Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0); 1596 Printf(output, "\t\t\treturn;\n"); 1597 Printf(output, "\t\t}\n"); 1598 } else { 1599 Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args); 1600 } 1601 Delete(acc); 1602 } else if (wrapperType == staticmembervar) { 1603 // We're called twice for a writable static member variable - first 1604 // with "foo_set" and then with "foo_get" - so generate half the 1605 // wrapper function each time. 1606 // 1607 // For a const static member, we only get called once. 1608 static bool started = false; 1609 if (!started) { 1610 Printf(output, "\tstatic function %s() {\n", methodname); 1611 if (max_num_of_arguments) { 1612 // Setter. 1613 Printf(output, "\t\tif (func_num_args()) {\n"); 1614 Printf(output, "\t\t\t%s(func_get_arg(0));\n", iname); 1615 Printf(output, "\t\t\treturn;\n"); 1616 Printf(output, "\t\t}\n"); 1617 started = true; 1618 goto done; 1619 } 1620 } 1621 started = false; 1622 } else { 1623 Printf(output, "\tstatic function %s(%s) {\n", methodname, args); 1624 } 1625 1626 if (!newobject) 1627 Printf(output, "%s", prepare); 1628 if (constructor) { 1629 if (!directorsEnabled() || !Swig_directorclass(n)) { 1630 if (strcmp(methodname, "__construct") == 0) { 1631 Printf(output, "\t\t$this->%s=%s;\n", SWIG_PTR, invoke); 1632 } else { 1633 String *classname = Swig_class_name(current_class); 1634 Printf(output, "\t\treturn new %s(%s);\n", classname, invoke); 1635 } 1636 } else { 1637 Node *parent = Swig_methodclass(n); 1638 String *classname = Swig_class_name(parent); 1639 Printf(output, "\t\tif (get_class($this) === '%s%s') {\n", prefix, classname); 1640 Printf(output, "\t\t\t$_this = null;\n"); 1641 Printf(output, "\t\t} else {\n"); 1642 Printf(output, "\t\t\t$_this = $this;\n"); 1643 Printf(output, "\t\t}\n"); 1644 if (!Len(prepare)) { 1645 if (num_arguments > 1) { 1646 Printf(output, "\t\t$this->%s=%s($_this, %s);\n", SWIG_PTR, iname, args); 1647 } else { 1648 Printf(output, "\t\t$this->%s=%s($_this);\n", SWIG_PTR, iname); 1649 } 1650 } 1651 } 1652 Printf(output, "%s", prepare); 1653 } else if (Cmp(d, "void") == 0) { 1654 if (Cmp(invoke, "$r") != 0) 1655 Printf(output, "\t\t%s;\n", invoke); 1656 } else if (is_class(d)) { 1657 if (Cmp(invoke, "$r") != 0) 1658 Printf(output, "\t\t$r=%s;\n", invoke); 1659 if (Len(ret_types) == 1) { 1660 /* If it has an abstract base, then we can't create a new 1661 * base object. */ 1662 int hasabstractbase = 0; 1663 Node *bases = Getattr(Swig_methodclass(n), "bases"); 1664 if (bases) { 1665 Iterator i = First(bases); 1666 while(i.item) { 1667 if (Getattr(i.item, "abstract")) { 1668 hasabstractbase = 1; 1669 break; 1670 } 1671 i = Next(i); 1672 } 1673 } 1674 if (newobject || !hasabstractbase) { 1675 /* 1676 * _p_Foo -> Foo, _p_ns__Bar -> Bar 1677 * TODO: do this in a more elegant way 1678 */ 1679 Printf(output, "\t\tif (is_resource($r)) {\n"); 1680 if (Getattr(classLookup(Getattr(n, "type")), "module")) { 1681 if (Len(prefix) == 0) { 1682 Printf(output, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n"); 1683 } else { 1684 Printf(output, "\t\t\t$c='%s'.substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n", prefix); 1685 } 1686 Printf(output, "\t\t\tif (!class_exists($c)) {\n"); 1687 Printf(output, "\t\t\t\treturn new %s($r);\n", Getattr(classLookup(d), "sym:name")); 1688 Printf(output, "\t\t\t}\n"); 1689 Printf(output, "\t\t\treturn new $c($r);\n"); 1690 } else { 1691 Printf(output, "\t\t\t$c = new stdClass();\n"); 1692 Printf(output, "\t\t\t$c->_cPtr = $r;\n"); 1693 Printf(output, "\t\t\treturn $c;\n"); 1694 } 1695 Printf(output, "\t\t}\n\t\treturn $r;\n"); 1696 } else { 1697 Printf(output, "\t\t$this->%s = $r;\n", SWIG_PTR); 1698 Printf(output, "\t\treturn $this;\n"); 1699 } 1700 } else { 1701 Printf(output, "\t\tif (!is_resource($r)) return $r;\n"); 1702 Printf(output, "\t\tswitch (get_resource_type($r)) {\n"); 1703 Iterator i = First(ret_types); 1704 while (i.item) { 1705 SwigType *ret_type = i.item; 1706 i = Next(i); 1707 Printf(output, "\t\t"); 1708 String *mangled = NewString("_p"); 1709 Printf(mangled, "%s", SwigType_manglestr(ret_type)); 1710 Node *class_node = Getattr(zend_types, mangled); 1711 if (!class_node) { 1712 /* This is needed when we're returning a pointer to a type 1713 * rather than returning the type by value or reference. */ 1714 class_node = current_class; 1715 Delete(mangled); 1716 mangled = NewString(SwigType_manglestr(ret_type)); 1717 class_node = Getattr(zend_types, mangled); 1718 } 1719 if (i.item) { 1720 Printf(output, "case '%s': ", mangled); 1721 } else { 1722 Printf(output, "default: "); 1723 } 1724 const char *classname = GetChar(class_node, "sym:name"); 1725 if (!classname) 1726 classname = GetChar(class_node, "name"); 1727 if (classname) 1728 Printf(output, "return new %s%s($r);\n", prefix, classname); 1729 else 1730 Printf(output, "return $r;\n"); 1731 Delete(mangled); 1732 } 1733 Printf(output, "\t\t}\n"); 1734 } 1735 } else { 1736 Printf(output, "\t\treturn %s;\n", invoke); 1737 } 1738 Printf(output, "\t}\n"); 1739 1740done: 1741 Delete(prepare); 1742 Delete(invoke); 1743 free(arg_values); 1744 1745 Delete(args); 1746 args = NULL; 1747 1748 for (int i = 0; i < max_num_of_arguments; ++i) { 1749 Delete(arg_names[i]); 1750 } 1751 free(arg_names); 1752 arg_names = NULL; 1753 } 1754 1755 return SWIG_OK; 1756 } 1757 1758 /* ------------------------------------------------------------ 1759 * globalvariableHandler() 1760 * ------------------------------------------------------------ */ 1761 1762 virtual int globalvariableHandler(Node *n) { 1763 char *name = GetChar(n, "name"); 1764 char *iname = GetChar(n, "sym:name"); 1765 SwigType *t = Getattr(n, "type"); 1766 String *tm; 1767 1768 /* First do the wrappers such as name_set(), name_get() 1769 * as provided by the baseclass's implementation of variableWrapper 1770 */ 1771 if (Language::globalvariableHandler(n) == SWIG_NOWRAP) { 1772 return SWIG_NOWRAP; 1773 } 1774 1775 if (!addSymbol(iname, n)) 1776 return SWIG_ERROR; 1777 1778 SwigType_remember(t); 1779 1780 /* First link C variables to PHP */ 1781 1782 tm = Swig_typemap_lookup("varinit", n, name, 0); 1783 if (tm) { 1784 Replaceall(tm, "$target", name); 1785 Printf(s_vinit, "%s\n", tm); 1786 } else { 1787 Printf(stderr, "%s: Line %d, Unable to link with type %s\n", input_file, line_number, SwigType_str(t, 0)); 1788 } 1789 1790 /* Now generate PHP -> C sync blocks */ 1791 /* 1792 tm = Swig_typemap_lookup("varin", n, name, 0); 1793 if(tm) { 1794 Replaceall(tm, "$symname", iname); 1795 Printf(f_c->code, "%s\n", tm); 1796 } else { 1797 Printf(stderr,"%s: Line %d, Unable to link with type %s\n", input_file, line_number, SwigType_str(t, 0)); 1798 } 1799 */ 1800 /* Now generate C -> PHP sync blocks */ 1801 /* 1802 if(!GetFlag(n,"feature:immutable")) { 1803 1804 tm = Swig_typemap_lookup("varout", n, name, 0); 1805 if(tm) { 1806 Replaceall(tm, "$symname", iname); 1807 Printf(f_php->code, "%s\n", tm); 1808 } else { 1809 Printf(stderr,"%s: Line %d, Unable to link with type %s\n", input_file, line_number, SwigType_str(t, 0)); 1810 } 1811 } 1812 */ 1813 return SWIG_OK; 1814 } 1815 1816 /* ------------------------------------------------------------ 1817 * constantWrapper() 1818 * ------------------------------------------------------------ */ 1819 1820 virtual int constantWrapper(Node *n) { 1821 String *name = GetChar(n, "name"); 1822 String *iname = GetChar(n, "sym:name"); 1823 SwigType *type = Getattr(n, "type"); 1824 String *rawval = Getattr(n, "rawval"); 1825 String *value = rawval ? rawval : Getattr(n, "value"); 1826 String *tm; 1827 1828 if (!addSymbol(iname, n)) 1829 return SWIG_ERROR; 1830 1831 SwigType_remember(type); 1832 1833 if ((tm = Swig_typemap_lookup("consttab", n, name, 0))) { 1834 Replaceall(tm, "$source", value); 1835 Replaceall(tm, "$target", name); 1836 Replaceall(tm, "$value", value); 1837 Printf(s_cinit, "%s\n", tm); 1838 } 1839 1840 if (shadow) { 1841 String *enumvalue = GetChar(n, "enumvalue"); 1842 String *set_to = iname; 1843 1844 if (!enumvalue) { 1845 enumvalue = GetChar(n, "enumvalueex"); 1846 } 1847 1848 if (enumvalue) { 1849 // Check for a simple constant expression which is valid in PHP. 1850 // If we find one, initialise the const member with it; otherwise 1851 // we initialise it using the C/C++ wrapped constant. 1852 const char *p; 1853 for (p = Char(enumvalue); *p; ++p) { 1854 if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) { 1855 // FIXME: enhance to handle `<previous_enum> + 1' which is what 1856 // we get for enums that don't have an explicit value set. 1857 break; 1858 } 1859 } 1860 if (!*p) set_to = enumvalue; 1861 } 1862 1863 if (wrapping_member_constant) { 1864 if (!s_oowrappers) 1865 s_oowrappers = NewStringEmpty(); 1866 Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, set_to); 1867 } else { 1868 if (!s_fakeoowrappers) 1869 s_fakeoowrappers = NewStringEmpty(); 1870 Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", iname, set_to); 1871 } 1872 } 1873 1874 return SWIG_OK; 1875 } 1876 1877 /* 1878 * PHP::pragma() 1879 * 1880 * Pragma directive. 1881 * 1882 * %pragma(php) code="String" # Includes a string in the .php file 1883 * %pragma(php) include="file.php" # Includes a file in the .php file 1884 */ 1885 1886 virtual int pragmaDirective(Node *n) { 1887 if (!ImportMode) { 1888 String *lang = Getattr(n, "lang"); 1889 String *type = Getattr(n, "name"); 1890 String *value = Getattr(n, "value"); 1891 1892 if (Strcmp(lang, "php") == 0 || Strcmp(lang, "php4") == 0) { 1893 if (Strcmp(type, "code") == 0) { 1894 if (value) { 1895 Printf(pragma_code, "%s\n", value); 1896 } 1897 } else if (Strcmp(type, "include") == 0) { 1898 if (value) { 1899 Printf(pragma_incl, "include '%s';\n", value); 1900 } 1901 } else if (Strcmp(type, "phpinfo") == 0) { 1902 if (value) { 1903 Printf(pragma_phpinfo, "%s\n", value); 1904 } 1905 } else { 1906 Swig_warning(WARN_PHP_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", type); 1907 } 1908 } 1909 } 1910 return Language::pragmaDirective(n); 1911 } 1912 1913 /* ------------------------------------------------------------ 1914 * classDeclaration() 1915 * ------------------------------------------------------------ */ 1916 1917 virtual int classDeclaration(Node *n) { 1918 if (!Getattr(n, "feature:onlychildren")) { 1919 String *symname = Getattr(n, "sym:name"); 1920 Setattr(n, "php:proxy", symname); 1921 } 1922 1923 return Language::classDeclaration(n); 1924 } 1925 1926 /* ------------------------------------------------------------ 1927 * classHandler() 1928 * ------------------------------------------------------------ */ 1929 1930 virtual int classHandler(Node *n) { 1931 constructors = 0; 1932 //SwigType *t = Getattr(n, "classtype"); 1933 current_class = n; 1934 // String *use_class_name=SwigType_manglestr(SwigType_ltype(t)); 1935 1936 if (shadow) { 1937 char *rename = GetChar(n, "sym:name"); 1938 1939 if (!addSymbol(rename, n)) 1940 return SWIG_ERROR; 1941 shadow_classname = NewString(rename); 1942 1943 shadow_get_vars = NewHash(); 1944 shadow_set_vars = NewHash(); 1945 1946 /* Deal with inheritance */ 1947 List *baselist = Getattr(n, "bases"); 1948 if (baselist) { 1949 Iterator base = First(baselist); 1950 while (base.item && GetFlag(base.item, "feature:ignore")) { 1951 base = Next(base); 1952 } 1953 base = Next(base); 1954 if (base.item) { 1955 /* Warn about multiple inheritance for additional base class(es) */ 1956 while (base.item) { 1957 if (GetFlag(base.item, "feature:ignore")) { 1958 base = Next(base); 1959 continue; 1960 } 1961 String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0); 1962 String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0); 1963 Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number, 1964 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname); 1965 base = Next(base); 1966 } 1967 } 1968 } 1969 } 1970 1971 classnode = n; 1972 Language::classHandler(n); 1973 classnode = 0; 1974 1975 if (shadow) { 1976 DOH *key; 1977 List *baselist = Getattr(n, "bases"); 1978 Iterator ki, base; 1979 1980 if (baselist) { 1981 base = First(baselist); 1982 while (base.item && GetFlag(base.item, "feature:ignore")) { 1983 base = Next(base); 1984 } 1985 } else { 1986 base.item = NULL; 1987 } 1988 1989 if (Getattr(n, "abstract") && !GetFlag(n, "feature:notabstract")) { 1990 Printf(s_phpclasses, "abstract "); 1991 } 1992 1993 Printf(s_phpclasses, "class %s%s ", prefix, shadow_classname); 1994 String *baseclass = NULL; 1995 if (base.item && Getattr(base.item, "module")) { 1996 baseclass = Getattr(base.item, "sym:name"); 1997 if (!baseclass) 1998 baseclass = Getattr(base.item, "name"); 1999 Printf(s_phpclasses, "extends %s%s ", prefix, baseclass); 2000 } else if (GetFlag(n, "feature:exceptionclass")) { 2001 Append(s_phpclasses, "extends Exception "); 2002 } 2003 Printf(s_phpclasses, "{\n\tpublic $%s=null;\n", SWIG_PTR); 2004 if (!baseclass) { 2005 // Only store this in the base class (NB !baseclass means we *are* 2006 // a base class...) 2007 Printf(s_phpclasses, "\tprotected $%s=array();\n", SWIG_DATA); 2008 } 2009 2010 // Write property SET handlers 2011 ki = First(shadow_set_vars); 2012 2013 if (ki.key) { 2014 // This class has setters. 2015 Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n"); 2016 // FIXME: tune this threshold... 2017 if (Len(shadow_set_vars) <= 2) { 2018 // Not many setters, so avoid call_user_func. 2019 while (ki.key) { 2020 key = ki.key; 2021 Printf(s_phpclasses, "\t\tif ($var === '%s') return %s($this->%s,$value);\n", key, ki.item, SWIG_PTR); 2022 ki = Next(ki); 2023 } 2024 } else { 2025 Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname); 2026 Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s,$value);\n", SWIG_PTR); 2027 } 2028 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR); 2029 if (baseclass) { 2030 Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass); 2031 } else { 2032 Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA); 2033 } 2034 Printf(s_phpclasses, "\t}\n"); 2035 2036 /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */ 2037 Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); 2038 Printf(s_phpclasses, "\t\tif (function_exists('%s_'.$var.'_set')) return true;\n", shadow_classname); 2039 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); 2040 if (baseclass) { 2041 Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); 2042 } else { 2043 Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); 2044 } 2045 Printf(s_phpclasses, "\t}\n"); 2046 } else { 2047 Printf(s_phpclasses, "\n\tfunction __set($var,$value) {\n"); 2048 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_alter_newobject($this->%s,$value);\n", module, SWIG_PTR); 2049 if (baseclass) { 2050 Printf(s_phpclasses, "\t\t%s%s::__set($var,$value);\n", prefix, baseclass); 2051 } else { 2052 Printf(s_phpclasses, "\t\t$this->%s[$var] = $value;\n", SWIG_DATA); 2053 } 2054 Printf(s_phpclasses, "\t}\n"); 2055 Printf(s_phpclasses, "\n\tfunction __isset($var) {\n"); 2056 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return true;\n"); 2057 if (baseclass) { 2058 Printf(s_phpclasses, "\t\treturn %s%s::__isset($var);\n", prefix, baseclass); 2059 } else { 2060 Printf(s_phpclasses, "\t\treturn array_key_exists($var, $this->%s);\n", SWIG_DATA); 2061 } 2062 Printf(s_phpclasses, "\t}\n"); 2063 } 2064 // Write property GET handlers 2065 ki = First(shadow_get_vars); 2066 2067 if (ki.key) { 2068 // This class has getters. 2069 Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); 2070 // FIXME: Currently we always use call_user_func for __get, so we can 2071 // check and wrap the result. This is needless if all the properties 2072 // are primitive types. Also this doesn't handle all the cases which 2073 // a method returning an object does. 2074 Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname); 2075 Printf(s_phpclasses, "\t\tif (function_exists($func)) {\n"); 2076 Printf(s_phpclasses, "\t\t\t$r = call_user_func($func,$this->%s);\n", SWIG_PTR); 2077 Printf(s_phpclasses, "\t\t\tif (!is_resource($r)) return $r;\n"); 2078 if (Len(prefix) == 0) { 2079 Printf(s_phpclasses, "\t\t\t$c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n"); 2080 } else { 2081 Printf(s_phpclasses, "\t\t\t$c='%s'.substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));\n", prefix); 2082 } 2083 Printf(s_phpclasses, "\t\t\treturn new $c($r);\n"); 2084 Printf(s_phpclasses, "\t\t}\n"); 2085 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); 2086 if (baseclass) { 2087 Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); 2088 } else { 2089 // Reading an unknown property name gives null in PHP. 2090 Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA); 2091 } 2092 Printf(s_phpclasses, "\t}\n"); 2093 } else { 2094 Printf(s_phpclasses, "\n\tfunction __get($var) {\n"); 2095 Printf(s_phpclasses, "\t\tif ($var === 'thisown') return swig_%s_get_newobject($this->%s);\n", module, SWIG_PTR); 2096 if (baseclass) { 2097 Printf(s_phpclasses, "\t\treturn %s%s::__get($var);\n", prefix, baseclass); 2098 } else { 2099 Printf(s_phpclasses, "\t\treturn $this->%s[$var];\n", SWIG_DATA); 2100 } 2101 Printf(s_phpclasses, "\t}\n"); 2102 } 2103 2104 if (!class_has_ctor) { 2105 Printf(s_phpclasses, "\tfunction __construct($h) {\n"); 2106 Printf(s_phpclasses, "\t\t$this->%s=$h;\n", SWIG_PTR); 2107 Printf(s_phpclasses, "\t}\n"); 2108 } 2109 2110 if (s_oowrappers) { 2111 Printf(s_phpclasses, "%s", s_oowrappers); 2112 Delete(s_oowrappers); 2113 s_oowrappers = NULL; 2114 } 2115 class_has_ctor = false; 2116 2117 Printf(s_phpclasses, "}\n\n"); 2118 2119 Delete(shadow_classname); 2120 shadow_classname = NULL; 2121 2122 Delete(shadow_set_vars); 2123 shadow_set_vars = NULL; 2124 Delete(shadow_get_vars); 2125 shadow_get_vars = NULL; 2126 } 2127 return SWIG_OK; 2128 } 2129 2130 /* ------------------------------------------------------------ 2131 * memberfunctionHandler() 2132 * ------------------------------------------------------------ */ 2133 2134 virtual int memberfunctionHandler(Node *n) { 2135 wrapperType = memberfn; 2136 Language::memberfunctionHandler(n); 2137 wrapperType = standard; 2138 2139 return SWIG_OK; 2140 } 2141 2142 /* ------------------------------------------------------------ 2143 * membervariableHandler() 2144 * ------------------------------------------------------------ */ 2145 2146 virtual int membervariableHandler(Node *n) { 2147 wrapperType = membervar; 2148 Language::membervariableHandler(n); 2149 wrapperType = standard; 2150 2151 return SWIG_OK; 2152 } 2153 2154 /* ------------------------------------------------------------ 2155 * staticmembervariableHandler() 2156 * ------------------------------------------------------------ */ 2157 2158 virtual int staticmembervariableHandler(Node *n) { 2159 wrapperType = staticmembervar; 2160 Language::staticmembervariableHandler(n); 2161 wrapperType = standard; 2162 2163 return SWIG_OK; 2164 } 2165 2166 /* ------------------------------------------------------------ 2167 * staticmemberfunctionHandler() 2168 * ------------------------------------------------------------ */ 2169 2170 virtual int staticmemberfunctionHandler(Node *n) { 2171 wrapperType = staticmemberfn; 2172 Language::staticmemberfunctionHandler(n); 2173 wrapperType = standard; 2174 2175 return SWIG_OK; 2176 } 2177 2178 int abstractConstructorHandler(Node *) { 2179 return SWIG_OK; 2180 } 2181 2182 /* ------------------------------------------------------------ 2183 * constructorHandler() 2184 * ------------------------------------------------------------ */ 2185 2186 virtual int constructorHandler(Node *n) { 2187 constructors++; 2188 if (Swig_directorclass(n)) { 2189 String *name = GetChar(Swig_methodclass(n), "name"); 2190 String *ctype = GetChar(Swig_methodclass(n), "classtype"); 2191 String *sname = GetChar(Swig_methodclass(n), "sym:name"); 2192 String *args = NewStringEmpty(); 2193 ParmList *p = Getattr(n, "parms"); 2194 int i; 2195 2196 for (i = 0; p; p = nextSibling(p), i++) { 2197 if (i) { 2198 Printf(args, ", "); 2199 } 2200 if (Strcmp(GetChar(p, "type"), SwigType_str(GetChar(p, "type"), 0))) { 2201 SwigType *t = Getattr(p, "type"); 2202 Printf(args, "%s", SwigType_rcaststr(t, 0)); 2203 if (SwigType_isreference(t)) { 2204 Append(args, "*"); 2205 } 2206 } 2207 Printf(args, "arg%d", i+1); 2208 } 2209 2210 /* director ctor code is specific for each class */ 2211 Delete(director_ctor_code); 2212 director_ctor_code = NewStringEmpty(); 2213 director_prot_ctor_code = NewStringEmpty(); 2214 Printf(director_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); 2215 Printf(director_prot_ctor_code, "if ( arg0->type == IS_NULL ) { /* not subclassed */\n"); 2216 Printf(director_ctor_code, " result = (%s *)new %s(%s);\n", ctype, ctype, args); 2217 Printf(director_prot_ctor_code, " SWIG_PHP_Error(E_ERROR, \"accessing abstract class or protected constructor\");\n", name, name, args); 2218 if (i) { 2219 Insert(args, 0, ", "); 2220 } 2221 Printf(director_ctor_code, "} else {\n result = (%s *)new SwigDirector_%s(arg0%s);\n}\n", ctype, sname, args); 2222 Printf(director_prot_ctor_code, "} else {\n result = (%s *)new SwigDirector_%s(arg0%s);\n}\n", ctype, sname, args); 2223 Delete(args); 2224 2225 wrapperType = directorconstructor; 2226 } else { 2227 wrapperType = constructor; 2228 } 2229 Language::constructorHandler(n); 2230 wrapperType = standard; 2231 2232 return SWIG_OK; 2233 } 2234 2235 /* ------------------------------------------------------------ 2236 * CreateZendListDestructor() 2237 * ------------------------------------------------------------ */ 2238 //virtual int destructorHandler(Node *n) { 2239 //} 2240 int CreateZendListDestructor(Node *n) { 2241 String *name = GetChar(Swig_methodclass(n), "name"); 2242 String *iname = GetChar(n, "sym:name"); 2243 ParmList *l = Getattr(n, "parms"); 2244 2245 String *destructorname = NewStringEmpty(); 2246 Printf(destructorname, "_%s", Swig_name_wrapper(iname)); 2247 Setattr(classnode, "destructor", destructorname); 2248 2249 Wrapper *f = NewWrapper(); 2250 Printf(f->def, "/* This function is designed to be called by the zend list destructors */\n"); 2251 Printf(f->def, "/* to typecast and do the actual destruction */\n"); 2252 Printf(f->def, "static void %s(zend_rsrc_list_entry *rsrc, const char *type_name TSRMLS_DC) {\n", destructorname); 2253 2254 Wrapper_add_localv(f, "value", "swig_object_wrapper *value=(swig_object_wrapper *) rsrc->ptr", NIL); 2255 Wrapper_add_localv(f, "ptr", "void *ptr=value->ptr", NIL); 2256 Wrapper_add_localv(f, "newobject", "int newobject=value->newobject", NIL); 2257 2258 emit_parameter_variables(l, f); 2259 emit_attach_parmmaps(l, f); 2260 2261 // Get type of first arg, thing to be destructed 2262 // Skip ignored arguments 2263 Parm *p = l; 2264 //while (Getattr(p,"tmap:ignore")) {p = Getattr(p,"tmap:ignore:next");} 2265 while (checkAttribute(p, "tmap:in:numinputs", "0")) { 2266 p = Getattr(p, "tmap:in:next"); 2267 } 2268 SwigType *pt = Getattr(p, "type"); 2269 2270 Printf(f->code, " efree(value);\n"); 2271 Printf(f->code, " if (! newobject) return; /* can't delete it! */\n"); 2272 Printf(f->code, " arg1 = (%s)SWIG_ZTS_ConvertResourceData(ptr,type_name,SWIGTYPE%s TSRMLS_CC);\n", SwigType_lstr(pt, 0), SwigType_manglestr(pt)); 2273 Printf(f->code, " if (! arg1) zend_error(E_ERROR, \"%s resource already free'd\");\n", Char(name)); 2274 2275 Setattr(n, "wrap:name", destructorname); 2276 2277 String *actioncode = emit_action(n); 2278 Append(f->code, actioncode); 2279 Delete(actioncode); 2280 2281 Append(f->code, "return;\n"); 2282 Append(f->code, "fail:\n"); 2283 Append(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n"); 2284 Printf(f->code, "}\n"); 2285 2286 Wrapper_print(f, s_wrappers); 2287 2288 return SWIG_OK; 2289 } 2290 2291 /* ------------------------------------------------------------ 2292 * memberconstantHandler() 2293 * ------------------------------------------------------------ */ 2294 2295 virtual int memberconstantHandler(Node *n) { 2296 wrapping_member_constant = Getattr(n, "sym:name"); 2297 Language::memberconstantHandler(n); 2298 wrapping_member_constant = NULL; 2299 return SWIG_OK; 2300 } 2301 2302 int classDirectorInit(Node *n) { 2303 String *declaration = Swig_director_declaration(n); 2304 Printf(f_directors_h, "%s\n", declaration); 2305 Printf(f_directors_h, "public:\n"); 2306 Delete(declaration); 2307 return Language::classDirectorInit(n); 2308 } 2309 2310 int classDirectorEnd(Node *n) { 2311 Printf(f_directors_h, "};\n"); 2312 return Language::classDirectorEnd(n); 2313 } 2314 2315 int classDirectorConstructor(Node *n) { 2316 Node *parent = Getattr(n, "parentNode"); 2317 String *decl = Getattr(n, "decl"); 2318 String *supername = Swig_class_name(parent); 2319 String *classname = NewStringEmpty(); 2320 Printf(classname, "SwigDirector_%s", supername); 2321 2322 /* insert self parameter */ 2323 Parm *p; 2324 ParmList *superparms = Getattr(n, "parms"); 2325 ParmList *parms = CopyParmList(superparms); 2326 String *type = NewString("zval"); 2327 SwigType_add_pointer(type); 2328 p = NewParm(type, NewString("self")); 2329 set_nextSibling(p, parms); 2330 parms = p; 2331 2332 if (!Getattr(n, "defaultargs")) { 2333 /* constructor */ 2334 { 2335 Wrapper *w = NewWrapper(); 2336 String *call; 2337 String *basetype = Getattr(parent, "classtype"); 2338 String *target = Swig_method_decl(0, decl, classname, parms, 0, 0); 2339 call = Swig_csuperclass_call(0, basetype, superparms); 2340 Printf(w->def, "%s::%s: %s, Swig::Director(self) {", classname, target, call); 2341 Append(w->def, "}"); 2342 Delete(target); 2343 Wrapper_print(w, f_directors); 2344 Delete(call); 2345 DelWrapper(w); 2346 } 2347 2348 /* constructor header */ 2349 { 2350 String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); 2351 Printf(f_directors_h, " %s;\n", target); 2352 Delete(target); 2353 } 2354 } 2355 return Language::classDirectorConstructor(n); 2356 } 2357 2358 int classDirectorMethod(Node *n, Node *parent, String *super) { 2359 int is_void = 0; 2360 int is_pointer = 0; 2361 String *decl; 2362 String *type; 2363 String *name; 2364 String *classname; 2365 String *c_classname = Getattr(parent, "name"); 2366 String *declaration; 2367 ParmList *l; 2368 Wrapper *w; 2369 String *tm; 2370 String *wrap_args = NewStringEmpty(); 2371 String *return_type; 2372 String *value = Getattr(n, "value"); 2373 String *storage = Getattr(n, "storage"); 2374 bool pure_virtual = false; 2375 int status = SWIG_OK; 2376 int idx; 2377 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false; 2378 2379 if (Cmp(storage, "virtual") == 0) { 2380 if (Cmp(value, "0") == 0) { 2381 pure_virtual = true; 2382 } 2383 } 2384 2385 classname = Getattr(parent, "sym:name"); 2386 type = Getattr(n, "type"); 2387 name = Getattr(n, "name"); 2388 2389 w = NewWrapper(); 2390 declaration = NewStringEmpty(); 2391 2392 /* determine if the method returns a pointer */ 2393 decl = Getattr(n, "decl"); 2394 is_pointer = SwigType_ispointer_return(decl); 2395 is_void = (Cmp(type, "void") == 0 && !is_pointer); 2396 2397 /* form complete return type */ 2398 return_type = Copy(type); 2399 { 2400 SwigType *t = Copy(decl); 2401 SwigType *f = SwigType_pop_function(t); 2402 SwigType_push(return_type, t); 2403 Delete(f); 2404 Delete(t); 2405 } 2406 2407 /* virtual method definition */ 2408 l = Getattr(n, "parms"); 2409 String *target; 2410 String *pclassname = NewStringf("SwigDirector_%s", classname); 2411 String *qualified_name = NewStringf("%s::%s", pclassname, name); 2412 SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type; 2413 target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0); 2414 Printf(w->def, "%s", target); 2415 Delete(qualified_name); 2416 Delete(target); 2417 /* header declaration */ 2418 target = Swig_method_decl(rtype, decl, name, l, 0, 1); 2419 Printf(declaration, " virtual %s", target); 2420 Delete(target); 2421 2422 // Get any exception classes in the throws typemap 2423 ParmList *throw_parm_list = 0; 2424 2425 if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { 2426 Parm *p; 2427 int gencomma = 0; 2428 2429 Append(w->def, " throw("); 2430 Append(declaration, " throw("); 2431 2432 if (throw_parm_list) 2433 Swig_typemap_attach_parms("throws", throw_parm_list, 0); 2434 for (p = throw_parm_list; p; p = nextSibling(p)) { 2435 if ((tm = Getattr(p, "tmap:throws"))) { 2436 if (gencomma++) { 2437 Append(w->def, ", "); 2438 Append(declaration, ", "); 2439 } 2440 String *str = SwigType_str(Getattr(p, "type"), 0); 2441 Append(w->def, str); 2442 Append(declaration, str); 2443 Delete(str); 2444 } 2445 } 2446 2447 Append(w->def, ")"); 2448 Append(declaration, ")"); 2449 } 2450 2451 Append(w->def, " {"); 2452 Append(declaration, ";\n"); 2453 2454 /* declare method return value 2455 * if the return value is a reference or const reference, a specialized typemap must 2456 * handle it, including declaration of c_result ($result). 2457 */ 2458 if (!is_void) { 2459 if (!(ignored_method && !pure_virtual)) { 2460 String *cres = SwigType_lstr(return_type, "c_result"); 2461 Printf(w->code, "%s;\n", cres); 2462 Delete(cres); 2463 } 2464 } 2465 2466 if (ignored_method) { 2467 if (!pure_virtual) { 2468 if (!is_void) 2469 Printf(w->code, "return "); 2470 String *super_call = Swig_method_call(super, l); 2471 Printf(w->code, "%s;\n", super_call); 2472 Delete(super_call); 2473 } else { 2474 Printf(w->code, "Swig::DirectorPureVirtualException::raise(\"Attempted to invoke pure virtual method %s::%s\");\n", SwigType_namestr(c_classname), 2475 SwigType_namestr(name)); 2476 } 2477 } else { 2478 /* attach typemaps to arguments (C/C++ -> PHP) */ 2479 String *parse_args = NewStringEmpty(); 2480 2481 /* remove the wrapper 'w' since it was producing spurious temps */ 2482 Swig_typemap_attach_parms("in", l, 0); 2483 Swig_typemap_attach_parms("directorin", l, 0); 2484 Swig_typemap_attach_parms("directorargout", l, w); 2485 2486 Parm *p; 2487 char source[256]; 2488 2489 int outputs = 0; 2490 if (!is_void) 2491 outputs++; 2492 2493 /* build argument list and type conversion string */ 2494 idx = 0; 2495 p = l; 2496 int use_parse = 0; 2497 while (p != NULL) { 2498 if (checkAttribute(p, "tmap:in:numinputs", "0")) { 2499 p = Getattr(p, "tmap:in:next"); 2500 continue; 2501 } 2502 2503 if (Getattr(p, "tmap:directorargout") != 0) 2504 outputs++; 2505 2506 String *pname = Getattr(p, "name"); 2507 String *ptype = Getattr(p, "type"); 2508 2509 if ((tm = Getattr(p, "tmap:directorin")) != 0) { 2510 String *parse = Getattr(p, "tmap:directorin:parse"); 2511 if (!parse) { 2512 sprintf(source, "obj%d", idx++); 2513 String *input = NewStringf("&%s", source); 2514 Replaceall(tm, "$input", input); 2515 Delete(input); 2516 Replaceall(tm, "$owner", "0"); 2517 Printv(wrap_args, "zval ", source, ";\n", NIL); 2518 Printf(wrap_args, "args[%d] = &%s;\n", idx - 1, source); 2519 2520 Printv(wrap_args, tm, "\n", NIL); 2521 Putc('O', parse_args); 2522 } else { 2523 use_parse = 1; 2524 Append(parse_args, parse); 2525 Replaceall(tm, "$input", pname); 2526 Replaceall(tm, "$owner", "0"); 2527 if (Len(tm) == 0) 2528 Append(tm, pname); 2529 } 2530 p = Getattr(p, "tmap:directorin:next"); 2531 continue; 2532 } else if (Cmp(ptype, "void")) { 2533 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, 2534 "Unable to use type %s as a function argument in director method %s::%s (skipping method).\n", SwigType_str(ptype, 0), 2535 SwigType_namestr(c_classname), SwigType_namestr(name)); 2536 status = SWIG_NOWRAP; 2537 break; 2538 } 2539 p = nextSibling(p); 2540 } 2541 Append(w->code, "int error;\n"); 2542 if (!idx) { 2543 Printf(w->code, "zval **args = NULL;\n", idx); 2544 } else { 2545 Printf(w->code, "zval *args[%d];\n", idx); 2546 } 2547 Append(w->code, "zval *result, funcname;\n"); 2548 Append(w->code, "MAKE_STD_ZVAL(result);\n"); 2549 Printf(w->code, "ZVAL_STRING(&funcname, (char *)\"%s\", 0);\n", name); 2550 Append(w->code, "if (!swig_self) {\n"); 2551 Append(w->code, " SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");"); 2552 Append(w->code, "}\n\n"); 2553 2554 /* wrap complex arguments to zvals */ 2555 Printv(w->code, wrap_args, NIL); 2556 2557 Append(w->code, "call_user_function(EG(function_table), (zval**)&swig_self, &funcname,\n"); 2558 Printf(w->code, " result, %d, args TSRMLS_CC);\n", idx); 2559 2560 /* exception handling */ 2561 tm = Swig_typemap_lookup("director:except", n, "result", 0); 2562 if (!tm) { 2563 tm = Getattr(n, "feature:director:except"); 2564 if (tm) 2565 tm = Copy(tm); 2566 } 2567 if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { 2568 Replaceall(tm, "$error", "error"); 2569 Printv(w->code, Str(tm), "\n", NIL); 2570 } 2571 Delete(tm); 2572 2573 /* marshal return value from PHP to C/C++ type */ 2574 2575 String *cleanup = NewStringEmpty(); 2576 String *outarg = NewStringEmpty(); 2577 2578 idx = 0; 2579 2580 /* marshal return value */ 2581 if (!is_void) { 2582 /* this seems really silly. the node's type excludes 2583 * qualifier/pointer/reference markers, which have to be retrieved 2584 * from the decl field to construct return_type. but the typemap 2585 * lookup routine uses the node's type, so we have to swap in and 2586 * out the correct type. it's not just me, similar silliness also 2587 * occurs in Language::cDeclaration(). 2588 */ 2589 Setattr(n, "type", return_type); 2590 tm = Swig_typemap_lookup("directorout", n, "result", w); 2591 Setattr(n, "type", type); 2592 if (tm != 0) { 2593 Replaceall(tm, "$input", "&result"); 2594 char temp[24]; 2595 sprintf(temp, "%d", idx); 2596 Replaceall(tm, "$argnum", temp); 2597 2598 /* TODO check this */ 2599 if (Getattr(n, "wrap:disown")) { 2600 Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN"); 2601 } else { 2602 Replaceall(tm, "$disown", "0"); 2603 } 2604 Replaceall(tm, "$result", "c_result"); 2605 Printv(w->code, tm, "\n", NIL); 2606 Delete(tm); 2607 } else { 2608 Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, 2609 "Unable to use return type %s in director method %s::%s (skipping method).\n", SwigType_str(return_type, 0), SwigType_namestr(c_classname), 2610 SwigType_namestr(name)); 2611 status = SWIG_ERROR; 2612 } 2613 } 2614 2615 /* marshal outputs */ 2616 for (p = l; p;) { 2617 if ((tm = Getattr(p, "tmap:directorargout")) != 0) { 2618 Replaceall(tm, "$input", "result"); 2619 Replaceall(tm, "$result", Getattr(p, "name")); 2620 Printv(w->code, tm, "\n", NIL); 2621 p = Getattr(p, "tmap:directorargout:next"); 2622 } else { 2623 p = nextSibling(p); 2624 } 2625 } 2626 2627 Append(w->code, "FREE_ZVAL(result);\n"); 2628 2629 Delete(parse_args); 2630 Delete(cleanup); 2631 Delete(outarg); 2632 } 2633 2634 if (!is_void) { 2635 if (!(ignored_method && !pure_virtual)) { 2636 String *rettype = SwigType_str(return_type, 0); 2637 if (!SwigType_isreference(return_type)) { 2638 Printf(w->code, "return (%s) c_result;\n", rettype); 2639 } else { 2640 Printf(w->code, "return (%s) *c_result;\n", rettype); 2641 } 2642 Delete(rettype); 2643 } 2644 } else { 2645 Append(w->code, "return;\n"); 2646 } 2647 2648 Append(w->code, "fail:\n"); 2649 Append(w->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n"); 2650 Append(w->code, "}\n"); 2651 2652 // We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method 2653 String *inline_extra_method = NewStringEmpty(); 2654 if (dirprot_mode() && !is_public(n) && !pure_virtual) { 2655 Printv(inline_extra_method, declaration, NIL); 2656 String *extra_method_name = NewStringf("%sSwigPublic", name); 2657 Replaceall(inline_extra_method, name, extra_method_name); 2658 Replaceall(inline_extra_method, ";\n", " {\n "); 2659 if (!is_void) 2660 Printf(inline_extra_method, "return "); 2661 String *methodcall = Swig_method_call(super, l); 2662 Printv(inline_extra_method, methodcall, ";\n }\n", NIL); 2663 Delete(methodcall); 2664 Delete(extra_method_name); 2665 } 2666 2667 /* emit the director method */ 2668 if (status == SWIG_OK) { 2669 if (!Getattr(n, "defaultargs")) { 2670 Wrapper_print(w, f_directors); 2671 Printv(f_directors_h, declaration, NIL); 2672 Printv(f_directors_h, inline_extra_method, NIL); 2673 } 2674 } 2675 2676 /* clean up */ 2677 Delete(wrap_args); 2678 Delete(return_type); 2679 Delete(pclassname); 2680 DelWrapper(w); 2681 return status; 2682 } 2683 2684 int classDirectorDisown(Node *) { 2685 return SWIG_OK; 2686 } 2687}; /* class PHP */ 2688 2689static PHP *maininstance = 0; 2690 2691// We use this function to be able to write out zend_register_list_destructor_ex 2692// lines for most things in the type table 2693// NOTE: it's a function NOT A PHP::METHOD 2694extern "C" void typetrace(SwigType *ty, String *mangled, String *clientdata) { 2695 Node *class_node; 2696 if (!zend_types) { 2697 zend_types = NewHash(); 2698 } 2699 // we want to know if the type which reduced to this has a constructor 2700 if ((class_node = maininstance->classLookup(ty))) { 2701 if (!Getattr(zend_types, mangled)) { 2702 // OK it may have been set before by a different SwigType but it would 2703 // have had the same underlying class node I think 2704 // - it is certainly required not to have different originating class 2705 // nodes for the same SwigType 2706 Setattr(zend_types, mangled, class_node); 2707 } 2708 } else { // a non-class pointer 2709 Setattr(zend_types, mangled, NOTCLASS); 2710 } 2711 if (r_prevtracefunc) 2712 (*r_prevtracefunc) (ty, mangled, (String *) clientdata); 2713} 2714 2715/* ----------------------------------------------------------------------------- 2716 * new_swig_php() - Instantiate module 2717 * ----------------------------------------------------------------------------- */ 2718 2719static Language *new_swig_php() { 2720 maininstance = new PHP; 2721 if (!r_prevtracefunc) { 2722 r_prevtracefunc = SwigType_remember_trace(typetrace); 2723 } else { 2724 Printf(stderr, "php Typetrace vector already saved!\n"); 2725 assert(0); 2726 } 2727 return maininstance; 2728} 2729 2730extern "C" Language *swig_php4(void) { 2731 Printf(stderr, "*** -php4 is no longer supported.\n" 2732 "*** Either upgrade to PHP5 or use SWIG 1.3.36 or earlier.\n"); 2733 SWIG_exit(EXIT_FAILURE); 2734 return NULL; // To avoid compiler warnings. 2735} 2736 2737extern "C" Language *swig_php(void) { 2738 return new_swig_php(); 2739} 2740