root/ext/spl/php_spl.c

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

DEFINITIONS

This source file includes following definitions.
  1. PHP_GINIT_FUNCTION
  2. spl_find_ce_by_name
  3. PHP_FUNCTION
  4. PHP_FUNCTION
  5. PHP_FUNCTION
  6. PHP_FUNCTION
  7. spl_autoload
  8. PHP_FUNCTION
  9. PHP_FUNCTION
  10. autoload_func_info_dtor
  11. PHP_FUNCTION
  12. PHP_FUNCTION
  13. PHP_FUNCTION
  14. PHP_FUNCTION
  15. PHP_FUNCTION
  16. php_spl_object_hash
  17. spl_build_class_list_string
  18. PHP_MINFO_FUNCTION
  19. PHP_MINIT_FUNCTION
  20. PHP_RINIT_FUNCTION
  21. PHP_RSHUTDOWN_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Marcus Boerger <helly@php.net>                              |
  16    +----------------------------------------------------------------------+
  17  */
  18 
  19 /* $Id$ */
  20 
  21 #ifdef HAVE_CONFIG_H
  22 #include "config.h"
  23 #endif
  24 
  25 #include "php.h"
  26 #include "php_ini.h"
  27 #include "php_main.h"
  28 #include "ext/standard/info.h"
  29 #include "php_spl.h"
  30 #include "spl_functions.h"
  31 #include "spl_engine.h"
  32 #include "spl_array.h"
  33 #include "spl_directory.h"
  34 #include "spl_iterators.h"
  35 #include "spl_exceptions.h"
  36 #include "spl_observer.h"
  37 #include "spl_dllist.h"
  38 #include "spl_fixedarray.h"
  39 #include "spl_heap.h"
  40 #include "zend_exceptions.h"
  41 #include "zend_interfaces.h"
  42 #include "ext/standard/php_rand.h"
  43 #include "ext/standard/php_lcg.h"
  44 #include "main/snprintf.h"
  45 
  46 #ifdef COMPILE_DL_SPL
  47 ZEND_GET_MODULE(spl)
  48 #endif
  49 
  50 ZEND_DECLARE_MODULE_GLOBALS(spl)
  51 
  52 #define SPL_DEFAULT_FILE_EXTENSIONS ".inc,.php"
  53 
  54 /* {{{ PHP_GINIT_FUNCTION
  55  */
  56 static PHP_GINIT_FUNCTION(spl)
  57 {
  58         spl_globals->autoload_extensions     = NULL;
  59         spl_globals->autoload_functions      = NULL;
  60         spl_globals->autoload_running        = 0;
  61 }
  62 /* }}} */
  63 
  64 static zend_class_entry * spl_find_ce_by_name(zend_string *name, zend_bool autoload)
  65 {
  66         zend_class_entry *ce;
  67 
  68         if (!autoload) {
  69                 zend_string *lc_name = zend_string_alloc(ZSTR_LEN(name), 0);
  70                 zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(name), ZSTR_LEN(name));
  71 
  72                 ce = zend_hash_find_ptr(EG(class_table), lc_name);
  73                 zend_string_free(lc_name);
  74         } else {
  75                 ce = zend_lookup_class(name);
  76         }
  77         if (ce == NULL) {
  78                 php_error_docref(NULL, E_WARNING, "Class %s does not exist%s", ZSTR_VAL(name), autoload ? " and could not be loaded" : "");
  79                 return NULL;
  80         }
  81 
  82         return ce;
  83 }
  84 
  85 /* {{{ proto array class_parents(object instance [, boolean autoload = true])
  86  Return an array containing the names of all parent classes */
  87 PHP_FUNCTION(class_parents)
  88 {
  89         zval *obj;
  90         zend_class_entry *parent_class, *ce;
  91         zend_bool autoload = 1;
  92 
  93         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) {
  94                 RETURN_FALSE;
  95         }
  96 
  97         if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) {
  98                 php_error_docref(NULL, E_WARNING, "object or string expected");
  99                 RETURN_FALSE;
 100         }
 101 
 102         if (Z_TYPE_P(obj) == IS_STRING) {
 103                 if (NULL == (ce = spl_find_ce_by_name(Z_STR_P(obj), autoload))) {
 104                         RETURN_FALSE;
 105                 }
 106         } else {
 107                 ce = Z_OBJCE_P(obj);
 108         }
 109 
 110         array_init(return_value);
 111         parent_class = ce->parent;
 112         while (parent_class) {
 113                 spl_add_class_name(return_value, parent_class, 0, 0);
 114                 parent_class = parent_class->parent;
 115         }
 116 }
 117 /* }}} */
 118 
 119 /* {{{ proto array class_implements(mixed what [, bool autoload ])
 120  Return all classes and interfaces implemented by SPL */
 121 PHP_FUNCTION(class_implements)
 122 {
 123         zval *obj;
 124         zend_bool autoload = 1;
 125         zend_class_entry *ce;
 126 
 127         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) {
 128                 RETURN_FALSE;
 129         }
 130         if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) {
 131                 php_error_docref(NULL, E_WARNING, "object or string expected");
 132                 RETURN_FALSE;
 133         }
 134 
 135         if (Z_TYPE_P(obj) == IS_STRING) {
 136                 if (NULL == (ce = spl_find_ce_by_name(Z_STR_P(obj), autoload))) {
 137                         RETURN_FALSE;
 138                 }
 139         } else {
 140                 ce = Z_OBJCE_P(obj);
 141         }
 142 
 143         array_init(return_value);
 144         spl_add_interfaces(return_value, ce, 1, ZEND_ACC_INTERFACE);
 145 }
 146 /* }}} */
 147 
 148 /* {{{ proto array class_uses(mixed what [, bool autoload ])
 149  Return all traits used by a class. */
 150 PHP_FUNCTION(class_uses)
 151 {
 152         zval *obj;
 153         zend_bool autoload = 1;
 154         zend_class_entry *ce;
 155 
 156         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &obj, &autoload) == FAILURE) {
 157                 RETURN_FALSE;
 158         }
 159         if (Z_TYPE_P(obj) != IS_OBJECT && Z_TYPE_P(obj) != IS_STRING) {
 160                 php_error_docref(NULL, E_WARNING, "object or string expected");
 161                 RETURN_FALSE;
 162         }
 163 
 164         if (Z_TYPE_P(obj) == IS_STRING) {
 165                 if (NULL == (ce = spl_find_ce_by_name(Z_STR_P(obj), autoload))) {
 166                         RETURN_FALSE;
 167                 }
 168         } else {
 169                 ce = Z_OBJCE_P(obj);
 170         }
 171 
 172         array_init(return_value);
 173         spl_add_traits(return_value, ce, 1, ZEND_ACC_TRAIT);
 174 }
 175 /* }}} */
 176 
 177 #define SPL_ADD_CLASS(class_name, z_list, sub, allow, ce_flags) \
 178         spl_add_classes(spl_ce_ ## class_name, z_list, sub, allow, ce_flags)
 179 
 180 #define SPL_LIST_CLASSES(z_list, sub, allow, ce_flags) \
 181         SPL_ADD_CLASS(AppendIterator, z_list, sub, allow, ce_flags); \
 182         SPL_ADD_CLASS(ArrayIterator, z_list, sub, allow, ce_flags); \
 183         SPL_ADD_CLASS(ArrayObject, z_list, sub, allow, ce_flags); \
 184         SPL_ADD_CLASS(BadFunctionCallException, z_list, sub, allow, ce_flags); \
 185         SPL_ADD_CLASS(BadMethodCallException, z_list, sub, allow, ce_flags); \
 186         SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \
 187         SPL_ADD_CLASS(CallbackFilterIterator, z_list, sub, allow, ce_flags); \
 188         SPL_ADD_CLASS(Countable, z_list, sub, allow, ce_flags); \
 189         SPL_ADD_CLASS(DirectoryIterator, z_list, sub, allow, ce_flags); \
 190         SPL_ADD_CLASS(DomainException, z_list, sub, allow, ce_flags); \
 191         SPL_ADD_CLASS(EmptyIterator, z_list, sub, allow, ce_flags); \
 192         SPL_ADD_CLASS(FilesystemIterator, z_list, sub, allow, ce_flags); \
 193         SPL_ADD_CLASS(FilterIterator, z_list, sub, allow, ce_flags); \
 194         SPL_ADD_CLASS(GlobIterator, z_list, sub, allow, ce_flags); \
 195         SPL_ADD_CLASS(InfiniteIterator, z_list, sub, allow, ce_flags); \
 196         SPL_ADD_CLASS(InvalidArgumentException, z_list, sub, allow, ce_flags); \
 197         SPL_ADD_CLASS(IteratorIterator, z_list, sub, allow, ce_flags); \
 198         SPL_ADD_CLASS(LengthException, z_list, sub, allow, ce_flags); \
 199         SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
 200         SPL_ADD_CLASS(LogicException, z_list, sub, allow, ce_flags); \
 201         SPL_ADD_CLASS(MultipleIterator, z_list, sub, allow, ce_flags); \
 202         SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \
 203         SPL_ADD_CLASS(OuterIterator, z_list, sub, allow, ce_flags); \
 204         SPL_ADD_CLASS(OutOfBoundsException, z_list, sub, allow, ce_flags); \
 205         SPL_ADD_CLASS(OutOfRangeException, z_list, sub, allow, ce_flags); \
 206         SPL_ADD_CLASS(OverflowException, z_list, sub, allow, ce_flags); \
 207         SPL_ADD_CLASS(ParentIterator, z_list, sub, allow, ce_flags); \
 208         SPL_ADD_CLASS(RangeException, z_list, sub, allow, ce_flags); \
 209         SPL_ADD_CLASS(RecursiveArrayIterator, z_list, sub, allow, ce_flags); \
 210         SPL_ADD_CLASS(RecursiveCachingIterator, z_list, sub, allow, ce_flags); \
 211         SPL_ADD_CLASS(RecursiveCallbackFilterIterator, z_list, sub, allow, ce_flags); \
 212         SPL_ADD_CLASS(RecursiveDirectoryIterator, z_list, sub, allow, ce_flags); \
 213         SPL_ADD_CLASS(RecursiveFilterIterator, z_list, sub, allow, ce_flags); \
 214         SPL_ADD_CLASS(RecursiveIterator, z_list, sub, allow, ce_flags); \
 215         SPL_ADD_CLASS(RecursiveIteratorIterator, z_list, sub, allow, ce_flags); \
 216         SPL_ADD_CLASS(RecursiveRegexIterator, z_list, sub, allow, ce_flags); \
 217         SPL_ADD_CLASS(RecursiveTreeIterator, z_list, sub, allow, ce_flags); \
 218         SPL_ADD_CLASS(RegexIterator, z_list, sub, allow, ce_flags); \
 219         SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
 220         SPL_ADD_CLASS(SeekableIterator, z_list, sub, allow, ce_flags); \
 221         SPL_ADD_CLASS(SplDoublyLinkedList, z_list, sub, allow, ce_flags); \
 222         SPL_ADD_CLASS(SplFileInfo, z_list, sub, allow, ce_flags); \
 223         SPL_ADD_CLASS(SplFileObject, z_list, sub, allow, ce_flags); \
 224         SPL_ADD_CLASS(SplFixedArray, z_list, sub, allow, ce_flags); \
 225         SPL_ADD_CLASS(SplHeap, z_list, sub, allow, ce_flags); \
 226         SPL_ADD_CLASS(SplMinHeap, z_list, sub, allow, ce_flags); \
 227         SPL_ADD_CLASS(SplMaxHeap, z_list, sub, allow, ce_flags); \
 228         SPL_ADD_CLASS(SplObjectStorage, z_list, sub, allow, ce_flags); \
 229         SPL_ADD_CLASS(SplObserver, z_list, sub, allow, ce_flags); \
 230         SPL_ADD_CLASS(SplPriorityQueue, z_list, sub, allow, ce_flags); \
 231         SPL_ADD_CLASS(SplQueue, z_list, sub, allow, ce_flags); \
 232         SPL_ADD_CLASS(SplStack, z_list, sub, allow, ce_flags); \
 233         SPL_ADD_CLASS(SplSubject, z_list, sub, allow, ce_flags); \
 234         SPL_ADD_CLASS(SplTempFileObject, z_list, sub, allow, ce_flags); \
 235         SPL_ADD_CLASS(UnderflowException, z_list, sub, allow, ce_flags); \
 236         SPL_ADD_CLASS(UnexpectedValueException, z_list, sub, allow, ce_flags); \
 237 
 238 /* {{{ proto array spl_classes()
 239  Return an array containing the names of all clsses and interfaces defined in SPL */
 240 PHP_FUNCTION(spl_classes)
 241 {
 242         array_init(return_value);
 243 
 244         SPL_LIST_CLASSES(return_value, 0, 0, 0)
 245 }
 246 /* }}} */
 247 
 248 static int spl_autoload(zend_string *class_name, zend_string *lc_name, const char *ext, int ext_len) /* {{{ */
 249 {
 250         char *class_file;
 251         int class_file_len;
 252         zval dummy;
 253         zend_file_handle file_handle;
 254         zend_op_array *new_op_array;
 255         zval result;
 256         int ret;
 257 
 258         class_file_len = (int)spprintf(&class_file, 0, "%s%.*s", ZSTR_VAL(lc_name), ext_len, ext);
 259 
 260 #if DEFAULT_SLASH != '\\'
 261         {
 262                 char *ptr = class_file;
 263                 char *end = ptr + class_file_len;
 264 
 265                 while ((ptr = memchr(ptr, '\\', (end - ptr))) != NULL) {
 266                         *ptr = DEFAULT_SLASH;
 267                 }
 268         }
 269 #endif
 270 
 271         ret = php_stream_open_for_zend_ex(class_file, &file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE);
 272 
 273         if (ret == SUCCESS) {
 274                 zend_string *opened_path;
 275                 if (!file_handle.opened_path) {
 276                         file_handle.opened_path = zend_string_init(class_file, class_file_len, 0);
 277                 }
 278                 opened_path = zend_string_copy(file_handle.opened_path);
 279                 ZVAL_NULL(&dummy);
 280                 if (zend_hash_add(&EG(included_files), opened_path, &dummy)) {
 281                         new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE);
 282                         zend_destroy_file_handle(&file_handle);
 283                 } else {
 284                         new_op_array = NULL;
 285                         zend_file_handle_dtor(&file_handle);
 286                 }
 287                 zend_string_release(opened_path);
 288                 if (new_op_array) {
 289                         ZVAL_UNDEF(&result);
 290                         zend_execute(new_op_array, &result);
 291 
 292                         destroy_op_array(new_op_array);
 293                         efree(new_op_array);
 294                         if (!EG(exception)) {
 295                                 zval_ptr_dtor(&result);
 296                         }
 297 
 298                         efree(class_file);
 299                         return zend_hash_exists(EG(class_table), lc_name);
 300                 }
 301         }
 302         efree(class_file);
 303         return 0;
 304 } /* }}} */
 305 
 306 /* {{{ proto void spl_autoload(string class_name [, string file_extensions])
 307  Default implementation for __autoload() */
 308 PHP_FUNCTION(spl_autoload)
 309 {
 310         int found = 0, pos_len, pos1_len;
 311         char *pos, *pos1;
 312         zend_string *class_name, *lc_name, *file_exts = SPL_G(autoload_extensions);
 313 
 314         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &class_name, &file_exts) == FAILURE) {
 315                 RETURN_FALSE;
 316         }
 317 
 318         if (file_exts == NULL) { /* autoload_extensions is not initialized, set to defaults */
 319                 pos = SPL_DEFAULT_FILE_EXTENSIONS;
 320                 pos_len = sizeof(SPL_DEFAULT_FILE_EXTENSIONS) - 1;
 321         } else {
 322                 pos = ZSTR_VAL(file_exts);
 323                 pos_len = (int)ZSTR_LEN(file_exts);
 324         }
 325 
 326         lc_name = zend_string_alloc(ZSTR_LEN(class_name), 0);
 327         zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
 328         while (pos && *pos && !EG(exception)) {
 329                 pos1 = strchr(pos, ',');
 330                 if (pos1) {
 331                         pos1_len = (int)(pos1 - pos);
 332                 } else {
 333                         pos1_len = pos_len;
 334                 }
 335                 if (spl_autoload(class_name, lc_name, pos, pos1_len)) {
 336                         found = 1;
 337                         break; /* loaded */
 338                 }
 339                 pos = pos1 ? pos1 + 1 : NULL;
 340                 pos_len = pos1? pos_len - pos1_len - 1 : 0;
 341         }
 342         zend_string_free(lc_name);
 343 
 344         if (!found && !SPL_G(autoload_running)) {
 345                 /* For internal errors, we generate E_ERROR, for direct calls an exception is thrown.
 346                  * The "scope" is determined by an opcode, if it is ZEND_FETCH_CLASS we know function was called indirectly by
 347                  * the Zend engine.
 348                  */
 349                 zend_execute_data *ex = EX(prev_execute_data);
 350 
 351                 while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
 352                         ex = ex->prev_execute_data;
 353                 }
 354                 if (ex &&
 355                     ex->opline->opcode != ZEND_FETCH_CLASS &&
 356                     ex->opline->opcode != ZEND_NEW) {
 357                         zend_throw_exception_ex(spl_ce_LogicException, 0, "Class %s could not be loaded", ZSTR_VAL(class_name));
 358                 } else {
 359                         php_error_docref(NULL, E_ERROR, "Class %s could not be loaded", ZSTR_VAL(class_name));
 360                 }
 361         }
 362 } /* }}} */
 363 
 364 /* {{{ proto string spl_autoload_extensions([string file_extensions])
 365  Register and return default file extensions for spl_autoload */
 366 PHP_FUNCTION(spl_autoload_extensions)
 367 {
 368         zend_string *file_exts = NULL;
 369 
 370         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &file_exts) == FAILURE) {
 371                 return;
 372         }
 373         if (file_exts) {
 374                 if (SPL_G(autoload_extensions)) {
 375                         zend_string_release(SPL_G(autoload_extensions));
 376                 }
 377                 SPL_G(autoload_extensions) = zend_string_copy(file_exts);
 378         }
 379 
 380         if (SPL_G(autoload_extensions) == NULL) {
 381                 RETURN_STRINGL(SPL_DEFAULT_FILE_EXTENSIONS, sizeof(SPL_DEFAULT_FILE_EXTENSIONS) - 1);
 382         } else {
 383                 zend_string_addref(SPL_G(autoload_extensions));
 384                 RETURN_STR(SPL_G(autoload_extensions));
 385         }
 386 } /* }}} */
 387 
 388 typedef struct {
 389         zend_function *func_ptr;
 390         zval obj;
 391         zval closure;
 392         zend_class_entry *ce;
 393 } autoload_func_info;
 394 
 395 static void autoload_func_info_dtor(zval *element)
 396 {
 397         autoload_func_info *alfi = (autoload_func_info*)Z_PTR_P(element);
 398         if (!Z_ISUNDEF(alfi->obj)) {
 399                 zval_ptr_dtor(&alfi->obj);
 400         }
 401         if (!Z_ISUNDEF(alfi->closure)) {
 402                 zval_ptr_dtor(&alfi->closure);
 403         }
 404         efree(alfi);
 405 }
 406 
 407 /* {{{ proto void spl_autoload_call(string class_name)
 408  Try all registerd autoload function to load the requested class */
 409 PHP_FUNCTION(spl_autoload_call)
 410 {
 411         zval *class_name, *retval = NULL;
 412         zend_string *lc_name, *func_name;
 413         autoload_func_info *alfi;
 414 
 415         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE || Z_TYPE_P(class_name) != IS_STRING) {
 416                 return;
 417         }
 418 
 419         if (SPL_G(autoload_functions)) {
 420                 HashPosition pos;
 421                 zend_ulong num_idx;
 422                 int l_autoload_running = SPL_G(autoload_running);
 423                 SPL_G(autoload_running) = 1;
 424                 lc_name = zend_string_alloc(Z_STRLEN_P(class_name), 0);
 425                 zend_str_tolower_copy(ZSTR_VAL(lc_name), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
 426                 zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &pos);
 427                 while (zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &num_idx, &pos) == HASH_KEY_IS_STRING) {
 428                         alfi = zend_hash_get_current_data_ptr_ex(SPL_G(autoload_functions), &pos);
 429                         zend_call_method(Z_ISUNDEF(alfi->obj)? NULL : &alfi->obj, alfi->ce, &alfi->func_ptr, ZSTR_VAL(func_name), ZSTR_LEN(func_name), retval, 1, class_name, NULL);
 430                         zend_exception_save();
 431                         if (retval) {
 432                                 zval_ptr_dtor(retval);
 433                                 retval = NULL;
 434                         }
 435                         if (zend_hash_exists(EG(class_table), lc_name)) {
 436                                 break;
 437                         }
 438                         zend_hash_move_forward_ex(SPL_G(autoload_functions), &pos);
 439                 }
 440                 zend_exception_restore();
 441                 zend_string_free(lc_name);
 442                 SPL_G(autoload_running) = l_autoload_running;
 443         } else {
 444                 /* do not use or overwrite &EG(autoload_func) here */
 445                 zend_call_method_with_1_params(NULL, NULL, NULL, "spl_autoload", NULL, class_name);
 446         }
 447 } /* }}} */
 448 
 449 #define HT_MOVE_TAIL_TO_HEAD(ht)                                                        \
 450         do {                                                                                                    \
 451                 Bucket tmp = (ht)->arData[(ht)->nNumUsed-1];                            \
 452                 memmove((ht)->arData + 1, (ht)->arData,                                 \
 453                         sizeof(Bucket) * ((ht)->nNumUsed - 1));                         \
 454                 (ht)->arData[0] = tmp;                                                                  \
 455                 zend_hash_rehash(ht);                                                           \
 456         } while (0)
 457 
 458 /* {{{ proto bool spl_autoload_register([mixed autoload_function [, bool throw [, bool prepend]]])
 459  Register given function as __autoload() implementation */
 460 PHP_FUNCTION(spl_autoload_register)
 461 {
 462         zend_string *func_name;
 463         char *error = NULL;
 464         zend_string *lc_name;
 465         zval *zcallable = NULL;
 466         zend_bool do_throw = 1;
 467         zend_bool prepend  = 0;
 468         zend_function *spl_func_ptr;
 469         autoload_func_info alfi;
 470         zend_object *obj_ptr;
 471         zend_fcall_info_cache fcc;
 472 
 473         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|zbb", &zcallable, &do_throw, &prepend) == FAILURE) {
 474                 return;
 475         }
 476 
 477         if (ZEND_NUM_ARGS()) {
 478                 if (!zend_is_callable_ex(zcallable, NULL, IS_CALLABLE_STRICT, &func_name, &fcc, &error)) {
 479                         alfi.ce = fcc.calling_scope;
 480                         alfi.func_ptr = fcc.function_handler;
 481                         obj_ptr = fcc.object;
 482                         if (Z_TYPE_P(zcallable) == IS_ARRAY) {
 483                                 if (!obj_ptr && alfi.func_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
 484                                         if (do_throw) {
 485                                                 zend_throw_exception_ex(spl_ce_LogicException, 0, "Passed array specifies a non static method but no object (%s)", error);
 486                                         }
 487                                         if (error) {
 488                                                 efree(error);
 489                                         }
 490                                         zend_string_release(func_name);
 491                                         RETURN_FALSE;
 492                                 } else if (do_throw) {
 493                                         zend_throw_exception_ex(spl_ce_LogicException, 0, "Passed array does not specify %s %smethod (%s)", alfi.func_ptr ? "a callable" : "an existing", !obj_ptr ? "static " : "", error);
 494                                 }
 495                                 if (error) {
 496                                         efree(error);
 497                                 }
 498                                 zend_string_release(func_name);
 499                                 RETURN_FALSE;
 500                         } else if (Z_TYPE_P(zcallable) == IS_STRING) {
 501                                 if (do_throw) {
 502                                         zend_throw_exception_ex(spl_ce_LogicException, 0, "Function '%s' not %s (%s)", ZSTR_VAL(func_name), alfi.func_ptr ? "callable" : "found", error);
 503                                 }
 504                                 if (error) {
 505                                         efree(error);
 506                                 }
 507                                 zend_string_release(func_name);
 508                                 RETURN_FALSE;
 509                         } else {
 510                                 if (do_throw) {
 511                                         zend_throw_exception_ex(spl_ce_LogicException, 0, "Illegal value passed (%s)", error);
 512                                 }
 513                                 if (error) {
 514                                         efree(error);
 515                                 }
 516                                 zend_string_release(func_name);
 517                                 RETURN_FALSE;
 518                         }
 519                 } else if (fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
 520                                    fcc.function_handler->internal_function.handler == zif_spl_autoload_call) {
 521                         if (do_throw) {
 522                                 zend_throw_exception_ex(spl_ce_LogicException, 0, "Function spl_autoload_call() cannot be registered");
 523                         }
 524                         if (error) {
 525                                 efree(error);
 526                         }
 527                         zend_string_release(func_name);
 528                         RETURN_FALSE;
 529                 }
 530                 alfi.ce = fcc.calling_scope;
 531                 alfi.func_ptr = fcc.function_handler;
 532                 obj_ptr = fcc.object;
 533                 if (error) {
 534                         efree(error);
 535                 }
 536 
 537                 if (Z_TYPE_P(zcallable) == IS_OBJECT) {
 538                         ZVAL_COPY(&alfi.closure, zcallable);
 539 
 540                         lc_name = zend_string_alloc(ZSTR_LEN(func_name) + sizeof(uint32_t), 0);
 541                         zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name));
 542                         memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(func_name), &Z_OBJ_HANDLE_P(zcallable), sizeof(uint32_t));
 543                         ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0';
 544                 } else {
 545                         ZVAL_UNDEF(&alfi.closure);
 546                         lc_name = zend_string_alloc(ZSTR_LEN(func_name), 0);
 547                         zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name));
 548                 }
 549                 zend_string_release(func_name);
 550 
 551                 if (SPL_G(autoload_functions) && zend_hash_exists(SPL_G(autoload_functions), lc_name)) {
 552                         if (!Z_ISUNDEF(alfi.closure)) {
 553                                 Z_DELREF_P(&alfi.closure);
 554                         }
 555                         goto skip;
 556                 }
 557 
 558                 if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
 559                         /* add object id to the hash to ensure uniqueness, for more reference look at bug #40091 */
 560                         lc_name = zend_string_extend(lc_name, ZSTR_LEN(lc_name) + sizeof(uint32_t), 0);
 561                         memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(lc_name) - sizeof(uint32_t), &obj_ptr->handle, sizeof(uint32_t));
 562                         ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0';
 563                         ZVAL_OBJ(&alfi.obj, obj_ptr);
 564                         Z_ADDREF(alfi.obj);
 565                 } else {
 566                         ZVAL_UNDEF(&alfi.obj);
 567                 }
 568 
 569                 if (!SPL_G(autoload_functions)) {
 570                         ALLOC_HASHTABLE(SPL_G(autoload_functions));
 571                         zend_hash_init(SPL_G(autoload_functions), 1, NULL, autoload_func_info_dtor, 0);
 572                 }
 573 
 574                 spl_func_ptr = zend_hash_str_find_ptr(EG(function_table), "spl_autoload", sizeof("spl_autoload") - 1);
 575 
 576                 if (EG(autoload_func) == spl_func_ptr) { /* registered already, so we insert that first */
 577                         autoload_func_info spl_alfi;
 578 
 579                         spl_alfi.func_ptr = spl_func_ptr;
 580                         ZVAL_UNDEF(&spl_alfi.obj);
 581                         ZVAL_UNDEF(&spl_alfi.closure);
 582                         spl_alfi.ce = NULL;
 583                         zend_hash_str_add_mem(SPL_G(autoload_functions), "spl_autoload", sizeof("spl_autoload") - 1,
 584                                         &spl_alfi, sizeof(autoload_func_info));
 585                         if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
 586                                 /* Move the newly created element to the head of the hashtable */
 587                                 HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
 588                         }
 589                 }
 590 
 591                 if (zend_hash_add_mem(SPL_G(autoload_functions), lc_name, &alfi, sizeof(autoload_func_info)) == NULL) {
 592                         if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
 593                                 Z_DELREF(alfi.obj);
 594                         }
 595                         if (!Z_ISUNDEF(alfi.closure)) {
 596                                 Z_DELREF(alfi.closure);
 597                         }
 598                 }
 599                 if (prepend && SPL_G(autoload_functions)->nNumOfElements > 1) {
 600                         /* Move the newly created element to the head of the hashtable */
 601                         HT_MOVE_TAIL_TO_HEAD(SPL_G(autoload_functions));
 602                 }
 603 skip:
 604                 zend_string_release(lc_name);
 605         }
 606 
 607         if (SPL_G(autoload_functions)) {
 608                 EG(autoload_func) = zend_hash_str_find_ptr(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call") - 1);
 609         } else {
 610                 EG(autoload_func) =     zend_hash_str_find_ptr(EG(function_table), "spl_autoload", sizeof("spl_autoload") - 1);
 611         }
 612 
 613         RETURN_TRUE;
 614 } /* }}} */
 615 
 616 /* {{{ proto bool spl_autoload_unregister(mixed autoload_function)
 617  Unregister given function as __autoload() implementation */
 618 PHP_FUNCTION(spl_autoload_unregister)
 619 {
 620         zend_string *func_name = NULL;
 621         char *error = NULL;
 622         zend_string *lc_name;
 623         zval *zcallable;
 624         int success = FAILURE;
 625         zend_function *spl_func_ptr;
 626         zend_object *obj_ptr;
 627         zend_fcall_info_cache fcc;
 628 
 629         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zcallable) == FAILURE) {
 630                 return;
 631         }
 632 
 633         if (!zend_is_callable_ex(zcallable, NULL, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &fcc, &error)) {
 634                 zend_throw_exception_ex(spl_ce_LogicException, 0, "Unable to unregister invalid function (%s)", error);
 635                 if (error) {
 636                         efree(error);
 637                 }
 638                 if (func_name) {
 639                         zend_string_release(func_name);
 640                 }
 641                 RETURN_FALSE;
 642         }
 643         obj_ptr = fcc.object;
 644         if (error) {
 645                 efree(error);
 646         }
 647 
 648         if (Z_TYPE_P(zcallable) == IS_OBJECT) {
 649                 lc_name = zend_string_alloc(ZSTR_LEN(func_name) + sizeof(uint32_t), 0);
 650                 zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name));
 651                 memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(func_name), &Z_OBJ_HANDLE_P(zcallable), sizeof(uint32_t));
 652                 ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0';
 653         } else {
 654                 lc_name = zend_string_alloc(ZSTR_LEN(func_name), 0);
 655                 zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(func_name), ZSTR_LEN(func_name));
 656         }
 657         zend_string_release(func_name);
 658 
 659         if (SPL_G(autoload_functions)) {
 660                 if (ZSTR_LEN(lc_name) == sizeof("spl_autoload_call") - 1 && !strcmp(ZSTR_VAL(lc_name), "spl_autoload_call")) {
 661                         /* remove all */
 662                         if (!SPL_G(autoload_running)) {
 663                                 zend_hash_destroy(SPL_G(autoload_functions));
 664                                 FREE_HASHTABLE(SPL_G(autoload_functions));
 665                                 SPL_G(autoload_functions) = NULL;
 666                                 EG(autoload_func) = NULL;
 667                         } else {
 668                                 zend_hash_clean(SPL_G(autoload_functions));
 669                         }
 670                         success = SUCCESS;
 671                 } else {
 672                         /* remove specific */
 673                         success = zend_hash_del(SPL_G(autoload_functions), lc_name);
 674                         if (success != SUCCESS && obj_ptr) {
 675                                 lc_name = zend_string_extend(lc_name, ZSTR_LEN(lc_name) + sizeof(uint32_t), 0);
 676                                 memcpy(ZSTR_VAL(lc_name) + ZSTR_LEN(lc_name) - sizeof(uint32_t), &obj_ptr->handle, sizeof(uint32_t));
 677                                 ZSTR_VAL(lc_name)[ZSTR_LEN(lc_name)] = '\0';
 678                                 success = zend_hash_del(SPL_G(autoload_functions), lc_name);
 679                         }
 680                 }
 681         } else if (ZSTR_LEN(lc_name) == sizeof("spl_autoload")-1 && !strcmp(ZSTR_VAL(lc_name), "spl_autoload")) {
 682                 /* register single spl_autoload() */
 683                 spl_func_ptr = zend_hash_str_find_ptr(EG(function_table), "spl_autoload", sizeof("spl_autoload") - 1);
 684 
 685                 if (EG(autoload_func) == spl_func_ptr) {
 686                         success = SUCCESS;
 687                         EG(autoload_func) = NULL;
 688                 }
 689         }
 690 
 691         zend_string_release(lc_name);
 692         RETURN_BOOL(success == SUCCESS);
 693 } /* }}} */
 694 
 695 /* {{{ proto false|array spl_autoload_functions()
 696  Return all registered __autoload() functionns */
 697 PHP_FUNCTION(spl_autoload_functions)
 698 {
 699         zend_function *fptr;
 700         autoload_func_info *alfi;
 701 
 702         if (zend_parse_parameters_none() == FAILURE) {
 703                 return;
 704         }
 705 
 706         if (!EG(autoload_func)) {
 707                 if ((fptr = zend_hash_str_find_ptr(EG(function_table), ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1))) {
 708                         array_init(return_value);
 709                         add_next_index_stringl(return_value, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1);
 710                         return;
 711                 }
 712                 RETURN_FALSE;
 713         }
 714 
 715         fptr = zend_hash_str_find_ptr(EG(function_table), "spl_autoload_call", sizeof("spl_autoload_call") - 1);
 716 
 717         if (EG(autoload_func) == fptr) {
 718                 zend_string *key;
 719                 array_init(return_value);
 720                 ZEND_HASH_FOREACH_STR_KEY_PTR(SPL_G(autoload_functions), key, alfi) {
 721                         if (!Z_ISUNDEF(alfi->closure)) {
 722                                 Z_ADDREF(alfi->closure);
 723                                 add_next_index_zval(return_value, &alfi->closure);
 724                         } else if (alfi->func_ptr->common.scope) {
 725                                 zval tmp;
 726 
 727                                 array_init(&tmp);
 728                                 if (!Z_ISUNDEF(alfi->obj)) {
 729                                         Z_ADDREF(alfi->obj);
 730                                         add_next_index_zval(&tmp, &alfi->obj);
 731                                 } else {
 732                                         add_next_index_str(&tmp, zend_string_copy(alfi->ce->name));
 733                                 }
 734                                 add_next_index_str(&tmp, zend_string_copy(alfi->func_ptr->common.function_name));
 735                                 add_next_index_zval(return_value, &tmp);
 736                         } else {
 737                                 if (strncmp(ZSTR_VAL(alfi->func_ptr->common.function_name), "__lambda_func", sizeof("__lambda_func") - 1)) {
 738                                         add_next_index_str(return_value, zend_string_copy(alfi->func_ptr->common.function_name));
 739                                 } else {
 740                                         add_next_index_str(return_value, zend_string_copy(key));
 741                                 }
 742                         }
 743                 } ZEND_HASH_FOREACH_END();
 744                 return;
 745         }
 746 
 747         array_init(return_value);
 748         add_next_index_str(return_value, zend_string_copy(EG(autoload_func)->common.function_name));
 749 } /* }}} */
 750 
 751 /* {{{ proto string spl_object_hash(object obj)
 752  Return hash id for given object */
 753 PHP_FUNCTION(spl_object_hash)
 754 {
 755         zval *obj;
 756 
 757         if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
 758                 return;
 759         }
 760 
 761         RETURN_NEW_STR(php_spl_object_hash(obj));
 762 }
 763 /* }}} */
 764 
 765 PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/
 766 {
 767         intptr_t hash_handle, hash_handlers;
 768 
 769         if (!SPL_G(hash_mask_init)) {
 770                 if (!BG(mt_rand_is_seeded)) {
 771                         php_mt_srand((uint32_t)GENERATE_SEED());
 772                 }
 773 
 774                 SPL_G(hash_mask_handle)   = (intptr_t)(php_mt_rand() >> 1);
 775                 SPL_G(hash_mask_handlers) = (intptr_t)(php_mt_rand() >> 1);
 776                 SPL_G(hash_mask_init) = 1;
 777         }
 778 
 779         hash_handle   = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj);
 780         hash_handlers = SPL_G(hash_mask_handlers);
 781 
 782         return strpprintf(32, "%016lx%016lx", hash_handle, hash_handlers);
 783 }
 784 /* }}} */
 785 
 786 int spl_build_class_list_string(zval *entry, char **list) /* {{{ */
 787 {
 788         char *res;
 789 
 790         spprintf(&res, 0, "%s, %s", *list, Z_STRVAL_P(entry));
 791         efree(*list);
 792         *list = res;
 793         return ZEND_HASH_APPLY_KEEP;
 794 } /* }}} */
 795 
 796 /* {{{ PHP_MINFO(spl)
 797  */
 798 PHP_MINFO_FUNCTION(spl)
 799 {
 800         zval list;
 801         char *strg;
 802 
 803         php_info_print_table_start();
 804         php_info_print_table_header(2, "SPL support",        "enabled");
 805 
 806         array_init(&list);
 807         SPL_LIST_CLASSES(&list, 0, 1, ZEND_ACC_INTERFACE)
 808         strg = estrdup("");
 809         zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg);
 810         zval_dtor(&list);
 811         php_info_print_table_row(2, "Interfaces", strg + 2);
 812         efree(strg);
 813 
 814         array_init(&list);
 815         SPL_LIST_CLASSES(&list, 0, -1, ZEND_ACC_INTERFACE)
 816         strg = estrdup("");
 817         zend_hash_apply_with_argument(Z_ARRVAL_P(&list), (apply_func_arg_t)spl_build_class_list_string, &strg);
 818         zval_dtor(&list);
 819         php_info_print_table_row(2, "Classes", strg + 2);
 820         efree(strg);
 821 
 822         php_info_print_table_end();
 823 }
 824 /* }}} */
 825 
 826 /* {{{ arginfo */
 827 ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_to_array, 0, 0, 1)
 828         ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
 829         ZEND_ARG_INFO(0, use_keys)
 830 ZEND_END_ARG_INFO();
 831 
 832 ZEND_BEGIN_ARG_INFO(arginfo_iterator, 0)
 833         ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
 834 ZEND_END_ARG_INFO();
 835 
 836 ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_apply, 0, 0, 2)
 837         ZEND_ARG_OBJ_INFO(0, iterator, Traversable, 0)
 838         ZEND_ARG_INFO(0, function)
 839         ZEND_ARG_ARRAY_INFO(0, args, 1)
 840 ZEND_END_ARG_INFO();
 841 
 842 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_parents, 0, 0, 1)
 843         ZEND_ARG_INFO(0, instance)
 844         ZEND_ARG_INFO(0, autoload)
 845 ZEND_END_ARG_INFO()
 846 
 847 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_implements, 0, 0, 1)
 848         ZEND_ARG_INFO(0, what)
 849         ZEND_ARG_INFO(0, autoload)
 850 ZEND_END_ARG_INFO()
 851 
 852 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_uses, 0, 0, 1)
 853         ZEND_ARG_INFO(0, what)
 854         ZEND_ARG_INFO(0, autoload)
 855 ZEND_END_ARG_INFO()
 856 
 857 
 858 ZEND_BEGIN_ARG_INFO(arginfo_spl_classes, 0)
 859 ZEND_END_ARG_INFO()
 860 
 861 ZEND_BEGIN_ARG_INFO(arginfo_spl_autoload_functions, 0)
 862 ZEND_END_ARG_INFO()
 863 
 864 ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_autoload, 0, 0, 1)
 865         ZEND_ARG_INFO(0, class_name)
 866         ZEND_ARG_INFO(0, file_extensions)
 867 ZEND_END_ARG_INFO()
 868 
 869 ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_autoload_extensions, 0, 0, 0)
 870         ZEND_ARG_INFO(0, file_extensions)
 871 ZEND_END_ARG_INFO()
 872 
 873 ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_autoload_call, 0, 0, 1)
 874         ZEND_ARG_INFO(0, class_name)
 875 ZEND_END_ARG_INFO()
 876 
 877 ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_autoload_register, 0, 0, 0)
 878         ZEND_ARG_INFO(0, autoload_function)
 879         ZEND_ARG_INFO(0, throw)
 880         ZEND_ARG_INFO(0, prepend)
 881 ZEND_END_ARG_INFO()
 882 
 883 ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_autoload_unregister, 0, 0, 1)
 884         ZEND_ARG_INFO(0, autoload_function)
 885 ZEND_END_ARG_INFO()
 886 
 887 ZEND_BEGIN_ARG_INFO_EX(arginfo_spl_object_hash, 0, 0, 1)
 888         ZEND_ARG_INFO(0, obj)
 889 ZEND_END_ARG_INFO()
 890 /* }}} */
 891 
 892 /* {{{ spl_functions
 893  */
 894 const zend_function_entry spl_functions[] = {
 895         PHP_FE(spl_classes,             arginfo_spl_classes)
 896         PHP_FE(spl_autoload,            arginfo_spl_autoload)
 897         PHP_FE(spl_autoload_extensions, arginfo_spl_autoload_extensions)
 898         PHP_FE(spl_autoload_register,   arginfo_spl_autoload_register)
 899         PHP_FE(spl_autoload_unregister, arginfo_spl_autoload_unregister)
 900         PHP_FE(spl_autoload_functions,  arginfo_spl_autoload_functions)
 901         PHP_FE(spl_autoload_call,       arginfo_spl_autoload_call)
 902         PHP_FE(class_parents,           arginfo_class_parents)
 903         PHP_FE(class_implements,        arginfo_class_implements)
 904         PHP_FE(class_uses,              arginfo_class_uses)
 905         PHP_FE(spl_object_hash,         arginfo_spl_object_hash)
 906 #ifdef SPL_ITERATORS_H
 907         PHP_FE(iterator_to_array,       arginfo_iterator_to_array)
 908         PHP_FE(iterator_count,          arginfo_iterator)
 909         PHP_FE(iterator_apply,          arginfo_iterator_apply)
 910 #endif /* SPL_ITERATORS_H */
 911         PHP_FE_END
 912 };
 913 /* }}} */
 914 
 915 /* {{{ PHP_MINIT_FUNCTION(spl)
 916  */
 917 PHP_MINIT_FUNCTION(spl)
 918 {
 919         PHP_MINIT(spl_exceptions)(INIT_FUNC_ARGS_PASSTHRU);
 920         PHP_MINIT(spl_iterators)(INIT_FUNC_ARGS_PASSTHRU);
 921         PHP_MINIT(spl_array)(INIT_FUNC_ARGS_PASSTHRU);
 922         PHP_MINIT(spl_directory)(INIT_FUNC_ARGS_PASSTHRU);
 923         PHP_MINIT(spl_dllist)(INIT_FUNC_ARGS_PASSTHRU);
 924         PHP_MINIT(spl_heap)(INIT_FUNC_ARGS_PASSTHRU);
 925         PHP_MINIT(spl_fixedarray)(INIT_FUNC_ARGS_PASSTHRU);
 926         PHP_MINIT(spl_observer)(INIT_FUNC_ARGS_PASSTHRU);
 927 
 928         return SUCCESS;
 929 }
 930 /* }}} */
 931 
 932 PHP_RINIT_FUNCTION(spl) /* {{{ */
 933 {
 934         SPL_G(autoload_extensions) = NULL;
 935         SPL_G(autoload_functions) = NULL;
 936         SPL_G(hash_mask_init) = 0;
 937         return SUCCESS;
 938 } /* }}} */
 939 
 940 PHP_RSHUTDOWN_FUNCTION(spl) /* {{{ */
 941 {
 942         if (SPL_G(autoload_extensions)) {
 943                 zend_string_release(SPL_G(autoload_extensions));
 944                 SPL_G(autoload_extensions) = NULL;
 945         }
 946         if (SPL_G(autoload_functions)) {
 947                 zend_hash_destroy(SPL_G(autoload_functions));
 948                 FREE_HASHTABLE(SPL_G(autoload_functions));
 949                 SPL_G(autoload_functions) = NULL;
 950         }
 951         if (SPL_G(hash_mask_init)) {
 952                 SPL_G(hash_mask_init) = 0;
 953         }
 954         return SUCCESS;
 955 } /* }}} */
 956 
 957 /* {{{ spl_module_entry
 958  */
 959 zend_module_entry spl_module_entry = {
 960         STANDARD_MODULE_HEADER,
 961         "SPL",
 962         spl_functions,
 963         PHP_MINIT(spl),
 964         NULL,
 965         PHP_RINIT(spl),
 966         PHP_RSHUTDOWN(spl),
 967         PHP_MINFO(spl),
 968         PHP_SPL_VERSION,
 969         PHP_MODULE_GLOBALS(spl),
 970         PHP_GINIT(spl),
 971         NULL,
 972         NULL,
 973         STANDARD_MODULE_PROPERTIES_EX
 974 };
 975 /* }}} */
 976 
 977 /*
 978  * Local variables:
 979  * tab-width: 4
 980  * c-basic-offset: 4
 981  * End:
 982  * vim600: fdm=marker
 983  * vim: noet sw=4 ts=4
 984  */

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