root/Zend/zend_API.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_get_parameters
  2. _zend_get_parameters_array
  3. zend_get_parameters_ex
  4. _zend_get_parameters_array_ex
  5. zend_copy_parameters_array
  6. zend_wrong_param_count
  7. zend_get_type_by_const
  8. zend_zval_type_name
  9. zend_get_class_entry
  10. zend_get_object_classname
  11. parse_arg_object_to_string
  12. zend_parse_arg_impl
  13. zend_parse_arg
  14. zend_parse_parameter
  15. zend_parse_va_args
  16. zend_parse_parameters_ex
  17. zend_parse_parameters
  18. zend_parse_method_parameters
  19. zend_parse_method_parameters_ex
  20. _array_init
  21. zend_merge_property
  22. zend_merge_properties
  23. zval_update_class_constant
  24. zend_update_class_constants
  25. object_properties_init
  26. _object_and_properties_init
  27. _object_init_ex
  28. _object_init
  29. add_assoc_function
  30. add_assoc_long_ex
  31. add_assoc_null_ex
  32. add_assoc_bool_ex
  33. add_assoc_resource_ex
  34. add_assoc_double_ex
  35. add_assoc_string_ex
  36. add_assoc_stringl_ex
  37. add_assoc_zval_ex
  38. add_index_long
  39. add_index_null
  40. add_index_bool
  41. add_index_resource
  42. add_index_double
  43. add_index_string
  44. add_index_stringl
  45. add_index_zval
  46. add_next_index_long
  47. add_next_index_null
  48. add_next_index_bool
  49. add_next_index_resource
  50. add_next_index_double
  51. add_next_index_string
  52. add_next_index_stringl
  53. add_next_index_zval
  54. add_get_assoc_string_ex
  55. add_get_assoc_stringl_ex
  56. add_get_index_long
  57. add_get_index_double
  58. add_get_index_string
  59. add_get_index_stringl
  60. array_set_zval_key
  61. add_property_long_ex
  62. add_property_bool_ex
  63. add_property_null_ex
  64. add_property_resource_ex
  65. add_property_double_ex
  66. add_property_string_ex
  67. add_property_stringl_ex
  68. add_property_zval_ex
  69. zend_startup_module_ex
  70. zend_sort_modules
  71. zend_collect_module_handlers
  72. zend_startup_modules
  73. zend_destroy_modules
  74. zend_register_module_ex
  75. zend_register_internal_module
  76. zend_check_magic_method_implementation
  77. zend_register_functions
  78. zend_unregister_functions
  79. zend_startup_module
  80. zend_get_module_started
  81. clean_module_class
  82. clean_module_classes
  83. module_destructor
  84. zend_activate_modules
  85. module_registry_cleanup
  86. zend_deactivate_modules
  87. zend_cleanup_internal_classes
  88. module_registry_unload_temp
  89. exec_done_cb
  90. zend_post_deactivate_modules
  91. zend_next_free_module
  92. do_register_internal_class
  93. zend_register_internal_class_ex
  94. zend_class_implements
  95. zend_register_internal_class
  96. zend_register_internal_interface
  97. zend_register_class_alias_ex
  98. zend_set_hash_symbol
  99. ZEND_FUNCTION
  100. zend_disable_function
  101. display_disabled_class
  102. zend_disable_class
  103. zend_is_callable_check_class
  104. zend_is_callable_check_func
  105. zend_is_callable_ex
  106. zend_is_callable
  107. zend_make_callable
  108. zend_fcall_info_init
  109. zend_fcall_info_args_clear
  110. zend_fcall_info_args_save
  111. zend_fcall_info_args_restore
  112. zend_fcall_info_args
  113. zend_fcall_info_argp
  114. zend_fcall_info_argv
  115. zend_fcall_info_argn
  116. zend_fcall_info_call
  117. zend_get_module_version
  118. zend_declare_property_ex
  119. zend_declare_property
  120. zend_declare_property_null
  121. zend_declare_property_bool
  122. zend_declare_property_long
  123. zend_declare_property_double
  124. zend_declare_property_string
  125. zend_declare_property_stringl
  126. zend_declare_class_constant
  127. zend_declare_class_constant_null
  128. zend_declare_class_constant_long
  129. zend_declare_class_constant_bool
  130. zend_declare_class_constant_double
  131. zend_declare_class_constant_stringl
  132. zend_declare_class_constant_string
  133. zend_update_property
  134. zend_update_property_null
  135. zend_update_property_bool
  136. zend_update_property_long
  137. zend_update_property_double
  138. zend_update_property_string
  139. zend_update_property_stringl
  140. zend_update_static_property
  141. zend_update_static_property_null
  142. zend_update_static_property_bool
  143. zend_update_static_property_long
  144. zend_update_static_property_double
  145. zend_update_static_property_string
  146. zend_update_static_property_stringl
  147. zend_read_property
  148. zend_read_static_property
  149. zend_save_error_handling
  150. zend_replace_error_handling
  151. zend_restore_error_handling
  152. zend_find_alias_name
  153. zend_resolve_method_name

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend Engine                                                          |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 2.00 of the Zend license,     |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.zend.com/license/2_00.txt.                                |
  11    | If you did not receive a copy of the Zend license and are unable to  |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@zend.com so we can mail you a copy immediately.              |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    |          Andrei Zmievski <andrei@php.net>                            |
  18    +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id$ */
  22 
  23 #include "zend.h"
  24 #include "zend_execute.h"
  25 #include "zend_API.h"
  26 #include "zend_modules.h"
  27 #include "zend_constants.h"
  28 #include "zend_exceptions.h"
  29 #include "zend_closures.h"
  30 
  31 #ifdef HAVE_STDARG_H
  32 #include <stdarg.h>
  33 #endif
  34 
  35 /* these variables are true statics/globals, and have to be mutex'ed on every access */
  36 ZEND_API HashTable module_registry;
  37 
  38 static zend_module_entry **module_request_startup_handlers;
  39 static zend_module_entry **module_request_shutdown_handlers;
  40 static zend_module_entry **module_post_deactivate_handlers;
  41 
  42 static zend_class_entry  **class_cleanup_handlers;
  43 
  44 /* this function doesn't check for too many parameters */
  45 ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
  46 {
  47         void **p;
  48         int arg_count;
  49         va_list ptr;
  50         zval **param, *param_ptr;
  51         TSRMLS_FETCH();
  52 
  53         p = zend_vm_stack_top(TSRMLS_C) - 1;
  54         arg_count = (int)(zend_uintptr_t) *p;
  55 
  56         if (param_count>arg_count) {
  57                 return FAILURE;
  58         }
  59 
  60         va_start(ptr, param_count);
  61 
  62         while (param_count-->0) {
  63                 param = va_arg(ptr, zval **);
  64                 param_ptr = *(p-arg_count);
  65                 if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
  66                         zval *new_tmp;
  67 
  68                         ALLOC_ZVAL(new_tmp);
  69                         *new_tmp = *param_ptr;
  70                         zval_copy_ctor(new_tmp);
  71                         INIT_PZVAL(new_tmp);
  72                         param_ptr = new_tmp;
  73                         Z_DELREF_P((zval *) *(p-arg_count));
  74                         *(p-arg_count) = param_ptr;
  75                 }
  76                 *param = param_ptr;
  77                 arg_count--;
  78         }
  79         va_end(ptr);
  80 
  81         return SUCCESS;
  82 }
  83 /* }}} */
  84 
  85 ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */
  86 {
  87         void **p;
  88         int arg_count;
  89         zval *param_ptr;
  90 
  91         p = zend_vm_stack_top(TSRMLS_C) - 1;
  92         arg_count = (int)(zend_uintptr_t) *p;
  93 
  94         if (param_count>arg_count) {
  95                 return FAILURE;
  96         }
  97 
  98         while (param_count-->0) {
  99                 param_ptr = *(p-arg_count);
 100                 if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
 101                         zval *new_tmp;
 102 
 103                         ALLOC_ZVAL(new_tmp);
 104                         *new_tmp = *param_ptr;
 105                         zval_copy_ctor(new_tmp);
 106                         INIT_PZVAL(new_tmp);
 107                         param_ptr = new_tmp;
 108                         Z_DELREF_P((zval *) *(p-arg_count));
 109                         *(p-arg_count) = param_ptr;
 110                 }
 111                 *(argument_array++) = param_ptr;
 112                 arg_count--;
 113         }
 114 
 115         return SUCCESS;
 116 }
 117 /* }}} */
 118 
 119 /* Zend-optimized Extended functions */
 120 /* this function doesn't check for too many parameters */
 121 ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
 122 {
 123         void **p;
 124         int arg_count;
 125         va_list ptr;
 126         zval ***param;
 127         TSRMLS_FETCH();
 128 
 129         p = zend_vm_stack_top(TSRMLS_C) - 1;
 130         arg_count = (int)(zend_uintptr_t) *p;
 131 
 132         if (param_count>arg_count) {
 133                 return FAILURE;
 134         }
 135 
 136         va_start(ptr, param_count);
 137         while (param_count-->0) {
 138                 param = va_arg(ptr, zval ***);
 139                 *param = (zval **) p-(arg_count--);
 140         }
 141         va_end(ptr);
 142 
 143         return SUCCESS;
 144 }
 145 /* }}} */
 146 
 147 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */
 148 {
 149         void **p;
 150         int arg_count;
 151 
 152         p = zend_vm_stack_top(TSRMLS_C) - 1;
 153         arg_count = (int)(zend_uintptr_t) *p;
 154 
 155         if (param_count>arg_count) {
 156                 return FAILURE;
 157         }
 158 
 159         while (param_count-->0) {
 160                 zval **value = (zval**)(p-arg_count);
 161 
 162                 *(argument_array++) = value;
 163                 arg_count--;
 164         }
 165 
 166         return SUCCESS;
 167 }
 168 /* }}} */
 169 
 170 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
 171 {
 172         void **p;
 173         int arg_count;
 174 
 175         p = zend_vm_stack_top(TSRMLS_C) - 1;
 176         arg_count = (int)(zend_uintptr_t) *p;
 177 
 178         if (param_count>arg_count) {
 179                 return FAILURE;
 180         }
 181 
 182         while (param_count-->0) {
 183                 zval **param = (zval **) p-(arg_count--);
 184                 zval_add_ref(param);
 185                 add_next_index_zval(argument_array, *param);
 186         }
 187 
 188         return SUCCESS;
 189 }
 190 /* }}} */
 191 
 192 ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */
 193 {
 194         const char *space;
 195         const char *class_name = get_active_class_name(&space TSRMLS_CC);
 196 
 197         zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
 198 }
 199 /* }}} */
 200 
 201 /* Argument parsing API -- andrei */
 202 ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
 203 {
 204         switch(type) {
 205                 case IS_BOOL:
 206                         return "boolean";
 207                 case IS_LONG:
 208                         return "integer";
 209                 case IS_DOUBLE:
 210                         return "double";
 211                 case IS_STRING:
 212                         return "string";
 213                 case IS_OBJECT:
 214                         return "object";
 215                 case IS_RESOURCE:
 216                         return "resource";
 217                 case IS_NULL:
 218                         return "null";
 219                 case IS_CALLABLE:
 220                         return "callable";
 221                 case IS_ARRAY:
 222                         return "array";
 223                 default:
 224                         return "unknown";
 225         }
 226 }
 227 /* }}} */
 228 
 229 ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
 230 {
 231         return zend_get_type_by_const(Z_TYPE_P(arg));
 232 }
 233 /* }}} */
 234 
 235 ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) /* {{{ */
 236 {
 237         if (Z_OBJ_HT_P(zobject)->get_class_entry) {
 238                 return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC);
 239         } else {
 240                 zend_error(E_ERROR, "Class entry requested for an object without PHP class");
 241                 return NULL;
 242         }
 243 }
 244 /* }}} */
 245 
 246 /* returns 1 if you need to copy result, 0 if it's already a copy */
 247 ZEND_API int zend_get_object_classname(const zval *object, const char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */
 248 {
 249         if (Z_OBJ_HT_P(object)->get_class_name == NULL ||
 250                 Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) {
 251                 zend_class_entry *ce = Z_OBJCE_P(object);
 252 
 253                 *class_name = ce->name;
 254                 *class_name_len = ce->name_length;
 255                 return 1;
 256         }
 257         return 0;
 258 }
 259 /* }}} */
 260 
 261 static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TSRMLS_DC) /* {{{ */
 262 {
 263         if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
 264                 zval *obj;
 265                 MAKE_STD_ZVAL(obj);
 266                 if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, type TSRMLS_CC) == SUCCESS) {
 267                         zval_ptr_dtor(arg);
 268                         *arg = obj;
 269                         *pl = Z_STRLEN_PP(arg);
 270                         *p = Z_STRVAL_PP(arg);
 271                         return SUCCESS;
 272                 }
 273                 efree(obj);
 274         }
 275         /* Standard PHP objects */
 276         if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
 277                 SEPARATE_ZVAL_IF_NOT_REF(arg);
 278                 if (zend_std_cast_object_tostring(*arg, *arg, type TSRMLS_CC) == SUCCESS) {
 279                         *pl = Z_STRLEN_PP(arg);
 280                         *p = Z_STRVAL_PP(arg);
 281                         return SUCCESS;
 282                 }
 283         }
 284         if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
 285                 int use_copy;
 286                 zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
 287                 Z_ADDREF_P(z);
 288                 if(Z_TYPE_P(z) != IS_OBJECT) {
 289                         zval_dtor(*arg);
 290                         Z_TYPE_P(*arg) = IS_NULL;
 291                         zend_make_printable_zval(z, *arg, &use_copy);
 292                         if (!use_copy) {
 293                                 ZVAL_ZVAL(*arg, z, 1, 1);
 294                         }
 295                         *pl = Z_STRLEN_PP(arg);
 296                         *p = Z_STRVAL_PP(arg);
 297                         return SUCCESS;
 298                 }
 299                 zval_ptr_dtor(&z);
 300         }
 301         return FAILURE;
 302 }
 303 /* }}} */
 304 
 305 static const char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, const char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
 306 {
 307         const char *spec_walk = *spec;
 308         char c = *spec_walk++;
 309         int check_null = 0;
 310 
 311         /* scan through modifiers */
 312         while (1) {
 313                 if (*spec_walk == '/') {
 314                         SEPARATE_ZVAL_IF_NOT_REF(arg);
 315                 } else if (*spec_walk == '!') {
 316                         check_null = 1;
 317                 } else {
 318                         break;
 319                 }
 320                 spec_walk++;
 321         }
 322 
 323         switch (c) {
 324                 case 'l':
 325                 case 'L':
 326                         {
 327                                 long *p = va_arg(*va, long *);
 328 
 329                                 if (check_null) {
 330                                         zend_bool *p = va_arg(*va, zend_bool *);
 331                                         *p = (Z_TYPE_PP(arg) == IS_NULL);
 332                                 }
 333 
 334                                 switch (Z_TYPE_PP(arg)) {
 335                                         case IS_STRING:
 336                                                 {
 337                                                         double d;
 338                                                         int type;
 339 
 340                                                         if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) {
 341                                                                 return "long";
 342                                                         } else if (type == IS_DOUBLE) {
 343                                                                 if (c == 'L') {
 344                                                                         if (d > LONG_MAX) {
 345                                                                                 *p = LONG_MAX;
 346                                                                                 break;
 347                                                                         } else if (d < LONG_MIN) {
 348                                                                                 *p = LONG_MIN;
 349                                                                                 break;
 350                                                                         }
 351                                                                 }
 352 
 353                                                                 *p = zend_dval_to_lval(d);
 354                                                         }
 355                                                 }
 356                                                 break;
 357 
 358                                         case IS_DOUBLE:
 359                                                 if (c == 'L') {
 360                                                         if (Z_DVAL_PP(arg) > LONG_MAX) {
 361                                                                 *p = LONG_MAX;
 362                                                                 break;
 363                                                         } else if (Z_DVAL_PP(arg) < LONG_MIN) {
 364                                                                 *p = LONG_MIN;
 365                                                                 break;
 366                                                         }
 367                                                 }
 368                                         case IS_NULL:
 369                                         case IS_LONG:
 370                                         case IS_BOOL:
 371                                                 convert_to_long_ex(arg);
 372                                                 *p = Z_LVAL_PP(arg);
 373                                                 break;
 374 
 375                                         case IS_ARRAY:
 376                                         case IS_OBJECT:
 377                                         case IS_RESOURCE:
 378                                         default:
 379                                                 return "long";
 380                                 }
 381                         }
 382                         break;
 383 
 384                 case 'd':
 385                         {
 386                                 double *p = va_arg(*va, double *);
 387 
 388                                 if (check_null) {
 389                                         zend_bool *p = va_arg(*va, zend_bool *);
 390                                         *p = (Z_TYPE_PP(arg) == IS_NULL);
 391                                 }
 392 
 393                                 switch (Z_TYPE_PP(arg)) {
 394                                         case IS_STRING:
 395                                                 {
 396                                                         long l;
 397                                                         int type;
 398 
 399                                                         if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) {
 400                                                                 return "double";
 401                                                         } else if (type == IS_LONG) {
 402                                                                 *p = (double) l;
 403                                                         }
 404                                                 }
 405                                                 break;
 406 
 407                                         case IS_NULL:
 408                                         case IS_LONG:
 409                                         case IS_DOUBLE:
 410                                         case IS_BOOL:
 411                                                 convert_to_double_ex(arg);
 412                                                 *p = Z_DVAL_PP(arg);
 413                                                 break;
 414 
 415                                         case IS_ARRAY:
 416                                         case IS_OBJECT:
 417                                         case IS_RESOURCE:
 418                                         default:
 419                                                 return "double";
 420                                 }
 421                         }
 422                         break;
 423 
 424                 case 'p':
 425                 case 's':
 426                         {
 427                                 char **p = va_arg(*va, char **);
 428                                 int *pl = va_arg(*va, int *);
 429                                 switch (Z_TYPE_PP(arg)) {
 430                                         case IS_NULL:
 431                                                 if (check_null) {
 432                                                         *p = NULL;
 433                                                         *pl = 0;
 434                                                         break;
 435                                                 }
 436                                                 /* break omitted intentionally */
 437 
 438                                         case IS_STRING:
 439                                         case IS_LONG:
 440                                         case IS_DOUBLE:
 441                                         case IS_BOOL:
 442                                                 convert_to_string_ex(arg);
 443                                                 if (UNEXPECTED(Z_ISREF_PP(arg) != 0)) {
 444                                                         /* it's dangerous to return pointers to string
 445                                                            buffer of referenced variable, because it can
 446                                                            be clobbered throug magic callbacks */
 447                                                         SEPARATE_ZVAL(arg);
 448                                                 }
 449                                                 *p = Z_STRVAL_PP(arg);
 450                                                 *pl = Z_STRLEN_PP(arg);
 451                                                 if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
 452                                                         return "a valid path";
 453                                                 }
 454                                                 break;
 455 
 456                                         case IS_OBJECT:
 457                                                 if (parse_arg_object_to_string(arg, p, pl, IS_STRING TSRMLS_CC) == SUCCESS) {
 458                                                         if (c == 'p' && CHECK_ZVAL_NULL_PATH(*arg)) {
 459                                                                 return "a valid path";
 460                                                         }
 461                                                         break;
 462                                                 }
 463 
 464                                         case IS_ARRAY:
 465                                         case IS_RESOURCE:
 466                                         default:
 467                                                 return c == 's' ? "string" : "a valid path";
 468                                 }
 469                         }
 470                         break;
 471 
 472                 case 'b':
 473                         {
 474                                 zend_bool *p = va_arg(*va, zend_bool *);
 475 
 476                                 if (check_null) {
 477                                         zend_bool *p = va_arg(*va, zend_bool *);
 478                                         *p = (Z_TYPE_PP(arg) == IS_NULL);
 479                                 }
 480 
 481                                 switch (Z_TYPE_PP(arg)) {
 482                                         case IS_NULL:
 483                                         case IS_STRING:
 484                                         case IS_LONG:
 485                                         case IS_DOUBLE:
 486                                         case IS_BOOL:
 487                                                 convert_to_boolean_ex(arg);
 488                                                 *p = Z_BVAL_PP(arg);
 489                                                 break;
 490 
 491                                         case IS_ARRAY:
 492                                         case IS_OBJECT:
 493                                         case IS_RESOURCE:
 494                                         default:
 495                                                 return "boolean";
 496                                 }
 497                         }
 498                         break;
 499 
 500                 case 'r':
 501                         {
 502                                 zval **p = va_arg(*va, zval **);
 503                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 504                                         *p = NULL;
 505                                         break;
 506                                 }
 507                                 if (Z_TYPE_PP(arg) == IS_RESOURCE) {
 508                                         *p = *arg;
 509                                 } else {
 510                                         return "resource";
 511                                 }
 512                         }
 513                         break;
 514                 case 'A':
 515                 case 'a':
 516                         {
 517                                 zval **p = va_arg(*va, zval **);
 518                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 519                                         *p = NULL;
 520                                         break;
 521                                 }
 522                                 if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) {
 523                                         *p = *arg;
 524                                 } else {
 525                                         return "array";
 526                                 }
 527                         }
 528                         break;
 529                 case 'H':
 530                 case 'h':
 531                         {
 532                                 HashTable **p = va_arg(*va, HashTable **);
 533                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 534                                         *p = NULL;
 535                                         break;
 536                                 }
 537                                 if (Z_TYPE_PP(arg) == IS_ARRAY) {
 538                                         *p = Z_ARRVAL_PP(arg);
 539                                 } else if(c == 'H' && Z_TYPE_PP(arg) == IS_OBJECT) {
 540                                         *p = HASH_OF(*arg);
 541                                         if(*p == NULL) {
 542                                                 return "array";
 543                                         }
 544                                 } else {
 545                                         return "array";
 546                                 }
 547                         }
 548                         break;
 549 
 550                 case 'o':
 551                         {
 552                                 zval **p = va_arg(*va, zval **);
 553                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 554                                         *p = NULL;
 555                                         break;
 556                                 }
 557                                 if (Z_TYPE_PP(arg) == IS_OBJECT) {
 558                                         *p = *arg;
 559                                 } else {
 560                                         return "object";
 561                                 }
 562                         }
 563                         break;
 564 
 565                 case 'O':
 566                         {
 567                                 zval **p = va_arg(*va, zval **);
 568                                 zend_class_entry *ce = va_arg(*va, zend_class_entry *);
 569 
 570                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 571                                         *p = NULL;
 572                                         break;
 573                                 }
 574                                 if (Z_TYPE_PP(arg) == IS_OBJECT &&
 575                                                 (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
 576                                         *p = *arg;
 577                                 } else {
 578                                         if (ce) {
 579                                                 return ce->name;
 580                                         } else {
 581                                                 return "object";
 582                                         }
 583                                 }
 584                         }
 585                         break;
 586 
 587                 case 'C':
 588                         {
 589                                 zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
 590                                 zend_class_entry *ce_base = *pce;
 591 
 592                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 593                                         *pce = NULL;
 594                                         break;
 595                                 }
 596                                 convert_to_string_ex(arg);
 597                                 if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) {
 598                                         *pce = NULL;
 599                                 } else {
 600                                         *pce = *lookup;
 601                                 }
 602                                 if (ce_base) {
 603                                         if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
 604                                                 zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
 605                                                         ce_base->name, Z_STRVAL_PP(arg));
 606                                                 *pce = NULL;
 607                                                 return "";
 608                                         }
 609                                 }
 610                                 if (!*pce) {
 611                                         zend_spprintf(error, 0, "to be a valid class name, '%s' given",
 612                                                 Z_STRVAL_PP(arg));
 613                                         return "";
 614                                 }
 615                                 break;
 616 
 617                         }
 618                         break;
 619 
 620                 case 'f':
 621                         {
 622                                 zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
 623                                 zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
 624                                 char *is_callable_error = NULL;
 625 
 626                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 627                                         fci->size = 0;
 628                                         fcc->initialized = 0;
 629                                         break;
 630                                 }
 631 
 632                                 if (zend_fcall_info_init(*arg, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) {
 633                                         if (is_callable_error) {
 634                                                 *severity = E_STRICT;
 635                                                 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
 636                                                 efree(is_callable_error);
 637                                                 *spec = spec_walk;
 638                                                 return "";
 639                                         }
 640                                         break;
 641                                 } else {
 642                                         if (is_callable_error) {
 643                                                 *severity = E_WARNING;
 644                                                 zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
 645                                                 efree(is_callable_error);
 646                                                 return "";
 647                                         } else {
 648                                                 return "valid callback";
 649                                         }
 650                                 }
 651                         }
 652 
 653                 case 'z':
 654                         {
 655                                 zval **p = va_arg(*va, zval **);
 656                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 657                                         *p = NULL;
 658                                 } else {
 659                                         *p = *arg;
 660                                 }
 661                         }
 662                         break;
 663 
 664                 case 'Z':
 665                         {
 666                                 zval ***p = va_arg(*va, zval ***);
 667                                 if (check_null && Z_TYPE_PP(arg) == IS_NULL) {
 668                                         *p = NULL;
 669                                 } else {
 670                                         *p = arg;
 671                                 }
 672                         }
 673                         break;
 674 
 675                 default:
 676                         return "unknown";
 677         }
 678 
 679         *spec = spec_walk;
 680 
 681         return NULL;
 682 }
 683 /* }}} */
 684 
 685 static int zend_parse_arg(int arg_num, zval **arg, va_list *va, const char **spec, int quiet TSRMLS_DC) /* {{{ */
 686 {
 687         const char *expected_type = NULL;
 688         char *error = NULL;
 689         int severity = E_WARNING;
 690 
 691         expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
 692         if (expected_type) {
 693                 if (!quiet && (*expected_type || error)) {
 694                         const char *space;
 695                         const char *class_name = get_active_class_name(&space TSRMLS_CC);
 696 
 697                         if (error) {
 698                                 zend_error(severity, "%s%s%s() expects parameter %d %s",
 699                                                 class_name, space, get_active_function_name(TSRMLS_C), arg_num, error);
 700                                 efree(error);
 701                         } else {
 702                                 zend_error(severity, "%s%s%s() expects parameter %d to be %s, %s given",
 703                                                 class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
 704                                                 zend_zval_type_name(*arg));
 705                         }
 706                 }
 707                 if (severity != E_STRICT) {
 708                         return FAILURE;
 709                 }
 710         }
 711 
 712         return SUCCESS;
 713 }
 714 /* }}} */
 715 
 716 ZEND_API int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)
 717 {
 718         va_list va;
 719         int ret;
 720         int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
 721 
 722         va_start(va, spec);
 723         ret = zend_parse_arg(arg_num, arg, &va, &spec, quiet TSRMLS_CC);
 724         va_end(va);
 725 
 726         return ret;
 727 }
 728 
 729 static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
 730 {
 731         const  char *spec_walk;
 732         int c, i;
 733         int min_num_args = -1;
 734         int max_num_args = 0;
 735         int post_varargs = 0;
 736         zval **arg;
 737         int arg_count;
 738         int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
 739         zend_bool have_varargs = 0;
 740         zval ****varargs = NULL;
 741         int *n_varargs = NULL;
 742 
 743         for (spec_walk = type_spec; *spec_walk; spec_walk++) {
 744                 c = *spec_walk;
 745                 switch (c) {
 746                         case 'l': case 'd':
 747                         case 's': case 'b':
 748                         case 'r': case 'a':
 749                         case 'o': case 'O':
 750                         case 'z': case 'Z':
 751                         case 'C': case 'h':
 752                         case 'f': case 'A':
 753                         case 'H': case 'p':
 754                                 max_num_args++;
 755                                 break;
 756 
 757                         case '|':
 758                                 min_num_args = max_num_args;
 759                                 break;
 760 
 761                         case '/':
 762                         case '!':
 763                                 /* Pass */
 764                                 break;
 765 
 766                         case '*':
 767                         case '+':
 768                                 if (have_varargs) {
 769                                         if (!quiet) {
 770                                                 zend_function *active_function = EG(current_execute_data)->function_state.function;
 771                                                 const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 772                                                 zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
 773                                                                 class_name,
 774                                                                 class_name[0] ? "::" : "",
 775                                                                 active_function->common.function_name);
 776                                         }
 777                                         return FAILURE;
 778                                 }
 779                                 have_varargs = 1;
 780                                 /* we expect at least one parameter in varargs */
 781                                 if (c == '+') {
 782                                         max_num_args++;
 783                                 }
 784                                 /* mark the beginning of varargs */
 785                                 post_varargs = max_num_args;
 786                                 break;
 787 
 788                         default:
 789                                 if (!quiet) {
 790                                         zend_function *active_function = EG(current_execute_data)->function_state.function;
 791                                         const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 792                                         zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
 793                                                         class_name,
 794                                                         class_name[0] ? "::" : "",
 795                                                         active_function->common.function_name);
 796                                 }
 797                                 return FAILURE;
 798                 }
 799         }
 800 
 801         if (min_num_args < 0) {
 802                 min_num_args = max_num_args;
 803         }
 804 
 805         if (have_varargs) {
 806                 /* calculate how many required args are at the end of the specifier list */
 807                 post_varargs = max_num_args - post_varargs;
 808                 max_num_args = -1;
 809         }
 810 
 811         if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
 812                 if (!quiet) {
 813                         zend_function *active_function = EG(current_execute_data)->function_state.function;
 814                         const char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
 815                         zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
 816                                         class_name,
 817                                         class_name[0] ? "::" : "",
 818                                         active_function->common.function_name,
 819                                         min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
 820                                         num_args < min_num_args ? min_num_args : max_num_args,
 821                                         (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
 822                                         num_args);
 823                 }
 824                 return FAILURE;
 825         }
 826 
 827         arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
 828 
 829         if (num_args > arg_count) {
 830                 zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
 831                         get_active_function_name(TSRMLS_C));
 832                 return FAILURE;
 833         }
 834 
 835         i = 0;
 836         while (num_args-- > 0) {
 837                 if (*type_spec == '|') {
 838                         type_spec++;
 839                 }
 840 
 841                 if (*type_spec == '*' || *type_spec == '+') {
 842                         int num_varargs = num_args + 1 - post_varargs;
 843 
 844                         /* eat up the passed in storage even if it won't be filled in with varargs */
 845                         varargs = va_arg(*va, zval ****);
 846                         n_varargs = va_arg(*va, int *);
 847                         type_spec++;
 848 
 849                         if (num_varargs > 0) {
 850                                 int iv = 0;
 851                                 zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
 852 
 853                                 *n_varargs = num_varargs;
 854 
 855                                 /* allocate space for array and store args */
 856                                 *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0);
 857                                 while (num_varargs-- > 0) {
 858                                         (*varargs)[iv++] = p++;
 859                                 }
 860 
 861                                 /* adjust how many args we have left and restart loop */
 862                                 num_args = num_args + 1 - iv;
 863                                 i += iv;
 864                                 continue;
 865                         } else {
 866                                 *varargs = NULL;
 867                                 *n_varargs = 0;
 868                         }
 869                 }
 870 
 871                 arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i));
 872 
 873                 if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
 874                         /* clean up varargs array if it was used */
 875                         if (varargs && *varargs) {
 876                                 efree(*varargs);
 877                                 *varargs = NULL;
 878                         }
 879                         return FAILURE;
 880                 }
 881                 i++;
 882         }
 883 
 884         return SUCCESS;
 885 }
 886 /* }}} */
 887 
 888 #define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \
 889         int __num_args = (num_args); \
 890         \
 891         if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
 892                 const char *__space; \
 893                 const char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
 894                 zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
 895                         __class_name, __space, \
 896                         get_active_function_name(TSRMLS_C), __num_args); \
 897                 return FAILURE; \
 898         }\
 899 }
 900 
 901 ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, const char *type_spec, ...) /* {{{ */
 902 {
 903         va_list va;
 904         int retval;
 905 
 906         RETURN_IF_ZERO_ARGS(num_args, type_spec, flags & ZEND_PARSE_PARAMS_QUIET);
 907 
 908         va_start(va, type_spec);
 909         retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
 910         va_end(va);
 911 
 912         return retval;
 913 }
 914 /* }}} */
 915 
 916 ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...) /* {{{ */
 917 {
 918         va_list va;
 919         int retval;
 920 
 921         RETURN_IF_ZERO_ARGS(num_args, type_spec, 0);
 922 
 923         va_start(va, type_spec);
 924         retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
 925         va_end(va);
 926 
 927         return retval;
 928 }
 929 /* }}} */
 930 
 931 ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
 932 {
 933         va_list va;
 934         int retval;
 935         const char *p = type_spec;
 936         zval **object;
 937         zend_class_entry *ce;
 938 
 939         if (!this_ptr) {
 940                 RETURN_IF_ZERO_ARGS(num_args, p, 0);
 941 
 942                 va_start(va, type_spec);
 943                 retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
 944                 va_end(va);
 945         } else {
 946                 p++;
 947                 RETURN_IF_ZERO_ARGS(num_args, p, 0);
 948 
 949                 va_start(va, type_spec);
 950 
 951                 object = va_arg(va, zval **);
 952                 ce = va_arg(va, zend_class_entry *);
 953                 *object = this_ptr;
 954 
 955                 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
 956                         zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
 957                                 ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
 958                 }
 959 
 960                 retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC);
 961                 va_end(va);
 962         }
 963         return retval;
 964 }
 965 /* }}} */
 966 
 967 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
 968 {
 969         va_list va;
 970         int retval;
 971         const char *p = type_spec;
 972         zval **object;
 973         zend_class_entry *ce;
 974         int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
 975 
 976         if (!this_ptr) {
 977                 RETURN_IF_ZERO_ARGS(num_args, p, quiet);
 978 
 979                 va_start(va, type_spec);
 980                 retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
 981                 va_end(va);
 982         } else {
 983                 p++;
 984                 RETURN_IF_ZERO_ARGS(num_args, p, quiet);
 985 
 986                 va_start(va, type_spec);
 987 
 988                 object = va_arg(va, zval **);
 989                 ce = va_arg(va, zend_class_entry *);
 990                 *object = this_ptr;
 991 
 992                 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
 993                         if (!quiet) {
 994                                 zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
 995                                         ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
 996                         }
 997                         va_end(va);
 998                         return FAILURE;
 999                 }
1000 
1001                 retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
1002                 va_end(va);
1003         }
1004         return retval;
1005 }
1006 /* }}} */
1007 
1008 /* Argument parsing API -- andrei */
1009 ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
1010 {
1011         ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));
1012 
1013         _zend_hash_init(Z_ARRVAL_P(arg), size, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
1014         Z_TYPE_P(arg) = IS_ARRAY;
1015         return SUCCESS;
1016 }
1017 /* }}} */
1018 
1019 static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
1020 {
1021         /* which name should a numeric property have ? */
1022         if (hash_key->nKeyLength) {
1023                 zval *obj = va_arg(args, zval *);
1024                 zend_object_handlers *obj_ht = va_arg(args, zend_object_handlers *);
1025                 zval *member;
1026 
1027                 MAKE_STD_ZVAL(member);
1028                 ZVAL_STRINGL(member, hash_key->arKey, hash_key->nKeyLength-1, 1);
1029                 obj_ht->write_property(obj, member, *value, 0 TSRMLS_CC);
1030                 zval_ptr_dtor(&member);
1031         }
1032         return ZEND_HASH_APPLY_KEEP;
1033 }
1034 /* }}} */
1035 
1036 /* This function should be called after the constructor has been called
1037  * because it may call __set from the uninitialized object otherwise. */
1038 ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */
1039 {
1040         const zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
1041         zend_class_entry *old_scope = EG(scope);
1042 
1043         EG(scope) = Z_OBJCE_P(obj);
1044         zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t)zend_merge_property, 2, obj, obj_ht);
1045         EG(scope) = old_scope;
1046 
1047         if (destroy_ht) {
1048                 zend_hash_destroy(properties);
1049                 FREE_HASHTABLE(properties);
1050         }
1051 }
1052 /* }}} */
1053 
1054 static int zval_update_class_constant(zval **pp, int is_static, int offset TSRMLS_DC) /* {{{ */
1055 {
1056         if (IS_CONSTANT_TYPE(Z_TYPE_PP(pp))) {
1057                 zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
1058 
1059                 if ((*scope)->parent) {
1060                         zend_class_entry *ce = *scope;
1061                         HashPosition pos;
1062                         zend_property_info *prop_info;
1063 
1064                         do {
1065                                 for (zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
1066                                      zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop_info, &pos) == SUCCESS;
1067                                      zend_hash_move_forward_ex(&ce->properties_info, &pos)) {
1068                                         if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
1069                                             offset == prop_info->offset) {
1070                                                 int ret;
1071                                                 zend_class_entry *old_scope = *scope;
1072                                                 *scope = prop_info->ce;
1073                                                 ret = zval_update_constant(pp, 1 TSRMLS_CC);
1074                                                 *scope = old_scope;
1075                                                 return ret;
1076                                         }
1077                                 }                               
1078                                 ce = ce->parent;
1079                         } while (ce);
1080 
1081                 }
1082                 return zval_update_constant(pp, 1 TSRMLS_CC);
1083         }
1084         return 0;
1085 }
1086 /* }}} */
1087 
1088 ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
1089 {
1090         if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0 || (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count)) {
1091                 zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
1092                 zend_class_entry *old_scope = *scope;
1093                 int i;
1094 
1095                 *scope = class_type;
1096                 zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void *)1 TSRMLS_CC);
1097 
1098                 for (i = 0; i < class_type->default_properties_count; i++) {
1099                         if (class_type->default_properties_table[i]) {
1100                                 zval_update_class_constant(&class_type->default_properties_table[i], 0, i TSRMLS_CC);
1101                         }
1102                 }
1103 
1104                 if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
1105                         zval **p;
1106 
1107                         if (class_type->parent) {
1108                                 zend_update_class_constants(class_type->parent TSRMLS_CC);
1109                         }
1110 #if ZTS
1111                         CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
1112 #else
1113                         class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
1114 #endif
1115                         for (i = 0; i < class_type->default_static_members_count; i++) {
1116                                 p = &class_type->default_static_members_table[i];
1117                                 if (Z_ISREF_PP(p) &&
1118                                         class_type->parent &&
1119                                         i < class_type->parent->default_static_members_count &&
1120                                         *p == class_type->parent->default_static_members_table[i] &&
1121                                         CE_STATIC_MEMBERS(class_type->parent)[i]
1122                                 ) {
1123                                         zval *q = CE_STATIC_MEMBERS(class_type->parent)[i];
1124 
1125                                         Z_ADDREF_P(q);
1126                                         Z_SET_ISREF_P(q);
1127                                         CE_STATIC_MEMBERS(class_type)[i] = q;
1128                                 } else {
1129                                         zval *r;
1130 
1131                                         ALLOC_ZVAL(r);
1132                                         *r = **p;
1133                                         INIT_PZVAL(r);
1134                                         zval_copy_ctor(r);
1135                                         CE_STATIC_MEMBERS(class_type)[i] = r;
1136                                 }
1137                         }
1138                 }
1139 
1140                 for (i = 0; i < class_type->default_static_members_count; i++) {
1141                         zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i TSRMLS_CC);
1142                 }
1143 
1144                 *scope = old_scope;
1145                 class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1146         }
1147 }
1148 /* }}} */
1149 
1150 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1151 {
1152         int i;
1153 
1154         if (class_type->default_properties_count) {
1155                 object->properties_table = emalloc(sizeof(zval*) * class_type->default_properties_count);
1156                 for (i = 0; i < class_type->default_properties_count; i++) {
1157                         object->properties_table[i] = class_type->default_properties_table[i];
1158                         if (class_type->default_properties_table[i]) {
1159 #if ZTS
1160                                 ALLOC_ZVAL( object->properties_table[i]);
1161                                 MAKE_COPY_ZVAL(&class_type->default_properties_table[i], object->properties_table[i]);
1162 #else
1163                                 Z_ADDREF_P(object->properties_table[i]);
1164 #endif
1165                         }
1166                 }
1167                 object->properties = NULL;
1168         }
1169 }
1170 /* }}} */
1171 
1172 /* This function requires 'properties' to contain all props declared in the
1173  * class and all props being public. If only a subset is given or the class
1174  * has protected members then you need to merge the properties separately by
1175  * calling zend_merge_properties(). */
1176 ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1177 {
1178         zend_object *object;
1179 
1180         if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1181                 char *what =   (class_type->ce_flags & ZEND_ACC_INTERFACE)                ? "interface"
1182                                          :((class_type->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) ? "trait"
1183                                          :                                                              "abstract class";
1184                 zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
1185         }
1186 
1187         zend_update_class_constants(class_type TSRMLS_CC);
1188 
1189         Z_TYPE_P(arg) = IS_OBJECT;
1190         if (class_type->create_object == NULL) {
1191                 Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
1192                 if (properties) {
1193                         object->properties = properties;
1194                         object->properties_table = NULL;
1195                 } else {
1196                         object_properties_init(object, class_type);
1197                 }
1198         } else {
1199                 Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
1200         }
1201         return SUCCESS;
1202 }
1203 /* }}} */
1204 
1205 ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1206 {
1207         return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
1208 }
1209 /* }}} */
1210 
1211 ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1212 {
1213         return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
1214 }
1215 /* }}} */
1216 
1217 ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */
1218 {
1219         zend_error(E_WARNING, "add_assoc_function() is no longer supported");
1220         return FAILURE;
1221 }
1222 /* }}} */
1223 
1224 ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
1225 {
1226         zval *tmp;
1227 
1228         MAKE_STD_ZVAL(tmp);
1229         ZVAL_LONG(tmp, n);
1230 
1231         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1232 }
1233 /* }}} */
1234 
1235 ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */
1236 {
1237         zval *tmp;
1238 
1239         MAKE_STD_ZVAL(tmp);
1240         ZVAL_NULL(tmp);
1241 
1242         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1243 }
1244 /* }}} */
1245 
1246 ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */
1247 {
1248         zval *tmp;
1249 
1250         MAKE_STD_ZVAL(tmp);
1251         ZVAL_BOOL(tmp, b);
1252 
1253         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1254 }
1255 /* }}} */
1256 
1257 ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */
1258 {
1259         zval *tmp;
1260 
1261         MAKE_STD_ZVAL(tmp);
1262         ZVAL_RESOURCE(tmp, r);
1263 
1264         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1265 }
1266 /* }}} */
1267 
1268 ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */
1269 {
1270         zval *tmp;
1271 
1272         MAKE_STD_ZVAL(tmp);
1273         ZVAL_DOUBLE(tmp, d);
1274 
1275         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1276 }
1277 /* }}} */
1278 
1279 ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */
1280 {
1281         zval *tmp;
1282 
1283         MAKE_STD_ZVAL(tmp);
1284         ZVAL_STRING(tmp, str, duplicate);
1285 
1286         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1287 }
1288 /* }}} */
1289 
1290 ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */
1291 {
1292         zval *tmp;
1293 
1294         MAKE_STD_ZVAL(tmp);
1295         ZVAL_STRINGL(tmp, str, length, duplicate);
1296 
1297         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1298 }
1299 /* }}} */
1300 
1301 ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */
1302 {
1303         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL);
1304 }
1305 /* }}} */
1306 
1307 ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
1308 {
1309         zval *tmp;
1310 
1311         MAKE_STD_ZVAL(tmp);
1312         ZVAL_LONG(tmp, n);
1313 
1314         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1315 }
1316 /* }}} */
1317 
1318 ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
1319 {
1320         zval *tmp;
1321 
1322         MAKE_STD_ZVAL(tmp);
1323         ZVAL_NULL(tmp);
1324 
1325         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1326 }
1327 /* }}} */
1328 
1329 ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
1330 {
1331         zval *tmp;
1332 
1333         MAKE_STD_ZVAL(tmp);
1334         ZVAL_BOOL(tmp, b);
1335 
1336         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1337 }
1338 /* }}} */
1339 
1340 ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */
1341 {
1342         zval *tmp;
1343 
1344         MAKE_STD_ZVAL(tmp);
1345         ZVAL_RESOURCE(tmp, r);
1346 
1347         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1348 }
1349 /* }}} */
1350 
1351 ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
1352 {
1353         zval *tmp;
1354 
1355         MAKE_STD_ZVAL(tmp);
1356         ZVAL_DOUBLE(tmp, d);
1357 
1358         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1359 }
1360 /* }}} */
1361 
1362 ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */
1363 {
1364         zval *tmp;
1365 
1366         MAKE_STD_ZVAL(tmp);
1367         ZVAL_STRING(tmp, str, duplicate);
1368 
1369         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1370 }
1371 /* }}} */
1372 
1373 ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */
1374 {
1375         zval *tmp;
1376 
1377         MAKE_STD_ZVAL(tmp);
1378         ZVAL_STRINGL(tmp, str, length, duplicate);
1379 
1380         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1381 }
1382 /* }}} */
1383 
1384 ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */
1385 {
1386         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL);
1387 }
1388 /* }}} */
1389 
1390 ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
1391 {
1392         zval *tmp;
1393 
1394         MAKE_STD_ZVAL(tmp);
1395         ZVAL_LONG(tmp, n);
1396 
1397         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1398 }
1399 /* }}} */
1400 
1401 ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1402 {
1403         zval *tmp;
1404 
1405         MAKE_STD_ZVAL(tmp);
1406         ZVAL_NULL(tmp);
1407 
1408         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1409 }
1410 /* }}} */
1411 
1412 ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1413 {
1414         zval *tmp;
1415 
1416         MAKE_STD_ZVAL(tmp);
1417         ZVAL_BOOL(tmp, b);
1418 
1419         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1420 }
1421 /* }}} */
1422 
1423 ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */
1424 {
1425         zval *tmp;
1426 
1427         MAKE_STD_ZVAL(tmp);
1428         ZVAL_RESOURCE(tmp, r);
1429 
1430         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1431 }
1432 /* }}} */
1433 
1434 ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1435 {
1436         zval *tmp;
1437 
1438         MAKE_STD_ZVAL(tmp);
1439         ZVAL_DOUBLE(tmp, d);
1440 
1441         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1442 }
1443 /* }}} */
1444 
1445 ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */
1446 {
1447         zval *tmp;
1448 
1449         MAKE_STD_ZVAL(tmp);
1450         ZVAL_STRING(tmp, str, duplicate);
1451 
1452         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1453 }
1454 /* }}} */
1455 
1456 ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */
1457 {
1458         zval *tmp;
1459 
1460         MAKE_STD_ZVAL(tmp);
1461         ZVAL_STRINGL(tmp, str, length, duplicate);
1462 
1463         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1464 }
1465 /* }}} */
1466 
1467 ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
1468 {
1469         return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
1470 }
1471 /* }}} */
1472 
1473 ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */
1474 {
1475         zval *tmp;
1476 
1477         MAKE_STD_ZVAL(tmp);
1478         ZVAL_STRING(tmp, str, duplicate);
1479 
1480         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
1481 }
1482 /* }}} */
1483 
1484 ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) /* {{{ */
1485 {
1486         zval *tmp;
1487 
1488         MAKE_STD_ZVAL(tmp);
1489         ZVAL_STRINGL(tmp, str, length, duplicate);
1490 
1491         return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
1492 }
1493 /* }}} */
1494 
1495 ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */
1496 {
1497         zval *tmp;
1498 
1499         MAKE_STD_ZVAL(tmp);
1500         ZVAL_LONG(tmp, l);
1501 
1502         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1503 }
1504 /* }}} */
1505 
1506 ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */
1507 {
1508         zval *tmp;
1509 
1510         MAKE_STD_ZVAL(tmp);
1511         ZVAL_DOUBLE(tmp, d);
1512 
1513         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1514 }
1515 /* }}} */
1516 
1517 ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */
1518 {
1519         zval *tmp;
1520 
1521         MAKE_STD_ZVAL(tmp);
1522         ZVAL_STRING(tmp, str, duplicate);
1523 
1524         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1525 }
1526 /* }}} */
1527 
1528 ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */
1529 {
1530         zval *tmp;
1531 
1532         MAKE_STD_ZVAL(tmp);
1533         ZVAL_STRINGL(tmp, str, length, duplicate);
1534 
1535         return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1536 }
1537 /* }}} */
1538 
1539 ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
1540 {
1541         int result;
1542 
1543         switch (Z_TYPE_P(key)) {
1544                 case IS_STRING:
1545                         result = zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
1546                         break;
1547                 case IS_NULL:
1548                         result = zend_symtable_update(ht, "", 1, &value, sizeof(zval *), NULL);
1549                         break;
1550                 case IS_RESOURCE:
1551                         zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(key), Z_LVAL_P(key));
1552                         /* break missing intentionally */
1553                 case IS_BOOL:
1554                 case IS_LONG:
1555                         result = zend_hash_index_update(ht, Z_LVAL_P(key), &value, sizeof(zval *), NULL);
1556                         break;
1557                 case IS_DOUBLE:
1558                         result = zend_hash_index_update(ht, zend_dval_to_lval(Z_DVAL_P(key)), &value, sizeof(zval *), NULL);
1559                         break;
1560                 default:
1561                         zend_error(E_WARNING, "Illegal offset type");
1562                         result = FAILURE;
1563         }
1564 
1565         if (result == SUCCESS) {
1566                 Z_ADDREF_P(value);
1567         }
1568 
1569         return result;
1570 }
1571 /* }}} */
1572 
1573 ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
1574 {
1575         zval *tmp;
1576         zval *z_key;
1577 
1578         MAKE_STD_ZVAL(tmp);
1579         ZVAL_LONG(tmp, n);
1580 
1581         MAKE_STD_ZVAL(z_key);
1582         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1583 
1584         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1585         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1586         zval_ptr_dtor(&z_key);
1587         return SUCCESS;
1588 }
1589 /* }}} */
1590 
1591 ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */
1592 {
1593         zval *tmp;
1594         zval *z_key;
1595 
1596         MAKE_STD_ZVAL(tmp);
1597         ZVAL_BOOL(tmp, b);
1598 
1599         MAKE_STD_ZVAL(z_key);
1600         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1601 
1602         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1603         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1604         zval_ptr_dtor(&z_key);
1605         return SUCCESS;
1606 }
1607 /* }}} */
1608 
1609 ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */
1610 {
1611         zval *tmp;
1612         zval *z_key;
1613 
1614         MAKE_STD_ZVAL(tmp);
1615         ZVAL_NULL(tmp);
1616 
1617         MAKE_STD_ZVAL(z_key);
1618         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1619 
1620         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1621         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1622         zval_ptr_dtor(&z_key);
1623         return SUCCESS;
1624 }
1625 /* }}} */
1626 
1627 ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
1628 {
1629         zval *tmp;
1630         zval *z_key;
1631 
1632         MAKE_STD_ZVAL(tmp);
1633         ZVAL_RESOURCE(tmp, n);
1634 
1635         MAKE_STD_ZVAL(z_key);
1636         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1637 
1638         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1639         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1640         zval_ptr_dtor(&z_key);
1641         return SUCCESS;
1642 }
1643 /* }}} */
1644 
1645 ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */
1646 {
1647         zval *tmp;
1648         zval *z_key;
1649 
1650         MAKE_STD_ZVAL(tmp);
1651         ZVAL_DOUBLE(tmp, d);
1652 
1653         MAKE_STD_ZVAL(z_key);
1654         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1655 
1656         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1657         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1658         zval_ptr_dtor(&z_key);
1659         return SUCCESS;
1660 }
1661 /* }}} */
1662 
1663 ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str, int duplicate TSRMLS_DC) /* {{{ */
1664 {
1665         zval *tmp;
1666         zval *z_key;
1667 
1668         MAKE_STD_ZVAL(tmp);
1669         ZVAL_STRING(tmp, str, duplicate);
1670 
1671         MAKE_STD_ZVAL(z_key);
1672         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1673 
1674         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1675         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1676         zval_ptr_dtor(&z_key);
1677         return SUCCESS;
1678 }
1679 /* }}} */
1680 
1681 ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */
1682 {
1683         zval *tmp;
1684         zval *z_key;
1685 
1686         MAKE_STD_ZVAL(tmp);
1687         ZVAL_STRINGL(tmp, str, length, duplicate);
1688 
1689         MAKE_STD_ZVAL(z_key);
1690         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1691 
1692         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp, 0 TSRMLS_CC);
1693         zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1694         zval_ptr_dtor(&z_key);
1695         return SUCCESS;
1696 }
1697 /* }}} */
1698 
1699 ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */
1700 {
1701         zval *z_key;
1702 
1703         MAKE_STD_ZVAL(z_key);
1704         ZVAL_STRINGL(z_key, key, key_len-1, 1);
1705 
1706         Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value, 0 TSRMLS_CC);
1707         zval_ptr_dtor(&z_key);
1708         return SUCCESS;
1709 }
1710 /* }}} */
1711 
1712 ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1713 {
1714         int name_len;
1715         char *lcname;
1716 
1717         if (module->module_started) {
1718                 return SUCCESS;
1719         }
1720         module->module_started = 1;
1721 
1722         /* Check module dependencies */
1723         if (module->deps) {
1724                 const zend_module_dep *dep = module->deps;
1725 
1726                 while (dep->name) {
1727                         if (dep->type == MODULE_DEP_REQUIRED) {
1728                                 zend_module_entry *req_mod;
1729 
1730                                 name_len = strlen(dep->name);
1731                                 lcname = zend_str_tolower_dup(dep->name, name_len);
1732 
1733                                 if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || !req_mod->module_started) {
1734                                         efree(lcname);
1735                                         /* TODO: Check version relationship */
1736                                         zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
1737                                         module->module_started = 0;
1738                                         return FAILURE;
1739                                 }
1740                                 efree(lcname);
1741                         }
1742                         ++dep;
1743                 }
1744         }
1745 
1746         /* Initialize module globals */
1747         if (module->globals_size) {
1748 #ifdef ZTS
1749                 ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1750 #else
1751                 if (module->globals_ctor) {
1752                         module->globals_ctor(module->globals_ptr TSRMLS_CC);
1753                 }
1754 #endif
1755         }
1756         if (module->module_startup_func) {
1757                 EG(current_module) = module;
1758                 if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
1759                         zend_error(E_CORE_ERROR,"Unable to start %s module", module->name);
1760                         EG(current_module) = NULL;
1761                         return FAILURE;
1762                 }
1763                 EG(current_module) = NULL;
1764         }
1765         return SUCCESS;
1766 }
1767 /* }}} */
1768 
1769 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */
1770 {
1771         Bucket **b1 = base;
1772         Bucket **b2;
1773         Bucket **end = b1 + count;
1774         Bucket *tmp;
1775         zend_module_entry *m, *r;
1776 
1777         while (b1 < end) {
1778 try_again:
1779                 m = (zend_module_entry*)(*b1)->pData;
1780                 if (!m->module_started && m->deps) {
1781                         const zend_module_dep *dep = m->deps;
1782                         while (dep->name) {
1783                                 if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1784                                         b2 = b1 + 1;
1785                                         while (b2 < end) {
1786                                                 r = (zend_module_entry*)(*b2)->pData;
1787                                                 if (strcasecmp(dep->name, r->name) == 0) {
1788                                                         tmp = *b1;
1789                                                         *b1 = *b2;
1790                                                         *b2 = tmp;
1791                                                         goto try_again;
1792                                                 }
1793                                                 b2++;
1794                                         }
1795                                 }
1796                                 dep++;
1797                         }
1798                 }
1799                 b1++;
1800         }
1801 }
1802 /* }}} */
1803 
1804 ZEND_API void zend_collect_module_handlers(TSRMLS_D) /* {{{ */
1805 {
1806         HashPosition pos;
1807         zend_module_entry *module;
1808         int startup_count = 0;
1809         int shutdown_count = 0;
1810         int post_deactivate_count = 0;
1811         zend_class_entry **pce;
1812         int class_count = 0;
1813 
1814         /* Collect extensions with request startup/shutdown handlers */
1815         for (zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
1816              zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) == SUCCESS;
1817              zend_hash_move_forward_ex(&module_registry, &pos)) {
1818                 if (module->request_startup_func) {
1819                         startup_count++;
1820                 }
1821                 if (module->request_shutdown_func) {
1822                         shutdown_count++;
1823                 }
1824                 if (module->post_deactivate_func) {
1825                         post_deactivate_count++;
1826                 }
1827         }
1828         module_request_startup_handlers = (zend_module_entry**)malloc(
1829             sizeof(zend_module_entry*) *
1830                 (startup_count + 1 +
1831                  shutdown_count + 1 +
1832                  post_deactivate_count + 1));
1833         module_request_startup_handlers[startup_count] = NULL;
1834         module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1;
1835         module_request_shutdown_handlers[shutdown_count] = NULL;
1836         module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1;
1837         module_post_deactivate_handlers[post_deactivate_count] = NULL;
1838         startup_count = 0;
1839         
1840         for (zend_hash_internal_pointer_reset_ex(&module_registry, &pos);
1841              zend_hash_get_current_data_ex(&module_registry, (void *) &module, &pos) == SUCCESS;
1842              zend_hash_move_forward_ex(&module_registry, &pos)) {
1843                 if (module->request_startup_func) {
1844                         module_request_startup_handlers[startup_count++] = module;
1845                 }
1846                 if (module->request_shutdown_func) {
1847                         module_request_shutdown_handlers[--shutdown_count] = module;
1848                 }
1849                 if (module->post_deactivate_func) {
1850                         module_post_deactivate_handlers[--post_deactivate_count] = module;
1851                 }
1852         }
1853 
1854         /* Collect internal classes with static members */
1855         for (zend_hash_internal_pointer_reset_ex(CG(class_table), &pos);
1856              zend_hash_get_current_data_ex(CG(class_table), (void *) &pce, &pos) == SUCCESS;
1857              zend_hash_move_forward_ex(CG(class_table), &pos)) {
1858                 if ((*pce)->type == ZEND_INTERNAL_CLASS &&
1859                     (*pce)->default_static_members_count > 0) {
1860                     class_count++;
1861                 }
1862         }
1863 
1864         class_cleanup_handlers = (zend_class_entry**)malloc(
1865                 sizeof(zend_class_entry*) *
1866                 (class_count + 1));
1867         class_cleanup_handlers[class_count] = NULL;
1868 
1869         if (class_count) {
1870                 for (zend_hash_internal_pointer_reset_ex(CG(class_table), &pos);
1871                      zend_hash_get_current_data_ex(CG(class_table), (void *) &pce, &pos) == SUCCESS;
1872                  zend_hash_move_forward_ex(CG(class_table), &pos)) {
1873                         if ((*pce)->type == ZEND_INTERNAL_CLASS &&
1874                             (*pce)->default_static_members_count > 0) {
1875                             class_cleanup_handlers[--class_count] = *pce;
1876                         }
1877                 }
1878         }
1879 }
1880 /* }}} */
1881 
1882 ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
1883 {
1884         zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC);
1885         zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module_ex TSRMLS_CC);
1886         return SUCCESS;
1887 }
1888 /* }}} */
1889 
1890 ZEND_API void zend_destroy_modules(void) /* {{{ */
1891 {
1892         free(class_cleanup_handlers);
1893         free(module_request_startup_handlers);
1894         zend_hash_graceful_reverse_destroy(&module_registry);
1895 }
1896 /* }}} */
1897 
1898 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1899 {
1900         int name_len;
1901         char *lcname;
1902         zend_module_entry *module_ptr;
1903 
1904         if (!module) {
1905                 return NULL;
1906         }
1907 
1908 #if 0
1909         zend_printf("%s: Registering module %d\n", module->name, module->module_number);
1910 #endif
1911 
1912         /* Check module dependencies */
1913         if (module->deps) {
1914                 const zend_module_dep *dep = module->deps;
1915 
1916                 while (dep->name) {
1917                         if (dep->type == MODULE_DEP_CONFLICTS) {
1918                                 name_len = strlen(dep->name);
1919                                 lcname = zend_str_tolower_dup(dep->name, name_len);
1920 
1921                                 if (zend_hash_exists(&module_registry, lcname, name_len+1)) {
1922                                         efree(lcname);
1923                                         /* TODO: Check version relationship */
1924                                         zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
1925                                         return NULL;
1926                                 }
1927                                 efree(lcname);
1928                         }
1929                         ++dep;
1930                 }
1931         }
1932 
1933         name_len = strlen(module->name);
1934         lcname = zend_str_tolower_dup(module->name, name_len);
1935 
1936         if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) {
1937                 zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
1938                 efree(lcname);
1939                 return NULL;
1940         }
1941         efree(lcname);
1942         module = module_ptr;
1943         EG(current_module) = module;
1944 
1945         if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
1946                 EG(current_module) = NULL;
1947                 zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
1948                 return NULL;
1949         }
1950 
1951         EG(current_module) = NULL;
1952         return module;
1953 }
1954 /* }}} */
1955 
1956 ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */
1957 {
1958         module->module_number = zend_next_free_module();
1959         module->type = MODULE_PERSISTENT;
1960         return zend_register_module_ex(module TSRMLS_CC);
1961 }
1962 /* }}} */
1963 
1964 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */
1965 {
1966         char lcname[16];
1967         int name_len;
1968 
1969         /* we don't care if the function name is longer, in fact lowercasing only
1970          * the beginning of the name speeds up the check process */
1971         name_len = strlen(fptr->common.function_name);
1972         zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
1973         lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
1974 
1975         if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
1976                 zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
1977         } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1) && fptr->common.num_args != 0) {
1978                 zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
1979         } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
1980                 if (fptr->common.num_args != 1) {
1981                         zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
1982                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
1983                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_GET_FUNC_NAME);
1984                 }
1985         } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
1986                 if (fptr->common.num_args != 2) {
1987                         zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
1988                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
1989                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_SET_FUNC_NAME);
1990                 }
1991         } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
1992                 if (fptr->common.num_args != 1) {
1993                         zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME);
1994                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
1995                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_UNSET_FUNC_NAME);
1996                 }
1997         } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
1998                 if (fptr->common.num_args != 1) {
1999                         zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME);
2000                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2001                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_ISSET_FUNC_NAME);
2002                 }
2003         } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
2004                 if (fptr->common.num_args != 2) {
2005                         zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
2006                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2007                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME);
2008                 }
2009         } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
2010                 !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
2011         ) {
2012                 if (fptr->common.num_args != 2) {
2013                         zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
2014                 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2015                         zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
2016                 }
2017         } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
2018                 !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
2019         ) {
2020                 zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME);
2021         } else if (name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1 &&
2022                 !memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && fptr->common.num_args != 0) {
2023                 zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_DEBUGINFO_FUNC_NAME);
2024         }
2025 }
2026 /* }}} */
2027 
2028 /* registers all functions in *library_functions in the function hash */
2029 ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */
2030 {
2031         const zend_function_entry *ptr = functions;
2032         zend_function function, *reg_function;
2033         zend_internal_function *internal_function = (zend_internal_function *)&function;
2034         int count=0, unload=0;
2035         HashTable *target_function_table = function_table;
2036         int error_type;
2037         zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL, *__debugInfo = NULL;
2038         const char *lowercase_name;
2039         int fname_len;
2040         const char *lc_class_name = NULL;
2041         int class_name_len = 0;
2042         zend_ulong hash;
2043 
2044         if (type==MODULE_PERSISTENT) {
2045                 error_type = E_CORE_WARNING;
2046         } else {
2047                 error_type = E_WARNING;
2048         }
2049 
2050         if (!target_function_table) {
2051                 target_function_table = CG(function_table);
2052         }
2053         internal_function->type = ZEND_INTERNAL_FUNCTION;
2054         internal_function->module = EG(current_module);
2055 
2056         if (scope) {
2057                 class_name_len = strlen(scope->name);
2058                 if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) {
2059                         ++lc_class_name;
2060                         class_name_len -= (lc_class_name - scope->name);
2061                         lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
2062                 } else {
2063                         lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
2064                 }
2065         }
2066 
2067         while (ptr->fname) {
2068                 internal_function->handler = ptr->handler;
2069                 internal_function->function_name = (char*)ptr->fname;
2070                 internal_function->scope = scope;
2071                 internal_function->prototype = NULL;
2072                 if (ptr->flags) {
2073                         if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
2074                                 if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
2075                                         zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
2076                                 }
2077                                 internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
2078                         } else {
2079                                 internal_function->fn_flags = ptr->flags;
2080                         }
2081                 } else {
2082                         internal_function->fn_flags = ZEND_ACC_PUBLIC;
2083                 }
2084                 if (ptr->arg_info) {
2085                         zend_internal_function_info *info = (zend_internal_function_info*)ptr->arg_info;
2086                         
2087                         internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
2088                         internal_function->num_args = ptr->num_args;
2089                         /* Currently you cannot denote that the function can accept less arguments than num_args */
2090                         if (info->required_num_args == -1) {
2091                                 internal_function->required_num_args = ptr->num_args;
2092                         } else {
2093                                 internal_function->required_num_args = info->required_num_args;
2094                         }
2095                         if (info->return_reference) {
2096                                 internal_function->fn_flags |= ZEND_ACC_RETURN_REFERENCE;
2097                         }
2098                         if (ptr->arg_info[ptr->num_args].is_variadic) {
2099                                 internal_function->fn_flags |= ZEND_ACC_VARIADIC;
2100                         }
2101                 } else {
2102                         internal_function->arg_info = NULL;
2103                         internal_function->num_args = 0;
2104                         internal_function->required_num_args = 0;
2105                 }
2106                 if (ptr->flags & ZEND_ACC_ABSTRACT) {
2107                         if (scope) {
2108                                 /* This is a class that must be abstract itself. Here we set the check info. */
2109                                 scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2110                                 if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
2111                                         /* Since the class is not an interface it needs to be declared as a abstract class. */
2112                                         /* Since here we are handling internal functions only we can add the keyword flag. */
2113                                         /* This time we set the flag for the keyword 'abstract'. */
2114                                         scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2115                                 }
2116                         }
2117                         if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
2118                                 zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
2119                         }
2120                 } else {
2121                         if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
2122                                 efree((char*)lc_class_name);
2123                                 zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
2124                                 return FAILURE;
2125                         }
2126                         if (!internal_function->handler) {
2127                                 if (scope) {
2128                                         efree((char*)lc_class_name);
2129                                 }
2130                                 zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
2131                                 zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
2132                                 return FAILURE;
2133                         }
2134                 }
2135                 fname_len = strlen(ptr->fname);
2136                 lowercase_name = zend_new_interned_string(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC);
2137                 hash = str_hash(lowercase_name, fname_len);
2138                 if (zend_hash_quick_add(target_function_table, lowercase_name, fname_len+1, hash, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
2139                         unload=1;
2140                         str_efree(lowercase_name);
2141                         break;
2142                 }
2143 
2144                 /* If types of arguments have to be checked */
2145                 if (reg_function->common.arg_info && reg_function->common.num_args) {
2146                         int i;
2147                         for (i = 0; i < reg_function->common.num_args; i++) {
2148                                 if (reg_function->common.arg_info[i].class_name ||
2149                                     reg_function->common.arg_info[i].type_hint) {
2150                                     reg_function->common.fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
2151                                         break;
2152                                 }
2153                         }
2154                 }
2155 
2156                 if (scope) {
2157                         /* Look for ctor, dtor, clone
2158                          * If it's an old-style constructor, store it only if we don't have
2159                          * a constructor already.
2160                          */
2161                         if ((fname_len == class_name_len) && !ctor && !memcmp(lowercase_name, lc_class_name, class_name_len+1)) {
2162                                 ctor = reg_function;
2163                         } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1)) {
2164                                 ctor = reg_function;
2165                         } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1)) {
2166                                 dtor = reg_function;
2167                                 if (internal_function->num_args) {
2168                                         zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
2169                                 }
2170                         } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME) - 1)) {
2171                                 clone = reg_function;
2172                         } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME) - 1)) {
2173                                 __call = reg_function;
2174                         } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1)) {
2175                                 __callstatic = reg_function;
2176                         } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME) - 1)) {
2177                                 __tostring = reg_function;
2178                         } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME) - 1)) {
2179                                 __get = reg_function;
2180                         } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME) - 1)) {
2181                                 __set = reg_function;
2182                         } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME) - 1)) {
2183                                 __unset = reg_function;
2184                         } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME) - 1)) {
2185                                 __isset = reg_function;
2186                         } else if ((fname_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME) - 1)) {
2187                                 __debugInfo = reg_function;
2188                         } else {
2189                                 reg_function = NULL;
2190                         }
2191                         if (reg_function) {
2192                                 zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
2193                         }
2194                 }
2195                 ptr++;
2196                 count++;
2197                 str_efree(lowercase_name);
2198         }
2199         if (unload) { /* before unloading, display all remaining bad function in the module */
2200                 if (scope) {
2201                         efree((char*)lc_class_name);
2202                 }
2203                 while (ptr->fname) {
2204                         fname_len = strlen(ptr->fname);
2205                         lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
2206                         if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) {
2207                                 zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
2208                         }
2209                         efree((char*)lowercase_name);
2210                         ptr++;
2211                 }
2212                 zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
2213                 return FAILURE;
2214         }
2215         if (scope) {
2216                 scope->constructor = ctor;
2217                 scope->destructor = dtor;
2218                 scope->clone = clone;
2219                 scope->__call = __call;
2220                 scope->__callstatic = __callstatic;
2221                 scope->__tostring = __tostring;
2222                 scope->__get = __get;
2223                 scope->__set = __set;
2224                 scope->__unset = __unset;
2225                 scope->__isset = __isset;
2226                 scope->__debugInfo = __debugInfo;
2227                 if (ctor) {
2228                         ctor->common.fn_flags |= ZEND_ACC_CTOR;
2229                         if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
2230                                 zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
2231                         }
2232                         ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2233                 }
2234                 if (dtor) {
2235                         dtor->common.fn_flags |= ZEND_ACC_DTOR;
2236                         if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
2237                                 zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
2238                         }
2239                         dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2240                 }
2241                 if (clone) {
2242                         clone->common.fn_flags |= ZEND_ACC_CLONE;
2243                         if (clone->common.fn_flags & ZEND_ACC_STATIC) {
2244                                 zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
2245                         }
2246                         clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2247                 }
2248                 if (__call) {
2249                         if (__call->common.fn_flags & ZEND_ACC_STATIC) {
2250                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
2251                         }
2252                         __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2253                 }
2254                 if (__callstatic) {
2255                         if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
2256                                 zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name);
2257                         }
2258                         __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
2259                 }
2260                 if (__tostring) {
2261                         if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
2262                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name);
2263                         }
2264                         __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2265                 }
2266                 if (__get) {
2267                         if (__get->common.fn_flags & ZEND_ACC_STATIC) {
2268                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
2269                         }
2270                         __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2271                 }
2272                 if (__set) {
2273                         if (__set->common.fn_flags & ZEND_ACC_STATIC) {
2274                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
2275                         }
2276                         __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2277                 }
2278                 if (__unset) {
2279                         if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
2280                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name);
2281                         }
2282                         __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2283                 }
2284                 if (__isset) {
2285                         if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
2286                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name);
2287                         }
2288                         __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2289                 }
2290                 if (__debugInfo) {
2291                         if (__debugInfo->common.fn_flags & ZEND_ACC_STATIC) {
2292                                 zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __debugInfo->common.function_name);
2293                         }
2294                 }
2295                 efree((char*)lc_class_name);
2296         }
2297         return SUCCESS;
2298 }
2299 /* }}} */
2300 
2301 /* count=-1 means erase all functions, otherwise,
2302  * erase the first count functions
2303  */
2304 ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */
2305 {
2306         const zend_function_entry *ptr = functions;
2307         int i=0;
2308         HashTable *target_function_table = function_table;
2309 
2310         if (!target_function_table) {
2311                 target_function_table = CG(function_table);
2312         }
2313         while (ptr->fname) {
2314                 if (count!=-1 && i>=count) {
2315                         break;
2316                 }
2317 #if 0
2318                 zend_printf("Unregistering %s()\n", ptr->fname);
2319 #endif
2320                 zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1);
2321                 ptr++;
2322                 i++;
2323         }
2324 }
2325 /* }}} */
2326 
2327 ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
2328 {
2329         TSRMLS_FETCH();
2330 
2331         if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) {
2332                 return SUCCESS;
2333         }
2334         return FAILURE;
2335 }
2336 /* }}} */
2337 
2338 ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
2339 {
2340         zend_module_entry *module;
2341 
2342         return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE;
2343 }
2344 /* }}} */
2345 
2346 static int clean_module_class(const zend_class_entry **ce, int *module_number TSRMLS_DC) /* {{{ */
2347 {
2348         if ((*ce)->type == ZEND_INTERNAL_CLASS && (*ce)->info.internal.module->module_number == *module_number) {
2349                 return ZEND_HASH_APPLY_REMOVE;
2350         } else {
2351                 return ZEND_HASH_APPLY_KEEP;
2352         }
2353 }
2354 /* }}} */
2355 
2356 static void clean_module_classes(int module_number TSRMLS_DC) /* {{{ */
2357 {
2358         zend_hash_apply_with_argument(EG(class_table), (apply_func_arg_t) clean_module_class, (void *) &module_number TSRMLS_CC);
2359 }
2360 /* }}} */
2361 
2362 void module_destructor(zend_module_entry *module) /* {{{ */
2363 {
2364         TSRMLS_FETCH();
2365 
2366         if (module->type == MODULE_TEMPORARY) {
2367                 zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC);
2368                 clean_module_constants(module->module_number TSRMLS_CC);
2369                 clean_module_classes(module->module_number TSRMLS_CC);
2370         }
2371 
2372         if (module->module_started && module->module_shutdown_func) {
2373 #if 0
2374                 zend_printf("%s: Module shutdown\n", module->name);
2375 #endif
2376                 module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
2377         }
2378 
2379         /* Deinitilaise module globals */
2380         if (module->globals_size) {
2381 #ifdef ZTS
2382                 if (*module->globals_id_ptr) {
2383                         ts_free_id(*module->globals_id_ptr);
2384                 }
2385 #else
2386                 if (module->globals_dtor) {
2387                         module->globals_dtor(module->globals_ptr TSRMLS_CC);
2388                 }
2389 #endif
2390         }
2391 
2392         module->module_started=0;
2393         if (module->functions) {
2394                 zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
2395         }
2396 
2397 #if HAVE_LIBDL
2398 #if !(defined(NETWARE) && defined(APACHE_1_BUILD))
2399         if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2400                 DL_UNLOAD(module->handle);
2401         }
2402 #endif
2403 #endif
2404 }
2405 /* }}} */
2406 
2407 ZEND_API void zend_activate_modules(TSRMLS_D) /* {{{ */
2408 {
2409         zend_module_entry **p = module_request_startup_handlers;
2410 
2411         while (*p) {
2412                 zend_module_entry *module = *p;
2413 
2414                 if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
2415                         zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
2416                         exit(1);
2417                 }
2418                 p++;
2419         }
2420 }
2421 /* }}} */
2422 
2423 /* call request shutdown for all modules */
2424 int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
2425 {
2426         if (module->request_shutdown_func) {
2427 #if 0
2428                 zend_printf("%s: Request shutdown\n", module->name);
2429 #endif
2430                 module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2431         }
2432         return 0;
2433 }
2434 /* }}} */
2435 
2436 ZEND_API void zend_deactivate_modules(TSRMLS_D) /* {{{ */
2437 {
2438         EG(opline_ptr) = NULL; /* we're no longer executing anything */
2439 
2440         zend_try {
2441                 if (EG(full_tables_cleanup)) {
2442                         zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC);
2443                 } else {
2444                         zend_module_entry **p = module_request_shutdown_handlers;
2445 
2446                         while (*p) {
2447                                 zend_module_entry *module = *p;
2448 
2449                                 module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2450                                 p++;
2451                         }
2452                 }
2453         } zend_end_try();
2454 }
2455 /* }}} */
2456 
2457 ZEND_API void zend_cleanup_internal_classes(TSRMLS_D) /* {{{ */
2458 {
2459         zend_class_entry **p = class_cleanup_handlers;
2460 
2461         while (*p) {
2462                 zend_cleanup_internal_class_data(*p TSRMLS_CC);
2463                 p++;
2464         }
2465 }
2466 /* }}} */
2467 
2468 int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */
2469 {
2470         return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
2471 }
2472 /* }}} */
2473 
2474 static int exec_done_cb(zend_module_entry *module TSRMLS_DC) /* {{{ */
2475 {
2476         if (module->post_deactivate_func) {
2477                 module->post_deactivate_func();
2478         }
2479         return 0;
2480 }
2481 /* }}} */
2482 
2483 ZEND_API void zend_post_deactivate_modules(TSRMLS_D) /* {{{ */
2484 {
2485         if (EG(full_tables_cleanup)) {
2486                 zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC);
2487                 zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_unload_temp TSRMLS_CC);
2488         } else {
2489                 zend_module_entry **p = module_post_deactivate_handlers;
2490 
2491                 while (*p) {
2492                         zend_module_entry *module = *p;
2493 
2494                         module->post_deactivate_func();
2495                         p++;
2496                 }
2497         }
2498 }
2499 /* }}} */
2500 
2501 /* return the next free module number */
2502 ZEND_API int zend_next_free_module(void) /* {{{ */
2503 {
2504         return zend_hash_num_elements(&module_registry) + 1;
2505 }
2506 /* }}} */
2507 
2508 static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
2509 {
2510         zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2511         char *lowercase_name = emalloc(orig_class_entry->name_length + 1);
2512         zend_ulong hash;
2513         *class_entry = *orig_class_entry;
2514 
2515         class_entry->type = ZEND_INTERNAL_CLASS;
2516         zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
2517         class_entry->ce_flags = ce_flags;
2518         class_entry->info.internal.module = EG(current_module);
2519 
2520         if (class_entry->info.internal.builtin_functions) {
2521                 zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
2522         }
2523 
2524         zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
2525         lowercase_name = (char*)zend_new_interned_string(lowercase_name, class_entry->name_length + 1, 1 TSRMLS_CC);
2526         hash = str_hash(lowercase_name, class_entry->name_length);
2527         zend_hash_quick_update(CG(class_table), lowercase_name, class_entry->name_length+1, hash, &class_entry, sizeof(zend_class_entry *), NULL);
2528         str_efree(lowercase_name);
2529         return class_entry;
2530 }
2531 /* }}} */
2532 
2533 /* If parent_ce is not NULL then it inherits from parent_ce
2534  * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2535  * If both parent_ce and parent_name are NULL it does a regular class registration
2536  * If parent_name is specified but not found NULL is returned
2537  */
2538 ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) /* {{{ */
2539 {
2540         zend_class_entry *register_class;
2541 
2542         if (!parent_ce && parent_name) {
2543                 zend_class_entry **pce;
2544                 if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) {
2545                         return NULL;
2546                 } else {
2547                         parent_ce = *pce;
2548                 }
2549         }
2550 
2551         register_class = zend_register_internal_class(class_entry TSRMLS_CC);
2552 
2553         if (parent_ce) {
2554                 zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
2555         }
2556         return register_class;
2557 }
2558 /* }}} */
2559 
2560 ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */
2561 {
2562         zend_class_entry *interface_entry;
2563         va_list interface_list;
2564         va_start(interface_list, num_interfaces);
2565 
2566         while (num_interfaces--) {
2567                 interface_entry = va_arg(interface_list, zend_class_entry *);
2568                 zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC);
2569         }
2570 
2571         va_end(interface_list);
2572 }
2573 /* }}} */
2574 
2575 /* A class that contains at least one abstract method automatically becomes an abstract class.
2576  */
2577 ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
2578 {
2579         return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
2580 }
2581 /* }}} */
2582 
2583 ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
2584 {
2585         return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC);
2586 }
2587 /* }}} */
2588 
2589 ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */
2590 {
2591         char *lcname = zend_str_tolower_dup(name, name_len);
2592         int ret;
2593 
2594         if (lcname[0] == '\\') {
2595                 ret = zend_hash_add(CG(class_table), lcname+1, name_len, &ce, sizeof(zend_class_entry *), NULL);
2596         } else {
2597                 ret = zend_hash_add(CG(class_table), lcname, name_len+1, &ce, sizeof(zend_class_entry *), NULL);
2598         }
2599 
2600         efree(lcname);
2601         if (ret == SUCCESS) {
2602                 ce->refcount++;
2603         }
2604         return ret;
2605 }
2606 /* }}} */
2607 
2608 ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
2609 {
2610         HashTable *symbol_table;
2611         va_list symbol_table_list;
2612 
2613         if (num_symbol_tables <= 0) return FAILURE;
2614 
2615         Z_SET_ISREF_TO_P(symbol, is_ref);
2616 
2617         va_start(symbol_table_list, num_symbol_tables);
2618         while (num_symbol_tables-- > 0) {
2619                 symbol_table = va_arg(symbol_table_list, HashTable *);
2620                 zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
2621                 zval_add_ref(&symbol);
2622         }
2623         va_end(symbol_table_list);
2624         return SUCCESS;
2625 }
2626 /* }}} */
2627 
2628 /* Disabled functions support */
2629 
2630 /* {{{ proto void display_disabled_function(void)
2631 Dummy function which displays an error when a disabled function is called. */
2632 ZEND_API ZEND_FUNCTION(display_disabled_function)
2633 {
2634         zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
2635 }
2636 /* }}} */
2637 
2638 ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) /* {{{ */
2639 {
2640         zend_internal_function *func;
2641         if (zend_hash_find(CG(function_table), function_name, function_name_length+1, (void **)&func)==SUCCESS) {
2642                 func->arg_info = NULL;
2643                 func->handler = ZEND_FN(display_disabled_function);
2644                 return SUCCESS;
2645         }
2646         return FAILURE;
2647 }
2648 /* }}} */
2649 
2650 #ifdef ZEND_WIN32
2651 #pragma optimize("", off)
2652 #endif
2653 static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
2654 {
2655         zend_object_value retval;
2656         zend_object *intern;
2657         retval = zend_objects_new(&intern, class_type TSRMLS_CC);
2658         zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
2659         return retval;
2660 }
2661 #ifdef ZEND_WIN32
2662 #pragma optimize("", on)
2663 #endif
2664 /* }}} */
2665 
2666 static const zend_function_entry disabled_class_new[] = {
2667         ZEND_FE_END
2668 };
2669 
2670 ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) /* {{{ */
2671 {
2672         zend_class_entry **disabled_class;
2673 
2674         zend_str_tolower(class_name, class_name_length);
2675         if (zend_hash_find(CG(class_table), class_name, class_name_length+1, (void **)&disabled_class)==FAILURE) {
2676                 return FAILURE;
2677         }
2678         INIT_CLASS_ENTRY_INIT_METHODS((**disabled_class), disabled_class_new, NULL, NULL, NULL, NULL, NULL);
2679         (*disabled_class)->create_object = display_disabled_class;
2680         zend_hash_clean(&((*disabled_class)->function_table));
2681         return SUCCESS;
2682 }
2683 /* }}} */
2684 
2685 static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
2686 {
2687         int ret = 0;
2688         zend_class_entry **pce;
2689         char *lcname = zend_str_tolower_dup(name, name_len);
2690 
2691         *strict_class = 0;
2692         if (name_len == sizeof("self") - 1 &&
2693             !memcmp(lcname, "self", sizeof("self") - 1)) {
2694                 if (!EG(scope)) {
2695                         if (error) *error = estrdup("cannot access self:: when no class scope is active");
2696                 } else {
2697                         fcc->called_scope = EG(called_scope);
2698                         fcc->calling_scope = EG(scope);
2699                         if (!fcc->object_ptr) {
2700                                 fcc->object_ptr = EG(This);
2701                         }
2702                         ret = 1;
2703                 }
2704         } else if (name_len == sizeof("parent") - 1 && 
2705                        !memcmp(lcname, "parent", sizeof("parent") - 1)) {
2706                 if (!EG(scope)) {
2707                         if (error) *error = estrdup("cannot access parent:: when no class scope is active");
2708                 } else if (!EG(scope)->parent) {
2709                         if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
2710                 } else {
2711                         fcc->called_scope = EG(called_scope);
2712                         fcc->calling_scope = EG(scope)->parent;
2713                         if (!fcc->object_ptr) {
2714                                 fcc->object_ptr = EG(This);
2715                         }
2716                         *strict_class = 1;
2717                         ret = 1;
2718                 }
2719         } else if (name_len == sizeof("static") - 1 &&
2720                    !memcmp(lcname, "static", sizeof("static") - 1)) {
2721                 if (!EG(called_scope)) {
2722                         if (error) *error = estrdup("cannot access static:: when no class scope is active");
2723                 } else {
2724                         fcc->called_scope = EG(called_scope);
2725                         fcc->calling_scope = EG(called_scope);
2726                         if (!fcc->object_ptr) {
2727                                 fcc->object_ptr = EG(This);
2728                         }
2729                         *strict_class = 1;
2730                         ret = 1;
2731                 }
2732         } else if (zend_lookup_class_ex(name, name_len, NULL, 1, &pce TSRMLS_CC) == SUCCESS) {
2733                 zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
2734 
2735                 fcc->calling_scope = *pce;
2736                 if (scope && !fcc->object_ptr && EG(This) &&
2737                     instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
2738                     instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) {
2739                         fcc->object_ptr = EG(This);
2740                         fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
2741                 } else {
2742                         fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
2743                 }
2744                 *strict_class = 1;
2745                 ret = 1;
2746         } else {
2747                 if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
2748         }
2749         efree(lcname);
2750         return ret;
2751 }
2752 /* }}} */
2753 
2754 static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
2755 {
2756         zend_class_entry *ce_org = fcc->calling_scope;
2757         int retval = 0;
2758         char *mname, *lmname;
2759         const char *colon;
2760         int clen, mlen;
2761         zend_class_entry *last_scope;
2762         HashTable *ftable;
2763         int call_via_handler = 0;
2764 
2765         if (error) {
2766                 *error = NULL;
2767         }
2768 
2769         fcc->calling_scope = NULL;
2770         fcc->function_handler = NULL;
2771 
2772         if (!ce_org) {
2773                 /* Skip leading \ */
2774                 if (Z_STRVAL_P(callable)[0] == '\\') {
2775                         mlen = Z_STRLEN_P(callable) - 1;
2776                         lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 1, mlen);
2777                 } else {
2778                         mlen = Z_STRLEN_P(callable);
2779                         lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
2780                 }
2781                 /* Check if function with given name exists.
2782                  * This may be a compound name that includes namespace name */
2783                 if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
2784                         efree(lmname);
2785                         return 1;
2786                 }
2787                 efree(lmname);
2788         }
2789 
2790         /* Split name into class/namespace and method/function names */
2791         if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
2792                 colon > Z_STRVAL_P(callable) &&
2793                 *(colon-1) == ':'
2794         ) {
2795                 colon--;
2796                 clen = colon - Z_STRVAL_P(callable);
2797                 mlen = Z_STRLEN_P(callable) - clen - 2;
2798 
2799                 if (colon == Z_STRVAL_P(callable)) {
2800                         if (error) zend_spprintf(error, 0, "invalid function name");
2801                         return 0;
2802                 }
2803 
2804                 /* This is a compound name.
2805                  * Try to fetch class and then find static method. */
2806                 last_scope = EG(scope);
2807                 if (ce_org) {
2808                         EG(scope) = ce_org;
2809                 }
2810 
2811                 if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
2812                         EG(scope) = last_scope;
2813                         return 0;
2814                 }
2815                 EG(scope) = last_scope;
2816 
2817                 ftable = &fcc->calling_scope->function_table;
2818                 if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) {
2819                         if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, fcc->calling_scope->name);
2820                         return 0;
2821                 }
2822                 mname = Z_STRVAL_P(callable) + clen + 2;
2823         } else if (ce_org) {
2824                 /* Try to fetch find static method of given class. */
2825                 mlen = Z_STRLEN_P(callable);
2826                 mname = Z_STRVAL_P(callable);
2827                 ftable = &ce_org->function_table;
2828                 fcc->calling_scope = ce_org;
2829         } else {
2830                 /* We already checked for plain function before. */
2831                 if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
2832                         zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
2833                 }
2834                 return 0;
2835         }
2836 
2837         lmname = zend_str_tolower_dup(mname, mlen);
2838         if (strict_class &&
2839             fcc->calling_scope &&
2840             mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
2841             !memcmp(lmname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME) - 1)) {
2842                 fcc->function_handler = fcc->calling_scope->constructor;
2843                 if (fcc->function_handler) {
2844                         retval = 1;
2845                 }
2846         } else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
2847                 retval = 1;
2848                 if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
2849                     !strict_class && EG(scope) &&
2850                     instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
2851                         zend_function *priv_fbc;
2852 
2853                         if (zend_hash_find(&EG(scope)->function_table, lmname, mlen+1, (void **) &priv_fbc)==SUCCESS
2854                                 && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
2855                                 && priv_fbc->common.scope == EG(scope)) {
2856                                 fcc->function_handler = priv_fbc;
2857                         }
2858                 }
2859                 if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
2860                     (fcc->calling_scope &&
2861                      ((fcc->object_ptr && fcc->calling_scope->__call) ||
2862                       (!fcc->object_ptr && fcc->calling_scope->__callstatic)))) {
2863                         if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
2864                                 if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
2865                                         retval = 0;
2866                                         fcc->function_handler = NULL;
2867                                         goto get_function_via_handler;
2868                                 }
2869                         } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
2870                                 if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
2871                                         retval = 0;
2872                                         fcc->function_handler = NULL;
2873                                         goto get_function_via_handler;
2874                                 }
2875                         }
2876                 }
2877         } else {
2878 get_function_via_handler:
2879                 if (fcc->object_ptr && fcc->calling_scope == ce_org) {
2880                         if (strict_class && ce_org->__call) {
2881                                 fcc->function_handler = emalloc(sizeof(zend_internal_function));
2882                                 fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
2883                                 fcc->function_handler->internal_function.module = (ce_org->type == ZEND_INTERNAL_CLASS) ? ce_org->info.internal.module : NULL;
2884                                 fcc->function_handler->internal_function.handler = zend_std_call_user_call;
2885                                 fcc->function_handler->internal_function.arg_info = NULL;
2886                                 fcc->function_handler->internal_function.num_args = 0;
2887                                 fcc->function_handler->internal_function.scope = ce_org;
2888                                 fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
2889                                 fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
2890                                 call_via_handler = 1;
2891                                 retval = 1;
2892                         } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
2893                                 fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen, NULL TSRMLS_CC);
2894                                 if (fcc->function_handler) {
2895                                         if (strict_class &&
2896                                             (!fcc->function_handler->common.scope ||
2897                                              !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
2898                                                 if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
2899                                                         if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
2900                                                                 efree((char*)fcc->function_handler->common.function_name);
2901                                                         }
2902                                                         efree(fcc->function_handler);
2903                                                 }
2904                                         } else {
2905                                                 retval = 1;
2906                                                 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
2907                                         }
2908                                 }
2909                         }
2910                 } else if (fcc->calling_scope) {
2911                         if (fcc->calling_scope->get_static_method) {
2912                                 fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
2913                         } else {
2914                                 fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen, NULL TSRMLS_CC);
2915                         }
2916                         if (fcc->function_handler) {
2917                                 retval = 1;
2918                                 call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
2919                                 if (call_via_handler && !fcc->object_ptr && EG(This) &&
2920                                     Z_OBJ_HT_P(EG(This))->get_class_entry &&
2921                                     instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
2922                                         fcc->object_ptr = EG(This);
2923                                 }
2924                         }
2925                 }
2926         }
2927 
2928         if (retval) {
2929                 if (fcc->calling_scope && !call_via_handler) {
2930                         if (!fcc->object_ptr && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2931                                 if (error) {
2932                                         zend_spprintf(error, 0, "cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2933                                         retval = 0;
2934                                 } else {
2935                                         zend_error(E_ERROR, "Cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2936                                 }
2937                         } else if (!fcc->object_ptr && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
2938                                 int severity;
2939                                 char *verb;
2940                                 if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2941                                         severity = E_STRICT;
2942                                         verb = "should not";
2943                                 } else {
2944                                         /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2945                                         severity = E_ERROR;
2946                                         verb = "cannot";
2947                                 }
2948                                 if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
2949                                         retval = 0;
2950                                 }
2951                                 if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
2952                                         fcc->object_ptr = EG(This);
2953                                         if (error) {
2954                                                 zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
2955                                                 if (severity == E_ERROR) {
2956                                                         retval = 0;
2957                                                 }
2958                                         } else if (retval) {
2959                                                 zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb, Z_OBJCE_P(EG(This))->name);
2960                                         }
2961                                 } else {
2962                                         if (error) {
2963                                                 zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
2964                                                 if (severity == E_ERROR) {
2965                                                         retval = 0;
2966                                                 }
2967                                         } else if (retval) {
2968                                                 zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
2969                                         }
2970                                 }
2971                         }
2972                         if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
2973                                 if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
2974                                         if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
2975                                                 if (error) {
2976                                                         if (*error) {
2977                                                                 efree(*error);
2978                                                         }
2979                                                         zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2980                                                 }
2981                                                 retval = 0;
2982                                         }
2983                                 } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
2984                                         if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
2985                                                 if (error) {
2986                                                         if (*error) {
2987                                                                 efree(*error);
2988                                                         }
2989                                                         zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2990                                                 }
2991                                                 retval = 0;
2992                                         }
2993                                 }
2994                         }
2995                 }
2996         } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
2997                 if (fcc->calling_scope) {
2998                         if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, mname);
2999                 } else {
3000                         if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname);
3001                 }
3002         }
3003         efree(lmname);
3004 
3005         if (fcc->object_ptr) {
3006                 fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
3007         }
3008         if (retval) {
3009                 fcc->initialized = 1;
3010         }
3011         return retval;
3012 }
3013 /* }}} */
3014 
3015 ZEND_API zend_bool zend_is_callable_ex(zval *callable, zval *object_ptr, uint check_flags, char **callable_name, int *callable_name_len, zend_fcall_info_cache *fcc, char **error TSRMLS_DC) /* {{{ */
3016 {
3017         zend_bool ret;
3018         int callable_name_len_local;
3019         zend_fcall_info_cache fcc_local;
3020 
3021         if (callable_name) {
3022                 *callable_name = NULL;
3023         }
3024         if (callable_name_len == NULL) {
3025                 callable_name_len = &callable_name_len_local;
3026         }
3027         if (fcc == NULL) {
3028                 fcc = &fcc_local;
3029         }
3030         if (error) {
3031                 *error = NULL;
3032         }
3033         
3034         fcc->initialized = 0;
3035         fcc->calling_scope = NULL;
3036         fcc->called_scope = NULL;
3037         fcc->function_handler = NULL;
3038         fcc->calling_scope = NULL;
3039         fcc->object_ptr = NULL;
3040 
3041         if (object_ptr && Z_TYPE_P(object_ptr) != IS_OBJECT) {
3042                 object_ptr = NULL;
3043         }
3044         if (object_ptr &&
3045             (!EG(objects_store).object_buckets || 
3046              !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) {
3047                 return 0;
3048         }
3049 
3050         switch (Z_TYPE_P(callable)) {
3051                 case IS_STRING:
3052                         if (object_ptr) {
3053                                 fcc->object_ptr = object_ptr;
3054                                 fcc->calling_scope = Z_OBJCE_P(object_ptr);
3055                                 if (callable_name) {
3056                                         char *ptr;
3057 
3058                                         *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_P(callable) + sizeof("::") - 1;
3059                                         ptr = *callable_name = emalloc(*callable_name_len + 1);
3060                                         memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
3061                                         ptr += fcc->calling_scope->name_length;
3062                                         memcpy(ptr, "::", sizeof("::") - 1);
3063                                         ptr += sizeof("::") - 1;
3064                                         memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
3065                                 }
3066                         } else if (callable_name) {
3067                                 *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
3068                                 *callable_name_len = Z_STRLEN_P(callable);
3069                         }
3070                         if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3071                                 fcc->called_scope = fcc->calling_scope;
3072                                 return 1;
3073                         }
3074 
3075                         ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
3076                         if (fcc == &fcc_local &&
3077                             fcc->function_handler &&
3078                                 ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
3079                               (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
3080                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3081                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3082                                 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3083                                         efree((char*)fcc->function_handler->common.function_name);
3084                                 }
3085                                 efree(fcc->function_handler);
3086                         }
3087                         return ret;
3088 
3089                 case IS_ARRAY:
3090                         {
3091                                 zval **method = NULL;
3092                                 zval **obj = NULL;
3093                                 int strict_class = 0;
3094 
3095                                 if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3096                                         zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj);
3097                                         zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method);
3098                                 }
3099                                 if (obj && method &&
3100                                         (Z_TYPE_PP(obj) == IS_OBJECT ||
3101                                         Z_TYPE_PP(obj) == IS_STRING) &&
3102                                         Z_TYPE_PP(method) == IS_STRING) {
3103 
3104                                         if (Z_TYPE_PP(obj) == IS_STRING) {
3105                                                 if (callable_name) {
3106                                                         char *ptr;
3107 
3108                                                         *callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::") - 1;
3109                                                         ptr = *callable_name = emalloc(*callable_name_len + 1);
3110                                                         memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
3111                                                         ptr += Z_STRLEN_PP(obj);
3112                                                         memcpy(ptr, "::", sizeof("::") - 1);
3113                                                         ptr += sizeof("::") - 1;
3114                                                         memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
3115                                                 }
3116 
3117                                                 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3118                                                         return 1;
3119                                                 }
3120 
3121                                                 if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
3122                                                         return 0;
3123                                                 }
3124 
3125                                         } else {
3126                                                 if (!EG(objects_store).object_buckets || 
3127                                                     !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) {
3128                                                         return 0;
3129                                                 }
3130 
3131                                                 fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
3132 
3133                                                 fcc->object_ptr = *obj;
3134 
3135                                                 if (callable_name) {
3136                                                         char *ptr;
3137 
3138                                                         *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
3139                                                         ptr = *callable_name = emalloc(*callable_name_len + 1);
3140                                                         memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
3141                                                         ptr += fcc->calling_scope->name_length;
3142                                                         memcpy(ptr, "::", sizeof("::") - 1);
3143                                                         ptr += sizeof("::") - 1;
3144                                                         memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
3145                                                 }
3146 
3147                                                 if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
3148                                                         fcc->called_scope = fcc->calling_scope;
3149                                                         return 1;
3150                                                 }
3151                                         }
3152 
3153                                         ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC);
3154                                         if (fcc == &fcc_local &&
3155                                             fcc->function_handler &&
3156                                                 ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
3157                                               (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
3158                                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3159                                              fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3160                                                 if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3161                                                         efree((char*)fcc->function_handler->common.function_name);
3162                                                 }
3163                                                 efree(fcc->function_handler);
3164                                         }
3165                                         return ret;
3166 
3167                                 } else {
3168                                         if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
3169                                                 if (!obj || (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT)) {
3170                                                         if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object");
3171                                                 } else {
3172                                                         if (error) zend_spprintf(error, 0, "second array member is not a valid method");
3173                                                 }
3174                                         } else {
3175                                                 if (error) zend_spprintf(error, 0, "array must have exactly two members");
3176                                         }
3177                                         if (callable_name) {
3178                                                 *callable_name = estrndup("Array", sizeof("Array")-1);
3179                                                 *callable_name_len = sizeof("Array") - 1;
3180                                         }
3181                                 }
3182                         }
3183                         return 0;
3184 
3185                 case IS_OBJECT:
3186                         if (Z_OBJ_HANDLER_P(callable, get_closure) && Z_OBJ_HANDLER_P(callable, get_closure)(callable, &fcc->calling_scope, &fcc->function_handler, &fcc->object_ptr TSRMLS_CC) == SUCCESS) {
3187                                 fcc->called_scope = fcc->calling_scope;
3188                                 if (callable_name) {
3189                                         zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
3190 
3191                                         *callable_name_len = ce->name_length + sizeof("::__invoke") - 1;
3192                                         *callable_name = emalloc(*callable_name_len + 1);
3193                                         memcpy(*callable_name, ce->name, ce->name_length);
3194                                         memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke"));
3195                                 }                                                                       
3196                                 return 1;
3197                         }
3198                         /* break missing intentionally */
3199 
3200                 default:
3201                         if (callable_name) {
3202                                 zval expr_copy;
3203                                 int use_copy;
3204 
3205                                 zend_make_printable_zval(callable, &expr_copy, &use_copy);
3206                                 *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
3207                                 *callable_name_len = Z_STRLEN(expr_copy);
3208                                 zval_dtor(&expr_copy);
3209                         }
3210                         if (error) zend_spprintf(error, 0, "no array or string given");
3211                         return 0;
3212         }
3213 }
3214 /* }}} */
3215 
3216 ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC) /* {{{ */
3217 {
3218         return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
3219 }
3220 /* }}} */
3221 
3222 ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */
3223 {
3224         zend_fcall_info_cache fcc;
3225 
3226         if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, NULL, &fcc, NULL TSRMLS_CC)) {
3227                 if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
3228                         zval_dtor(callable);
3229                         array_init(callable);
3230                         add_next_index_string(callable, fcc.calling_scope->name, 1);
3231                         add_next_index_string(callable, fcc.function_handler->common.function_name, 1);
3232                 }
3233                 if (fcc.function_handler &&
3234                         ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
3235                       (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
3236                      fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
3237                      fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
3238                         if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
3239                                 efree((char*)fcc.function_handler->common.function_name);
3240                         }
3241                         efree(fcc.function_handler);
3242                 }
3243                 return 1;
3244         }
3245         return 0;
3246 }
3247 /* }}} */
3248 
3249 ZEND_API int zend_fcall_info_init(zval *callable, uint check_flags, zend_fcall_info *fci, zend_fcall_info_cache *fcc, char **callable_name, char **error TSRMLS_DC) /* {{{ */
3250 {
3251         if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) {
3252                 return FAILURE;
3253         }
3254 
3255         fci->size = sizeof(*fci);
3256         fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
3257         fci->object_ptr = fcc->object_ptr;
3258         fci->function_name = callable;
3259         fci->retval_ptr_ptr = NULL;
3260         fci->param_count = 0;
3261         fci->params = NULL;
3262         fci->no_separation = 1;
3263         fci->symbol_table = NULL;
3264 
3265         return SUCCESS;
3266 }
3267 /* }}} */
3268 
3269 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
3270 {
3271         if (fci->params) {
3272                 if (free_mem) {
3273                         efree(fci->params);
3274                         fci->params = NULL;
3275                 }
3276         }
3277         fci->param_count = 0;
3278 }
3279 /* }}} */
3280 
3281 ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */
3282 {
3283         *param_count = fci->param_count;
3284         *params = fci->params;
3285         fci->param_count = 0;
3286         fci->params = NULL;
3287 }
3288 /* }}} */
3289 
3290 ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */
3291 {
3292         zend_fcall_info_args_clear(fci, 1);
3293         fci->param_count = param_count;
3294         fci->params = params;
3295 }
3296 /* }}} */
3297 
3298 ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
3299 {
3300         HashPosition pos;
3301         zval **arg, ***params;
3302 
3303         zend_fcall_info_args_clear(fci, !args);
3304 
3305         if (!args) {
3306                 return SUCCESS;
3307         }
3308 
3309         if (Z_TYPE_P(args) != IS_ARRAY) {
3310                 return FAILURE;
3311         }
3312 
3313         fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
3314         fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
3315 
3316         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
3317         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) {
3318                 *params++ = arg;
3319                 zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
3320         }
3321 
3322         return SUCCESS;
3323 }
3324 /* }}} */
3325 
3326 ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */
3327 {
3328         int i;
3329 
3330         if (argc < 0) {
3331                 return FAILURE;
3332         }
3333 
3334         zend_fcall_info_args_clear(fci, !argc);
3335 
3336         if (argc) {
3337                 fci->param_count = argc;
3338                 fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
3339 
3340                 for (i = 0; i < argc; ++i) {
3341                         fci->params[i] = argv[i];
3342                 }
3343         }
3344 
3345         return SUCCESS;
3346 }
3347 /* }}} */
3348 
3349 ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */
3350 {
3351         int i;
3352         zval **arg;
3353 
3354         if (argc < 0) {
3355                 return FAILURE;
3356         }
3357 
3358         zend_fcall_info_args_clear(fci, !argc);
3359 
3360         if (argc) {
3361                 fci->param_count = argc;
3362                 fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
3363 
3364                 for (i = 0; i < argc; ++i) {
3365                         arg = va_arg(*argv, zval **);
3366                         fci->params[i] = arg;
3367                 }
3368         }
3369 
3370         return SUCCESS;
3371 }
3372 /* }}} */
3373 
3374 ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */
3375 {
3376         int ret;
3377         va_list argv;
3378 
3379         va_start(argv, argc);
3380         ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv);
3381         va_end(argv);
3382 
3383         return ret;
3384 }
3385 /* }}} */
3386 
3387 ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */
3388 {
3389         zval *retval, ***org_params = NULL;
3390         int result, org_count = 0;
3391 
3392         fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
3393         if (args) {
3394                 zend_fcall_info_args_save(fci, &org_count, &org_params);
3395                 zend_fcall_info_args(fci, args TSRMLS_CC);
3396         }
3397         result = zend_call_function(fci, fcc TSRMLS_CC);
3398 
3399         if (!retval_ptr_ptr && retval) {
3400                 zval_ptr_dtor(&retval);
3401         }
3402         if (args) {
3403                 zend_fcall_info_args_restore(fci, org_count, org_params);
3404         }
3405         return result;
3406 }
3407 /* }}} */
3408 
3409 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
3410 {
3411         char *lname;
3412         int name_len = strlen(module_name);
3413         zend_module_entry *module;
3414 
3415         lname = zend_str_tolower_dup(module_name, name_len);
3416         if (zend_hash_find(&module_registry, lname, name_len + 1, (void**)&module) == FAILURE) {
3417                 efree(lname);
3418                 return NULL;
3419         }
3420         efree(lname);
3421         return module->version;
3422 }
3423 /* }}} */
3424 
3425 ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, const char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
3426 {
3427         zend_property_info property_info, *property_info_ptr;
3428         const char *interned_name;
3429         ulong h = zend_get_hash_value(name, name_length+1);
3430 
3431         if (!(access_type & ZEND_ACC_PPP_MASK)) {
3432                 access_type |= ZEND_ACC_PUBLIC;
3433         }
3434         if (access_type & ZEND_ACC_STATIC) {
3435                 if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
3436                     (property_info_ptr->flags & ZEND_ACC_STATIC) != 0) {
3437                         property_info.offset = property_info_ptr->offset;
3438                         zval_ptr_dtor(&ce->default_static_members_table[property_info.offset]);
3439                         zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
3440                 } else {
3441                         property_info.offset = ce->default_static_members_count++;
3442                         ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
3443                 }
3444                 ce->default_static_members_table[property_info.offset] = property;
3445                 if (ce->type == ZEND_USER_CLASS) {
3446                         ce->static_members_table = ce->default_static_members_table;
3447                 }
3448         } else {
3449                 if (zend_hash_quick_find(&ce->properties_info, name, name_length + 1, h, (void**)&property_info_ptr) == SUCCESS &&
3450                     (property_info_ptr->flags & ZEND_ACC_STATIC) == 0) {
3451                         property_info.offset = property_info_ptr->offset;
3452                         zval_ptr_dtor(&ce->default_properties_table[property_info.offset]);
3453                         zend_hash_quick_del(&ce->properties_info, name, name_length + 1, h);
3454                 } else {
3455                         property_info.offset = ce->default_properties_count++;
3456                         ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
3457                 }
3458                 ce->default_properties_table[property_info.offset] = property;
3459         }
3460         if (ce->type & ZEND_INTERNAL_CLASS) {
3461                 switch(Z_TYPE_P(property)) {
3462                         case IS_ARRAY:
3463                         case IS_OBJECT:
3464                         case IS_RESOURCE:
3465                                 zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
3466                                 break;
3467                         default:
3468                                 break;
3469                 }
3470         }
3471         switch (access_type & ZEND_ACC_PPP_MASK) {
3472                 case ZEND_ACC_PRIVATE: {
3473                                 char *priv_name;
3474                                 int priv_name_length;
3475 
3476                                 zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3477                                 property_info.name = priv_name;
3478                                 property_info.name_length = priv_name_length;
3479                         }
3480                         break;
3481                 case ZEND_ACC_PROTECTED: {
3482                                 char *prot_name;
3483                                 int prot_name_length;
3484 
3485                                 zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3486                                 property_info.name = prot_name;
3487                                 property_info.name_length = prot_name_length;
3488                         }
3489                         break;
3490                 case ZEND_ACC_PUBLIC:
3491                         if (IS_INTERNED(name)) {
3492                                 property_info.name = (char*)name;
3493                         } else {
3494                                 property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
3495                         }
3496                         property_info.name_length = name_length;
3497                         break;
3498         }
3499 
3500         interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
3501         if (interned_name != property_info.name) {
3502                 if (ce->type == ZEND_USER_CLASS) {
3503                         efree((char*)property_info.name);
3504                 } else {
3505                         free((char*)property_info.name);
3506                 }
3507                 property_info.name = interned_name;
3508         }
3509 
3510         property_info.flags = access_type;
3511         property_info.h = (access_type & ZEND_ACC_PUBLIC) ? h : zend_get_hash_value(property_info.name, property_info.name_length+1);
3512 
3513         property_info.doc_comment = doc_comment;
3514         property_info.doc_comment_len = doc_comment_len;
3515 
3516         property_info.ce = ce;
3517 
3518         zend_hash_quick_update(&ce->properties_info, name, name_length+1, h, &property_info, sizeof(zend_property_info), NULL);
3519 
3520         return SUCCESS;
3521 }
3522 /* }}} */
3523 
3524 ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
3525 {
3526         return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
3527 }
3528 /* }}} */
3529 
3530 ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
3531 {
3532         zval *property;
3533 
3534         if (ce->type & ZEND_INTERNAL_CLASS) {
3535                 ALLOC_PERMANENT_ZVAL(property);
3536         } else {
3537                 ALLOC_ZVAL(property);
3538         }
3539         INIT_ZVAL(*property);
3540         return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3541 }
3542 /* }}} */
3543 
3544 ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
3545 {
3546         zval *property;
3547 
3548         if (ce->type & ZEND_INTERNAL_CLASS) {
3549                 ALLOC_PERMANENT_ZVAL(property);
3550         } else {
3551                 ALLOC_ZVAL(property);
3552         }
3553         INIT_PZVAL(property);
3554         ZVAL_BOOL(property, value);
3555         return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3556 }
3557 /* }}} */
3558 
3559 ZEND_API int zend_declare_property_long(zend_class_entry *ce, const char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
3560 {
3561         zval *property;
3562 
3563         if (ce->type & ZEND_INTERNAL_CLASS) {
3564                 ALLOC_PERMANENT_ZVAL(property);
3565         } else {
3566                 ALLOC_ZVAL(property);
3567         }
3568         INIT_PZVAL(property);
3569         ZVAL_LONG(property, value);
3570         return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3571 }
3572 /* }}} */
3573 
3574 ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
3575 {
3576         zval *property;
3577 
3578         if (ce->type & ZEND_INTERNAL_CLASS) {
3579                 ALLOC_PERMANENT_ZVAL(property);
3580         } else {
3581                 ALLOC_ZVAL(property);
3582         }
3583         INIT_PZVAL(property);
3584         ZVAL_DOUBLE(property, value);
3585         return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3586 }
3587 /* }}} */
3588 
3589 ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, int name_length, const char *value, int access_type TSRMLS_DC) /* {{{ */
3590 {
3591         zval *property;
3592         int len = strlen(value);
3593 
3594         if (ce->type & ZEND_INTERNAL_CLASS) {
3595                 ALLOC_PERMANENT_ZVAL(property);
3596                 ZVAL_STRINGL(property, zend_strndup(value, len), len, 0);
3597         } else {
3598                 ALLOC_ZVAL(property);
3599                 ZVAL_STRINGL(property, value, len, 1);
3600         }
3601         INIT_PZVAL(property);
3602         return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3603 }
3604 /* }}} */
3605 
3606 ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, int name_length, const char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
3607 {
3608         zval *property;
3609 
3610         if (ce->type & ZEND_INTERNAL_CLASS) {
3611                 ALLOC_PERMANENT_ZVAL(property);
3612                 ZVAL_STRINGL(property, zend_strndup(value, value_len), value_len, 0);
3613         } else {
3614                 ALLOC_ZVAL(property);
3615                 ZVAL_STRINGL(property, value, value_len, 1);
3616         }
3617         INIT_PZVAL(property);
3618         return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3619 }
3620 /* }}} */
3621 
3622 ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
3623 {
3624         return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL);
3625 }
3626 /* }}} */
3627 
3628 ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
3629 {
3630         zval *constant;
3631 
3632         if (ce->type & ZEND_INTERNAL_CLASS) {
3633                 ALLOC_PERMANENT_ZVAL(constant);
3634         } else {
3635                 ALLOC_ZVAL(constant);
3636         }
3637         ZVAL_NULL(constant);
3638         INIT_PZVAL(constant);
3639         return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3640 }
3641 /* }}} */
3642 
3643 ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
3644 {
3645         zval *constant;
3646 
3647         if (ce->type & ZEND_INTERNAL_CLASS) {
3648                 ALLOC_PERMANENT_ZVAL(constant);
3649         } else {
3650                 ALLOC_ZVAL(constant);
3651         }
3652         ZVAL_LONG(constant, value);
3653         INIT_PZVAL(constant);
3654         return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3655 }
3656 /* }}} */
3657 
3658 ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */
3659 {
3660         zval *constant;
3661 
3662         if (ce->type & ZEND_INTERNAL_CLASS) {
3663                 ALLOC_PERMANENT_ZVAL(constant);
3664         } else {
3665                 ALLOC_ZVAL(constant);
3666         }
3667         ZVAL_BOOL(constant, value);
3668         INIT_PZVAL(constant);
3669         return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3670 }
3671 /* }}} */
3672 
3673 ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
3674 {
3675         zval *constant;
3676 
3677         if (ce->type & ZEND_INTERNAL_CLASS) {
3678                 ALLOC_PERMANENT_ZVAL(constant);
3679         } else {
3680                 ALLOC_ZVAL(constant);
3681         }
3682         ZVAL_DOUBLE(constant, value);
3683         INIT_PZVAL(constant);
3684         return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3685 }
3686 /* }}} */
3687 
3688 ZEND_API int zend_declare_class_constant_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_length TSRMLS_DC) /* {{{ */
3689 {
3690         zval *constant;
3691 
3692         if (ce->type & ZEND_INTERNAL_CLASS) {
3693                 ALLOC_PERMANENT_ZVAL(constant);
3694                 ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
3695         } else {
3696                 ALLOC_ZVAL(constant);
3697                 ZVAL_STRINGL(constant, value, value_length, 1);
3698         }
3699         INIT_PZVAL(constant);
3700         return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3701 }
3702 /* }}} */
3703 
3704 ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
3705 {
3706         return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
3707 }
3708 /* }}} */
3709 
3710 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
3711 {
3712         zval *property;
3713         zend_class_entry *old_scope = EG(scope);
3714 
3715         EG(scope) = scope;
3716 
3717         if (!Z_OBJ_HT_P(object)->write_property) {
3718                 const char *class_name;
3719                 zend_uint class_name_len;
3720 
3721                 zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
3722 
3723                 zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name);
3724         }
3725         MAKE_STD_ZVAL(property);
3726         ZVAL_STRINGL(property, name, name_length, 1);
3727         Z_OBJ_HT_P(object)->write_property(object, property, value, 0 TSRMLS_CC);
3728         zval_ptr_dtor(&property);
3729 
3730         EG(scope) = old_scope;
3731 }
3732 /* }}} */
3733 
3734 ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */
3735 {
3736         zval *tmp;
3737 
3738         ALLOC_ZVAL(tmp);
3739         Z_UNSET_ISREF_P(tmp);
3740         Z_SET_REFCOUNT_P(tmp, 0);
3741         ZVAL_NULL(tmp);
3742         zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3743 }
3744 /* }}} */
3745 
3746 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3747 {
3748         zval *tmp;
3749 
3750         ALLOC_ZVAL(tmp);
3751         Z_UNSET_ISREF_P(tmp);
3752         Z_SET_REFCOUNT_P(tmp, 0);
3753         ZVAL_BOOL(tmp, value);
3754         zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3755 }
3756 /* }}} */
3757 
3758 ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3759 {
3760         zval *tmp;
3761 
3762         ALLOC_ZVAL(tmp);
3763         Z_UNSET_ISREF_P(tmp);
3764         Z_SET_REFCOUNT_P(tmp, 0);
3765         ZVAL_LONG(tmp, value);
3766         zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3767 }
3768 /* }}} */
3769 
3770 ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
3771 {
3772         zval *tmp;
3773 
3774         ALLOC_ZVAL(tmp);
3775         Z_UNSET_ISREF_P(tmp);
3776         Z_SET_REFCOUNT_P(tmp, 0);
3777         ZVAL_DOUBLE(tmp, value);
3778         zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3779 }
3780 /* }}} */
3781 
3782 ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
3783 {
3784         zval *tmp;
3785 
3786         ALLOC_ZVAL(tmp);
3787         Z_UNSET_ISREF_P(tmp);
3788         Z_SET_REFCOUNT_P(tmp, 0);
3789         ZVAL_STRING(tmp, value, 1);
3790         zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3791 }
3792 /* }}} */
3793 
3794 ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
3795 {
3796         zval *tmp;
3797 
3798         ALLOC_ZVAL(tmp);
3799         Z_UNSET_ISREF_P(tmp);
3800         Z_SET_REFCOUNT_P(tmp, 0);
3801         ZVAL_STRINGL(tmp, value, value_len, 1);
3802         zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3803 }
3804 /* }}} */
3805 
3806 ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
3807 {
3808         zval **property;
3809         zend_class_entry *old_scope = EG(scope);
3810 
3811         EG(scope) = scope;
3812         property = zend_std_get_static_property(scope, name, name_length, 0, NULL TSRMLS_CC);
3813         EG(scope) = old_scope;
3814         if (!property) {
3815                 return FAILURE;
3816         } else {
3817                 if (*property != value) {
3818                         if (PZVAL_IS_REF(*property)) {
3819                                 zval_dtor(*property);
3820                                 Z_TYPE_PP(property) = Z_TYPE_P(value);
3821                                 (*property)->value = value->value;
3822                                 if (Z_REFCOUNT_P(value) > 0) {
3823                                         zval_copy_ctor(*property);
3824                                 } else {
3825                                         efree(value);
3826                                 }
3827                         } else {
3828                                 zval *garbage = *property;
3829 
3830                                 Z_ADDREF_P(value);
3831                                 if (PZVAL_IS_REF(value)) {
3832                                         SEPARATE_ZVAL(&value);
3833                                 }
3834                                 *property = value;
3835                                 zval_ptr_dtor(&garbage);
3836                         }
3837                 }
3838                 return SUCCESS;
3839         }
3840 }
3841 /* }}} */
3842 
3843 ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC) /* {{{ */
3844 {
3845         zval *tmp;
3846 
3847         ALLOC_ZVAL(tmp);
3848         Z_UNSET_ISREF_P(tmp);
3849         Z_SET_REFCOUNT_P(tmp, 0);
3850         ZVAL_NULL(tmp);
3851         return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3852 }
3853 /* }}} */
3854 
3855 ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3856 {
3857         zval *tmp;
3858 
3859         ALLOC_ZVAL(tmp);
3860         Z_UNSET_ISREF_P(tmp);
3861         Z_SET_REFCOUNT_P(tmp, 0);
3862         ZVAL_BOOL(tmp, value);
3863         return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3864 }
3865 /* }}} */
3866 
3867 ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3868 {
3869         zval *tmp;
3870 
3871         ALLOC_ZVAL(tmp);
3872         Z_UNSET_ISREF_P(tmp);
3873         Z_SET_REFCOUNT_P(tmp, 0);
3874         ZVAL_LONG(tmp, value);
3875         return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3876 }
3877 /* }}} */
3878 
3879 ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
3880 {
3881         zval *tmp;
3882 
3883         ALLOC_ZVAL(tmp);
3884         Z_UNSET_ISREF_P(tmp);
3885         Z_SET_REFCOUNT_P(tmp, 0);
3886         ZVAL_DOUBLE(tmp, value);
3887         return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3888 }
3889 /* }}} */
3890 
3891 ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
3892 {
3893         zval *tmp;
3894 
3895         ALLOC_ZVAL(tmp);
3896         Z_UNSET_ISREF_P(tmp);
3897         Z_SET_REFCOUNT_P(tmp, 0);
3898         ZVAL_STRING(tmp, value, 1);
3899         return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3900 }
3901 /* }}} */
3902 
3903 ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, const char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
3904 {
3905         zval *tmp;
3906 
3907         ALLOC_ZVAL(tmp);
3908         Z_UNSET_ISREF_P(tmp);
3909         Z_SET_REFCOUNT_P(tmp, 0);
3910         ZVAL_STRINGL(tmp, value, value_len, 1);
3911         return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3912 }
3913 /* }}} */
3914 
3915 ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3916 {
3917         zval *property, *value;
3918         zend_class_entry *old_scope = EG(scope);
3919 
3920         EG(scope) = scope;
3921 
3922         if (!Z_OBJ_HT_P(object)->read_property) {
3923                 const char *class_name;
3924                 zend_uint class_name_len;
3925 
3926                 zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
3927                 zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name);
3928         }
3929 
3930         MAKE_STD_ZVAL(property);
3931         ZVAL_STRINGL(property, name, name_length, 1);
3932         value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R, 0 TSRMLS_CC);
3933         zval_ptr_dtor(&property);
3934 
3935         EG(scope) = old_scope;
3936         return value;
3937 }
3938 /* }}} */
3939 
3940 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3941 {
3942         zval **property;
3943         zend_class_entry *old_scope = EG(scope);
3944 
3945         EG(scope) = scope;
3946         property = zend_std_get_static_property(scope, name, name_length, silent, NULL TSRMLS_CC);
3947         EG(scope) = old_scope;
3948 
3949         return property?*property:NULL;
3950 }
3951 /* }}} */
3952 
3953 ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */
3954 {
3955         current->handling = EG(error_handling);
3956         current->exception = EG(exception_class);
3957         current->user_handler = EG(user_error_handler);
3958         if (current->user_handler) {
3959                 Z_ADDREF_P(current->user_handler);
3960         }
3961 }
3962 /* }}} */
3963 
3964 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */
3965 {
3966         if (current) {
3967                 zend_save_error_handling(current TSRMLS_CC);
3968                 if (error_handling != EH_NORMAL && EG(user_error_handler)) {
3969                         zval_ptr_dtor(&EG(user_error_handler));
3970                         EG(user_error_handler) = NULL;
3971                 }
3972         }
3973         EG(error_handling) = error_handling;
3974         EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL;
3975 }
3976 /* }}} */
3977 
3978 ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) /* {{{ */
3979 {
3980         EG(error_handling) = saved->handling;
3981         EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL;
3982         if (saved->user_handler && saved->user_handler != EG(user_error_handler)) {
3983                 if (EG(user_error_handler)) {
3984                         zval_ptr_dtor(&EG(user_error_handler));
3985                 }
3986                 EG(user_error_handler) = saved->user_handler;
3987         } else if (saved->user_handler) {
3988                 zval_ptr_dtor(&saved->user_handler);
3989         }
3990         saved->user_handler = NULL;
3991 }
3992 /* }}} */
3993 
3994 ZEND_API const char* zend_find_alias_name(zend_class_entry *ce, const char *name, zend_uint len) /* {{{ */
3995 {
3996         zend_trait_alias *alias, **alias_ptr;
3997 
3998         if ((alias_ptr = ce->trait_aliases)) {
3999                 alias = *alias_ptr;
4000                 while (alias) {
4001                         if (alias->alias_len == len &&
4002                                 !strncasecmp(name, alias->alias, alias->alias_len)) {
4003                                 return alias->alias;
4004                         }
4005                         alias_ptr++;
4006                         alias = *alias_ptr;
4007                 }
4008         }
4009 
4010         return name;
4011 }
4012 /* }}} */
4013 
4014 ZEND_API const char* zend_resolve_method_name(zend_class_entry *ce, zend_function *f) /* {{{ */
4015 {
4016         zend_function *func;
4017         HashPosition iterator;
4018         HashTable *function_table;
4019 
4020         if (f->common.type != ZEND_USER_FUNCTION ||
4021             *(f->op_array.refcount) < 2 ||
4022             !f->common.scope ||
4023             !f->common.scope->trait_aliases) {
4024                 return f->common.function_name;
4025         }
4026 
4027         function_table = &ce->function_table;
4028         zend_hash_internal_pointer_reset_ex(function_table, &iterator);
4029         while (zend_hash_get_current_data_ex(function_table, (void **)&func, &iterator) == SUCCESS) {
4030                 if (func == f) {
4031                         char *name;
4032                         uint len;
4033                         ulong idx;
4034 
4035                         if (zend_hash_get_current_key_ex(function_table, &name, &len, &idx, 0, &iterator) != HASH_KEY_IS_STRING) {
4036                                 return f->common.function_name;
4037                         }
4038                         --len;
4039                         if (len == strlen(f->common.function_name) &&
4040                             !strncasecmp(name, f->common.function_name, len)) {
4041                                 return f->common.function_name;
4042                         }
4043                         return zend_find_alias_name(f->common.scope, name, len);
4044                 }
4045                 zend_hash_move_forward_ex(function_table, &iterator);
4046         }
4047         return f->common.function_name;
4048 }
4049 /* }}} */
4050 
4051 /*
4052  * Local variables:
4053  * tab-width: 4
4054  * c-basic-offset: 4
4055  * indent-tabs-mode: t
4056  * End:
4057  */

/* [<][>][^][v][top][bottom][index][help] */