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