php_spl.c 33 KB

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