1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2015 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#include "zend.h"
23#include "zend_API.h"
24#include "zend_builtin_functions.h"
25#include "zend_constants.h"
26#include "zend_ini.h"
27#include "zend_exceptions.h"
28#include "zend_extensions.h"
29#include "zend_closures.h"
30#include "zend_generators.h"
31
32#undef ZEND_TEST_EXCEPTIONS
33
34static ZEND_FUNCTION(zend_version);
35static ZEND_FUNCTION(func_num_args);
36static ZEND_FUNCTION(func_get_arg);
37static ZEND_FUNCTION(func_get_args);
38static ZEND_FUNCTION(strlen);
39static ZEND_FUNCTION(strcmp);
40static ZEND_FUNCTION(strncmp);
41static ZEND_FUNCTION(strcasecmp);
42static ZEND_FUNCTION(strncasecmp);
43static ZEND_FUNCTION(each);
44static ZEND_FUNCTION(error_reporting);
45static ZEND_FUNCTION(define);
46static ZEND_FUNCTION(defined);
47static ZEND_FUNCTION(get_class);
48static ZEND_FUNCTION(get_called_class);
49static ZEND_FUNCTION(get_parent_class);
50static ZEND_FUNCTION(method_exists);
51static ZEND_FUNCTION(property_exists);
52static ZEND_FUNCTION(class_exists);
53static ZEND_FUNCTION(interface_exists);
54static ZEND_FUNCTION(trait_exists);
55static ZEND_FUNCTION(function_exists);
56static ZEND_FUNCTION(class_alias);
57#if ZEND_DEBUG
58static ZEND_FUNCTION(leak);
59static ZEND_FUNCTION(leak_variable);
60#ifdef ZEND_TEST_EXCEPTIONS
61static ZEND_FUNCTION(crash);
62#endif
63#endif
64static ZEND_FUNCTION(get_included_files);
65static ZEND_FUNCTION(is_subclass_of);
66static ZEND_FUNCTION(is_a);
67static ZEND_FUNCTION(get_class_vars);
68static ZEND_FUNCTION(get_object_vars);
69static ZEND_FUNCTION(get_class_methods);
70static ZEND_FUNCTION(trigger_error);
71static ZEND_FUNCTION(set_error_handler);
72static ZEND_FUNCTION(restore_error_handler);
73static ZEND_FUNCTION(set_exception_handler);
74static ZEND_FUNCTION(restore_exception_handler);
75static ZEND_FUNCTION(get_declared_classes);
76static ZEND_FUNCTION(get_declared_traits);
77static ZEND_FUNCTION(get_declared_interfaces);
78static ZEND_FUNCTION(get_defined_functions);
79static ZEND_FUNCTION(get_defined_vars);
80static ZEND_FUNCTION(create_function);
81static ZEND_FUNCTION(get_resource_type);
82static ZEND_FUNCTION(get_resources);
83static ZEND_FUNCTION(get_loaded_extensions);
84static ZEND_FUNCTION(extension_loaded);
85static ZEND_FUNCTION(get_extension_funcs);
86static ZEND_FUNCTION(get_defined_constants);
87static ZEND_FUNCTION(debug_backtrace);
88static ZEND_FUNCTION(debug_print_backtrace);
89#if ZEND_DEBUG
90static ZEND_FUNCTION(zend_test_func);
91static ZEND_FUNCTION(zend_test_func2);
92#ifdef ZTS
93static ZEND_FUNCTION(zend_thread_id);
94#endif
95#endif
96static ZEND_FUNCTION(gc_mem_caches);
97static ZEND_FUNCTION(gc_collect_cycles);
98static ZEND_FUNCTION(gc_enabled);
99static ZEND_FUNCTION(gc_enable);
100static ZEND_FUNCTION(gc_disable);
101
102/* {{{ arginfo */
103ZEND_BEGIN_ARG_INFO(arginfo_zend__void, 0)
104ZEND_END_ARG_INFO()
105
106ZEND_BEGIN_ARG_INFO_EX(arginfo_func_get_arg, 0, 0, 1)
107    ZEND_ARG_INFO(0, arg_num)
108ZEND_END_ARG_INFO()
109
110ZEND_BEGIN_ARG_INFO_EX(arginfo_strlen, 0, 0, 1)
111    ZEND_ARG_INFO(0, str)
112ZEND_END_ARG_INFO()
113
114ZEND_BEGIN_ARG_INFO_EX(arginfo_strcmp, 0, 0, 2)
115    ZEND_ARG_INFO(0, str1)
116    ZEND_ARG_INFO(0, str2)
117ZEND_END_ARG_INFO()
118
119ZEND_BEGIN_ARG_INFO_EX(arginfo_strncmp, 0, 0, 3)
120    ZEND_ARG_INFO(0, str1)
121    ZEND_ARG_INFO(0, str2)
122    ZEND_ARG_INFO(0, len)
123ZEND_END_ARG_INFO()
124
125ZEND_BEGIN_ARG_INFO_EX(arginfo_each, 0, 0, 1)
126    ZEND_ARG_INFO(1, arr)
127ZEND_END_ARG_INFO()
128
129ZEND_BEGIN_ARG_INFO_EX(arginfo_error_reporting, 0, 0, 0)
130    ZEND_ARG_INFO(0, new_error_level)
131ZEND_END_ARG_INFO()
132
133ZEND_BEGIN_ARG_INFO_EX(arginfo_define, 0, 0, 2)
134    ZEND_ARG_INFO(0, constant_name)
135    ZEND_ARG_INFO(0, value)
136    ZEND_ARG_INFO(0, case_insensitive)
137ZEND_END_ARG_INFO()
138
139ZEND_BEGIN_ARG_INFO_EX(arginfo_defined, 0, 0, 1)
140    ZEND_ARG_INFO(0, constant_name)
141ZEND_END_ARG_INFO()
142
143ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class, 0, 0, 0)
144    ZEND_ARG_INFO(0, object)
145ZEND_END_ARG_INFO()
146
147ZEND_BEGIN_ARG_INFO_EX(arginfo_is_subclass_of, 0, 0, 2)
148    ZEND_ARG_INFO(0, object)
149    ZEND_ARG_INFO(0, class_name)
150    ZEND_ARG_INFO(0, allow_string)
151ZEND_END_ARG_INFO()
152
153ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_vars, 0, 0, 1)
154    ZEND_ARG_INFO(0, class_name)
155ZEND_END_ARG_INFO()
156
157ZEND_BEGIN_ARG_INFO_EX(arginfo_get_object_vars, 0, 0, 1)
158    ZEND_ARG_INFO(0, obj)
159ZEND_END_ARG_INFO()
160
161ZEND_BEGIN_ARG_INFO_EX(arginfo_get_class_methods, 0, 0, 1)
162    ZEND_ARG_INFO(0, class)
163ZEND_END_ARG_INFO()
164
165ZEND_BEGIN_ARG_INFO_EX(arginfo_method_exists, 0, 0, 2)
166    ZEND_ARG_INFO(0, object)
167    ZEND_ARG_INFO(0, method)
168ZEND_END_ARG_INFO()
169
170ZEND_BEGIN_ARG_INFO_EX(arginfo_property_exists, 0, 0, 2)
171    ZEND_ARG_INFO(0, object_or_class)
172    ZEND_ARG_INFO(0, property_name)
173ZEND_END_ARG_INFO()
174
175ZEND_BEGIN_ARG_INFO_EX(arginfo_class_exists, 0, 0, 1)
176    ZEND_ARG_INFO(0, classname)
177    ZEND_ARG_INFO(0, autoload)
178ZEND_END_ARG_INFO()
179
180ZEND_BEGIN_ARG_INFO_EX(arginfo_trait_exists, 0, 0, 1)
181    ZEND_ARG_INFO(0, traitname)
182    ZEND_ARG_INFO(0, autoload)
183ZEND_END_ARG_INFO()
184
185ZEND_BEGIN_ARG_INFO_EX(arginfo_function_exists, 0, 0, 1)
186    ZEND_ARG_INFO(0, function_name)
187ZEND_END_ARG_INFO()
188
189ZEND_BEGIN_ARG_INFO_EX(arginfo_class_alias, 0, 0, 2)
190    ZEND_ARG_INFO(0, user_class_name)
191    ZEND_ARG_INFO(0, alias_name)
192    ZEND_ARG_INFO(0, autoload)
193ZEND_END_ARG_INFO()
194
195#if ZEND_DEBUG
196ZEND_BEGIN_ARG_INFO_EX(arginfo_leak_variable, 0, 0, 1)
197    ZEND_ARG_INFO(0, variable)
198    ZEND_ARG_INFO(0, leak_data)
199ZEND_END_ARG_INFO()
200#endif
201
202ZEND_BEGIN_ARG_INFO_EX(arginfo_trigger_error, 0, 0, 1)
203    ZEND_ARG_INFO(0, message)
204    ZEND_ARG_INFO(0, error_type)
205ZEND_END_ARG_INFO()
206
207ZEND_BEGIN_ARG_INFO_EX(arginfo_set_error_handler, 0, 0, 1)
208    ZEND_ARG_INFO(0, error_handler)
209    ZEND_ARG_INFO(0, error_types)
210ZEND_END_ARG_INFO()
211
212ZEND_BEGIN_ARG_INFO_EX(arginfo_set_exception_handler, 0, 0, 1)
213    ZEND_ARG_INFO(0, exception_handler)
214ZEND_END_ARG_INFO()
215
216ZEND_BEGIN_ARG_INFO_EX(arginfo_create_function, 0, 0, 2)
217    ZEND_ARG_INFO(0, args)
218    ZEND_ARG_INFO(0, code)
219ZEND_END_ARG_INFO()
220
221ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resource_type, 0, 0, 1)
222    ZEND_ARG_INFO(0, res)
223ZEND_END_ARG_INFO()
224
225ZEND_BEGIN_ARG_INFO_EX(arginfo_get_resources, 0, 0, 0)
226    ZEND_ARG_INFO(0, type)
227ZEND_END_ARG_INFO()
228
229ZEND_BEGIN_ARG_INFO_EX(arginfo_get_loaded_extensions, 0, 0, 0)
230    ZEND_ARG_INFO(0, zend_extensions)
231ZEND_END_ARG_INFO()
232
233ZEND_BEGIN_ARG_INFO_EX(arginfo_get_defined_constants, 0, 0, 0)
234    ZEND_ARG_INFO(0, categorize)
235ZEND_END_ARG_INFO()
236
237ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_backtrace, 0, 0, 0)
238    ZEND_ARG_INFO(0, options)
239    ZEND_ARG_INFO(0, limit)
240ZEND_END_ARG_INFO()
241
242ZEND_BEGIN_ARG_INFO_EX(arginfo_debug_print_backtrace, 0, 0, 0)
243    ZEND_ARG_INFO(0, options)
244    ZEND_ARG_INFO(0, limit)
245ZEND_END_ARG_INFO()
246
247ZEND_BEGIN_ARG_INFO_EX(arginfo_extension_loaded, 0, 0, 1)
248    ZEND_ARG_INFO(0, extension_name)
249ZEND_END_ARG_INFO()
250
251#if ZEND_DEBUG
252ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_func, IS_ARRAY, NULL, 0)
253ZEND_END_ARG_INFO()
254ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO(arginfo_zend_test_func2, IS_ARRAY, NULL, 1)
255ZEND_END_ARG_INFO()
256#endif
257
258/* }}} */
259
260static const zend_function_entry builtin_functions[] = { /* {{{ */
261    ZEND_FE(zend_version,       arginfo_zend__void)
262    ZEND_FE(func_num_args,      arginfo_zend__void)
263    ZEND_FE(func_get_arg,       arginfo_func_get_arg)
264    ZEND_FE(func_get_args,      arginfo_zend__void)
265    ZEND_FE(strlen,         arginfo_strlen)
266    ZEND_FE(strcmp,         arginfo_strcmp)
267    ZEND_FE(strncmp,        arginfo_strncmp)
268    ZEND_FE(strcasecmp,     arginfo_strcmp)
269    ZEND_FE(strncasecmp,        arginfo_strncmp)
270    ZEND_FE(each,           arginfo_each)
271    ZEND_FE(error_reporting,    arginfo_error_reporting)
272    ZEND_FE(define,         arginfo_define)
273    ZEND_FE(defined,        arginfo_defined)
274    ZEND_FE(get_class,      arginfo_get_class)
275    ZEND_FE(get_called_class,   arginfo_zend__void)
276    ZEND_FE(get_parent_class,   arginfo_get_class)
277    ZEND_FE(method_exists,      arginfo_method_exists)
278    ZEND_FE(property_exists,    arginfo_property_exists)
279    ZEND_FE(class_exists,       arginfo_class_exists)
280    ZEND_FE(interface_exists,   arginfo_class_exists)
281    ZEND_FE(trait_exists,       arginfo_trait_exists)
282    ZEND_FE(function_exists,    arginfo_function_exists)
283    ZEND_FE(class_alias,        arginfo_class_alias)
284#if ZEND_DEBUG
285    ZEND_FE(leak,               NULL)
286    ZEND_FE(leak_variable,      arginfo_leak_variable)
287#ifdef ZEND_TEST_EXCEPTIONS
288    ZEND_FE(crash,              NULL)
289#endif
290#endif
291    ZEND_FE(get_included_files, arginfo_zend__void)
292    ZEND_FALIAS(get_required_files, get_included_files,     arginfo_zend__void)
293    ZEND_FE(is_subclass_of,     arginfo_is_subclass_of)
294    ZEND_FE(is_a,           arginfo_is_subclass_of)
295    ZEND_FE(get_class_vars,     arginfo_get_class_vars)
296    ZEND_FE(get_object_vars,    arginfo_get_object_vars)
297    ZEND_FE(get_class_methods,  arginfo_get_class_methods)
298    ZEND_FE(trigger_error,      arginfo_trigger_error)
299    ZEND_FALIAS(user_error,     trigger_error,      arginfo_trigger_error)
300    ZEND_FE(set_error_handler,      arginfo_set_error_handler)
301    ZEND_FE(restore_error_handler,      arginfo_zend__void)
302    ZEND_FE(set_exception_handler,      arginfo_set_exception_handler)
303    ZEND_FE(restore_exception_handler,  arginfo_zend__void)
304    ZEND_FE(get_declared_classes,       arginfo_zend__void)
305    ZEND_FE(get_declared_traits,        arginfo_zend__void)
306    ZEND_FE(get_declared_interfaces,    arginfo_zend__void)
307    ZEND_FE(get_defined_functions,      arginfo_zend__void)
308    ZEND_FE(get_defined_vars,       arginfo_zend__void)
309    ZEND_FE(create_function,        arginfo_create_function)
310    ZEND_FE(get_resource_type,      arginfo_get_resource_type)
311    ZEND_FE(get_resources,          arginfo_get_resources)
312    ZEND_FE(get_loaded_extensions,      arginfo_get_loaded_extensions)
313    ZEND_FE(extension_loaded,       arginfo_extension_loaded)
314    ZEND_FE(get_extension_funcs,        arginfo_extension_loaded)
315    ZEND_FE(get_defined_constants,      arginfo_get_defined_constants)
316    ZEND_FE(debug_backtrace,        arginfo_debug_backtrace)
317    ZEND_FE(debug_print_backtrace,      arginfo_debug_print_backtrace)
318#if ZEND_DEBUG
319    ZEND_FE(zend_test_func,     arginfo_zend_test_func)
320    ZEND_FE(zend_test_func2,    arginfo_zend_test_func2)
321#ifdef ZTS
322    ZEND_FE(zend_thread_id,     NULL)
323#endif
324#endif
325    ZEND_FE(gc_mem_caches,      arginfo_zend__void)
326    ZEND_FE(gc_collect_cycles,  arginfo_zend__void)
327    ZEND_FE(gc_enabled,         arginfo_zend__void)
328    ZEND_FE(gc_enable,      arginfo_zend__void)
329    ZEND_FE(gc_disable,         arginfo_zend__void)
330    ZEND_FE_END
331};
332/* }}} */
333
334ZEND_MINIT_FUNCTION(core) { /* {{{ */
335    zend_class_entry class_entry;
336
337    INIT_CLASS_ENTRY(class_entry, "stdClass", NULL);
338    zend_standard_class_def = zend_register_internal_class(&class_entry);
339
340    zend_register_default_classes();
341
342    return SUCCESS;
343}
344/* }}} */
345
346zend_module_entry zend_builtin_module = { /* {{{ */
347    STANDARD_MODULE_HEADER,
348    "Core",
349    builtin_functions,
350    ZEND_MINIT(core),
351    NULL,
352    NULL,
353    NULL,
354    NULL,
355    ZEND_VERSION,
356    STANDARD_MODULE_PROPERTIES
357};
358/* }}} */
359
360int zend_startup_builtin_functions(void) /* {{{ */
361{
362    zend_builtin_module.module_number = 0;
363    zend_builtin_module.type = MODULE_PERSISTENT;
364    return (EG(current_module) = zend_register_module_ex(&zend_builtin_module)) == NULL ? FAILURE : SUCCESS;
365}
366/* }}} */
367
368/* {{{ proto string zend_version(void)
369   Get the version of the Zend Engine */
370ZEND_FUNCTION(zend_version)
371{
372    RETURN_STRINGL(ZEND_VERSION, sizeof(ZEND_VERSION)-1);
373}
374/* }}} */
375
376/* {{{ proto int gc_mem_caches(void)
377   Reclaims memory used by MM caches.
378   Returns number of freed bytes */
379ZEND_FUNCTION(gc_mem_caches)
380{
381    RETURN_LONG(zend_mm_gc(zend_mm_get_heap()));
382}
383/* }}} */
384
385/* {{{ proto int gc_collect_cycles(void)
386   Forces collection of any existing garbage cycles.
387   Returns number of freed zvals */
388ZEND_FUNCTION(gc_collect_cycles)
389{
390    RETURN_LONG(gc_collect_cycles());
391}
392/* }}} */
393
394/* {{{ proto void gc_enabled(void)
395   Returns status of the circular reference collector */
396ZEND_FUNCTION(gc_enabled)
397{
398    RETURN_BOOL(GC_G(gc_enabled));
399}
400/* }}} */
401
402/* {{{ proto void gc_enable(void)
403   Activates the circular reference collector */
404ZEND_FUNCTION(gc_enable)
405{
406    zend_string *key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
407    zend_alter_ini_entry_chars(key, "1", sizeof("1")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
408    zend_string_release(key);
409}
410/* }}} */
411
412/* {{{ proto void gc_disable(void)
413   Deactivates the circular reference collector */
414ZEND_FUNCTION(gc_disable)
415{
416    zend_string *key = zend_string_init("zend.enable_gc", sizeof("zend.enable_gc")-1, 0);
417    zend_alter_ini_entry_chars(key, "0", sizeof("0")-1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME);
418    zend_string_release(key);
419}
420/* }}} */
421
422/* {{{ proto int func_num_args(void)
423   Get the number of arguments that were passed to the function */
424ZEND_FUNCTION(func_num_args)
425{
426    zend_execute_data *ex = EX(prev_execute_data);
427
428    if (!(ZEND_CALL_INFO(ex) & ZEND_CALL_CODE)) {
429        RETURN_LONG(ZEND_CALL_NUM_ARGS(ex));
430    } else {
431        zend_error(E_WARNING, "func_num_args():  Called from the global scope - no function context");
432        RETURN_LONG(-1);
433    }
434}
435/* }}} */
436
437/* {{{ proto mixed func_get_arg(int arg_num)
438   Get the $arg_num'th argument that was passed to the function */
439ZEND_FUNCTION(func_get_arg)
440{
441    uint32_t arg_count, first_extra_arg;
442    zval *arg;
443    zend_long requested_offset;
444    zend_execute_data *ex;
445
446    if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &requested_offset) == FAILURE) {
447        return;
448    }
449
450    if (requested_offset < 0) {
451        zend_error(E_WARNING, "func_get_arg():  The argument number should be >= 0");
452        RETURN_FALSE;
453    }
454
455    ex = EX(prev_execute_data);
456    if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
457        zend_error(E_WARNING, "func_get_arg():  Called from the global scope - no function context");
458        RETURN_FALSE;
459    }
460
461    arg_count = ZEND_CALL_NUM_ARGS(ex);
462
463    if (requested_offset >= arg_count) {
464        zend_error(E_WARNING, "func_get_arg():  Argument " ZEND_LONG_FMT " not passed to function", requested_offset);
465        RETURN_FALSE;
466    }
467
468    first_extra_arg = ex->func->op_array.num_args;
469    if (requested_offset >= first_extra_arg && (ZEND_CALL_NUM_ARGS(ex) > first_extra_arg)) {
470        arg = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T) + (requested_offset - first_extra_arg);
471    } else {
472        arg = ZEND_CALL_ARG(ex, requested_offset + 1);
473    }
474    ZVAL_DEREF(arg);
475    ZVAL_COPY(return_value, arg);
476}
477/* }}} */
478
479/* {{{ proto array func_get_args()
480   Get an array of the arguments that were passed to the function */
481ZEND_FUNCTION(func_get_args)
482{
483    zval *p, *q;
484    uint32_t arg_count, first_extra_arg;
485    uint32_t i;
486    zend_execute_data *ex = EX(prev_execute_data);
487
488    if (ZEND_CALL_INFO(ex) & ZEND_CALL_CODE) {
489        zend_error(E_WARNING, "func_get_args():  Called from the global scope - no function context");
490        RETURN_FALSE;
491    }
492
493    arg_count = ZEND_CALL_NUM_ARGS(ex);
494
495    array_init_size(return_value, arg_count);
496    if (arg_count) {
497        first_extra_arg = ex->func->op_array.num_args;
498        zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
499        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
500            i = 0;
501            p = ZEND_CALL_ARG(ex, 1);
502            if (arg_count > first_extra_arg) {
503                while (i < first_extra_arg) {
504                    q = p;
505                    ZVAL_DEREF(q);
506                    if (Z_OPT_REFCOUNTED_P(q)) Z_ADDREF_P(q);
507                    ZEND_HASH_FILL_ADD(q);
508                    p++;
509                    i++;
510                }
511                p = ZEND_CALL_VAR_NUM(ex, ex->func->op_array.last_var + ex->func->op_array.T);
512            }
513            while (i < arg_count) {
514                q = p;
515                ZVAL_DEREF(q);
516                if (Z_OPT_REFCOUNTED_P(q)) Z_ADDREF_P(q);
517                ZEND_HASH_FILL_ADD(q);
518                p++;
519                i++;
520            }
521        } ZEND_HASH_FILL_END();
522    }
523}
524/* }}} */
525
526/* {{{ proto int strlen(string str)
527   Get string length
528   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
529ZEND_FUNCTION(strlen)
530{
531    zend_string *s;
532
533#ifndef FAST_ZPP
534    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &s) == FAILURE) {
535        return;
536    }
537#else
538    ZEND_PARSE_PARAMETERS_START(1, 1)
539        Z_PARAM_STR(s)
540    ZEND_PARSE_PARAMETERS_END();
541#endif
542
543    RETVAL_LONG(ZSTR_LEN(s));
544}
545/* }}} */
546
547/* {{{ proto int strcmp(string str1, string str2)
548   Binary safe string comparison */
549ZEND_FUNCTION(strcmp)
550{
551    zend_string *s1, *s2;
552
553    if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
554        return;
555    }
556
557    RETURN_LONG(zend_binary_strcmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
558}
559/* }}} */
560
561/* {{{ proto int strncmp(string str1, string str2, int len)
562   Binary safe string comparison */
563ZEND_FUNCTION(strncmp)
564{
565    zend_string *s1, *s2;
566    zend_long len;
567
568    if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &s1, &s2, &len) == FAILURE) {
569        return;
570    }
571
572    if (len < 0) {
573        zend_error(E_WARNING, "Length must be greater than or equal to 0");
574        RETURN_FALSE;
575    }
576
577    RETURN_LONG(zend_binary_strncmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
578}
579/* }}} */
580
581/* {{{ proto int strcasecmp(string str1, string str2)
582   Binary safe case-insensitive string comparison */
583ZEND_FUNCTION(strcasecmp)
584{
585    zend_string *s1, *s2;
586
587    if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &s1, &s2) == FAILURE) {
588        return;
589    }
590
591    RETURN_LONG(zend_binary_strcasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2)));
592}
593/* }}} */
594
595/* {{{ proto int strncasecmp(string str1, string str2, int len)
596   Binary safe string comparison */
597ZEND_FUNCTION(strncasecmp)
598{
599    zend_string *s1, *s2;
600    zend_long len;
601
602    if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &s1, &s2, &len) == FAILURE) {
603        return;
604    }
605
606    if (len < 0) {
607        zend_error(E_WARNING, "Length must be greater than or equal to 0");
608        RETURN_FALSE;
609    }
610
611    RETURN_LONG(zend_binary_strncasecmp(ZSTR_VAL(s1), ZSTR_LEN(s1), ZSTR_VAL(s2), ZSTR_LEN(s2), len));
612}
613/* }}} */
614
615/* {{{ proto mixed each(array &arr)
616   Return the currently pointed key..value pair in the passed array, and advance the pointer to the next element, or false if there is no element at this place */
617ZEND_FUNCTION(each)
618{
619    zval *array, *entry, tmp;
620    zend_ulong num_key;
621    HashTable *target_hash;
622    zend_string *key;
623
624    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &array) == FAILURE) {
625        return;
626    }
627
628    target_hash = HASH_OF(array);
629    if (!target_hash) {
630        zend_error(E_WARNING,"Variable passed to each() is not an array or object");
631        return;
632    }
633    while (1) {
634        entry = zend_hash_get_current_data(target_hash);
635        if (!entry) {
636            RETURN_FALSE;
637        } else if (Z_TYPE_P(entry) == IS_INDIRECT) {
638            entry = Z_INDIRECT_P(entry);
639            if (Z_TYPE_P(entry) == IS_UNDEF) {
640                zend_hash_move_forward(target_hash);
641                continue;
642            }
643        }
644        break;
645    }
646    array_init_size(return_value, 4);
647    zend_hash_real_init(Z_ARRVAL_P(return_value), 0);
648
649    /* add value elements */
650    if (Z_ISREF_P(entry)) {
651        ZVAL_DUP(&tmp, Z_REFVAL_P(entry));
652        entry = &tmp;
653        if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
654    } else {
655        if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
656        if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
657    }
658    zend_hash_index_add_new(Z_ARRVAL_P(return_value), 1, entry);
659    zend_hash_str_add_new(Z_ARRVAL_P(return_value), "value", sizeof("value")-1, entry);
660
661    /* add the key elements */
662    if (zend_hash_get_current_key(target_hash, &key, &num_key) == HASH_KEY_IS_STRING) {
663        ZVAL_STR_COPY(&tmp, key);
664        if (Z_REFCOUNTED(tmp)) Z_ADDREF(tmp);
665    } else {
666        ZVAL_LONG(&tmp, num_key);
667    }
668    zend_hash_index_add_new(Z_ARRVAL_P(return_value), 0, &tmp);
669    zend_hash_str_add_new(Z_ARRVAL_P(return_value), "key", sizeof("key")-1, &tmp);
670    zend_hash_move_forward(target_hash);
671}
672/* }}} */
673
674/* {{{ proto int error_reporting([int new_error_level])
675   Return the current error_reporting level, and if an argument was passed - change to the new level */
676ZEND_FUNCTION(error_reporting)
677{
678    zval *err;
679    int old_error_reporting;
680
681#ifndef FAST_ZPP
682    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &err) == FAILURE) {
683        return;
684    }
685#else
686    ZEND_PARSE_PARAMETERS_START(0, 1)
687        Z_PARAM_OPTIONAL
688        Z_PARAM_ZVAL(err)
689    ZEND_PARSE_PARAMETERS_END();
690#endif
691
692    old_error_reporting = EG(error_reporting);
693    if(ZEND_NUM_ARGS() != 0) {
694        do {
695            zend_ini_entry *p = EG(error_reporting_ini_entry);
696
697            if (!p) {
698                p = zend_hash_str_find_ptr(EG(ini_directives), "error_reporting", sizeof("error_reporting")-1);
699                if (p) {
700                    EG(error_reporting_ini_entry) = p;
701                } else {
702                    break;
703                }
704            }
705            if (!p->modified) {
706                if (!EG(modified_ini_directives)) {
707                    ALLOC_HASHTABLE(EG(modified_ini_directives));
708                    zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
709                }
710                if (EXPECTED(zend_hash_str_add_ptr(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting")-1, p) != NULL)) {
711                    p->orig_value = p->value;
712                    p->orig_modifiable = p->modifiable;
713                    p->modified = 1;
714                }
715            } else if (p->orig_value != p->value) {
716                zend_string_release(p->value);
717            }
718
719            p->value = zval_get_string(err);
720            if (Z_TYPE_P(err) == IS_LONG) {
721                EG(error_reporting) = Z_LVAL_P(err);
722            } else {
723                EG(error_reporting) = atoi(ZSTR_VAL(p->value));
724            }
725        } while (0);
726    }
727
728    RETVAL_LONG(old_error_reporting);
729}
730/* }}} */
731
732static int validate_constant_array(HashTable *ht) /* {{{ */
733{
734    int ret = 1;
735    zval *val;
736
737    ht->u.v.nApplyCount++;
738    ZEND_HASH_FOREACH_VAL_IND(ht, val) {
739        ZVAL_DEREF(val);
740        if (Z_REFCOUNTED_P(val)) {
741            if (Z_TYPE_P(val) == IS_ARRAY) {
742                if (!Z_IMMUTABLE_P(val)) {
743                    if (Z_ARRVAL_P(val)->u.v.nApplyCount > 0) {
744                        zend_error(E_WARNING, "Constants cannot be recursive arrays");
745                        ret = 0;
746                        break;
747                    } else if (!validate_constant_array(Z_ARRVAL_P(val))) {
748                        ret = 0;
749                        break;
750                    }
751                }
752            } else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
753                zend_error(E_WARNING, "Constants may only evaluate to scalar values or arrays");
754                ret = 0;
755                break;
756            }
757        }
758    } ZEND_HASH_FOREACH_END();
759    ht->u.v.nApplyCount--;
760    return ret;
761}
762/* }}} */
763
764static void copy_constant_array(zval *dst, zval *src) /* {{{ */
765{
766    zend_string *key;
767    zend_ulong idx;
768    zval *new_val, *val;
769
770    array_init_size(dst, zend_hash_num_elements(Z_ARRVAL_P(src)));
771    ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(src), idx, key, val) {
772        /* constant arrays can't contain references */
773        ZVAL_DEREF(val);
774        if (key) {
775            new_val = zend_hash_add_new(Z_ARRVAL_P(dst), key, val);
776        } else {
777            new_val = zend_hash_index_add_new(Z_ARRVAL_P(dst), idx, val);
778        }
779        if (Z_TYPE_P(val) == IS_ARRAY) {
780            if (!Z_IMMUTABLE_P(val)) {
781                copy_constant_array(new_val, val);
782            }
783        } else if (Z_REFCOUNTED_P(val)) {
784            Z_ADDREF_P(val);
785        }
786    } ZEND_HASH_FOREACH_END();
787}
788/* }}} */
789
790/* {{{ proto bool define(string constant_name, mixed value[, boolean case_insensitive])
791   Define a new constant */
792ZEND_FUNCTION(define)
793{
794    zend_string *name;
795    zval *val, val_free;
796    zend_bool non_cs = 0;
797    int case_sensitive = CONST_CS;
798    zend_constant c;
799
800#ifndef FAST_ZPP
801    if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz|b", &name, &val, &non_cs) == FAILURE) {
802        return;
803    }
804#else
805    ZEND_PARSE_PARAMETERS_START(2, 3)
806        Z_PARAM_STR(name)
807        Z_PARAM_ZVAL(val)
808        Z_PARAM_OPTIONAL
809        Z_PARAM_BOOL(non_cs)
810    ZEND_PARSE_PARAMETERS_END();
811#endif
812
813    if(non_cs) {
814        case_sensitive = 0;
815    }
816
817    /* class constant, check if there is name and make sure class is valid & exists */
818    if (zend_memnstr(ZSTR_VAL(name), "::", sizeof("::") - 1, ZSTR_VAL(name) + ZSTR_LEN(name))) {
819        zend_error(E_WARNING, "Class constants cannot be defined or redefined");
820        RETURN_FALSE;
821    }
822
823    ZVAL_UNDEF(&val_free);
824
825repeat:
826    switch (Z_TYPE_P(val)) {
827        case IS_LONG:
828        case IS_DOUBLE:
829        case IS_STRING:
830        case IS_FALSE:
831        case IS_TRUE:
832        case IS_RESOURCE:
833        case IS_NULL:
834            break;
835        case IS_ARRAY:
836            if (!Z_IMMUTABLE_P(val)) {
837                if (!validate_constant_array(Z_ARRVAL_P(val))) {
838                    RETURN_FALSE;
839                } else {
840                    copy_constant_array(&c.value, val);
841                    goto register_constant;
842                }
843            }
844            break;
845        case IS_OBJECT:
846            if (Z_TYPE(val_free) == IS_UNDEF) {
847                if (Z_OBJ_HT_P(val)->get) {
848                    zval rv;
849                    val = Z_OBJ_HT_P(val)->get(val, &rv);
850                    ZVAL_COPY_VALUE(&val_free, val);
851                    goto repeat;
852                } else if (Z_OBJ_HT_P(val)->cast_object) {
853                    if (Z_OBJ_HT_P(val)->cast_object(val, &val_free, IS_STRING) == SUCCESS) {
854                        val = &val_free;
855                        break;
856                    }
857                }
858            }
859            /* no break */
860        default:
861            zend_error(E_WARNING, "Constants may only evaluate to scalar values or arrays");
862            zval_ptr_dtor(&val_free);
863            RETURN_FALSE;
864    }
865
866    ZVAL_DUP(&c.value, val);
867    zval_ptr_dtor(&val_free);
868register_constant:
869    c.flags = case_sensitive; /* non persistent */
870    c.name = zend_string_copy(name);
871    c.module_number = PHP_USER_CONSTANT;
872    if (zend_register_constant(&c) == SUCCESS) {
873        RETURN_TRUE;
874    } else {
875        RETURN_FALSE;
876    }
877}
878/* }}} */
879
880/* {{{ proto bool defined(string constant_name)
881   Check whether a constant exists
882   Warning: This function is special-cased by zend_compile.c and so is usually bypassed */
883ZEND_FUNCTION(defined)
884{
885    zend_string *name;
886
887#ifndef FAST_ZPP
888    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
889        return;
890    }
891#else
892    ZEND_PARSE_PARAMETERS_START(1, 1)
893        Z_PARAM_STR(name)
894    ZEND_PARSE_PARAMETERS_END();
895#endif
896
897    if (zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT)) {
898        RETURN_TRUE;
899    } else {
900        RETURN_FALSE;
901    }
902}
903/* }}} */
904
905/* {{{ proto string get_class([object object])
906   Retrieves the class name */
907ZEND_FUNCTION(get_class)
908{
909    zval *obj = NULL;
910
911    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|o!", &obj) == FAILURE) {
912        RETURN_FALSE;
913    }
914
915    if (!obj) {
916        if (EG(scope)) {
917            RETURN_STR_COPY(EG(scope)->name);
918        } else {
919            zend_error(E_WARNING, "get_class() called without object from outside a class");
920            RETURN_FALSE;
921        }
922    }
923
924    RETURN_STR_COPY(Z_OBJCE_P(obj)->name);
925}
926/* }}} */
927
928/* {{{ proto string get_called_class()
929   Retrieves the "Late Static Binding" class name */
930ZEND_FUNCTION(get_called_class)
931{
932    zend_class_entry *called_scope;
933
934    if (zend_parse_parameters_none() == FAILURE) {
935        return;
936    }
937
938    called_scope = zend_get_called_scope(execute_data);
939    if (called_scope) {
940        RETURN_STR_COPY(called_scope->name);
941    } else if (!EG(scope))  {
942        zend_error(E_WARNING, "get_called_class() called from outside a class");
943    }
944    RETURN_FALSE;
945}
946/* }}} */
947
948/* {{{ proto mixed get_parent_class([mixed object])
949   Retrieves the parent class name for object or class or current scope or false if not in a scope. */
950ZEND_FUNCTION(get_parent_class)
951{
952    zval *arg;
953    zend_class_entry *ce = NULL;
954
955    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
956        return;
957    }
958
959    if (!ZEND_NUM_ARGS()) {
960        ce = EG(scope);
961        if (ce && ce->parent) {
962            RETURN_STR_COPY(ce->parent->name);
963        } else {
964            RETURN_FALSE;
965        }
966    }
967
968    if (Z_TYPE_P(arg) == IS_OBJECT) {
969        ce = Z_OBJ_P(arg)->ce;
970    } else if (Z_TYPE_P(arg) == IS_STRING) {
971        ce = zend_lookup_class(Z_STR_P(arg));
972    }
973
974    if (ce && ce->parent) {
975        RETURN_STR_COPY(ce->parent->name);
976    } else {
977        RETURN_FALSE;
978    }
979}
980/* }}} */
981
982static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) /* {{{ */
983{
984    zval *obj;
985    zend_string *class_name;
986    zend_class_entry *instance_ce;
987    zend_class_entry *ce;
988    zend_bool allow_string = only_subclass;
989    zend_bool retval;
990
991#ifndef FAST_ZPP
992    if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS|b", &obj, &class_name, &allow_string) == FAILURE) {
993        return;
994    }
995#else
996    ZEND_PARSE_PARAMETERS_START(2, 3)
997        Z_PARAM_ZVAL(obj)
998        Z_PARAM_STR(class_name)
999        Z_PARAM_OPTIONAL
1000        Z_PARAM_BOOL(allow_string)
1001    ZEND_PARSE_PARAMETERS_END();
1002#endif
1003    /*
1004     * allow_string - is_a default is no, is_subclass_of is yes.
1005     *   if it's allowed, then the autoloader will be called if the class does not exist.
1006     *   default behaviour is different, as 'is_a' used to be used to test mixed return values
1007     *   and there is no easy way to deprecate this.
1008     */
1009
1010    if (allow_string && Z_TYPE_P(obj) == IS_STRING) {
1011        instance_ce = zend_lookup_class(Z_STR_P(obj));
1012        if (!instance_ce) {
1013            RETURN_FALSE;
1014        }
1015    } else if (Z_TYPE_P(obj) == IS_OBJECT) {
1016        instance_ce = Z_OBJCE_P(obj);
1017    } else {
1018        RETURN_FALSE;
1019    }
1020
1021    if (!only_subclass && EXPECTED(zend_string_equals(instance_ce->name, class_name))) {
1022        retval = 1;
1023    } else {
1024        ce = zend_lookup_class_ex(class_name, NULL, 0);
1025        if (!ce) {
1026            retval = 0;
1027        } else {
1028            if (only_subclass && instance_ce == ce) {
1029                retval = 0;
1030            } else {
1031                retval = instanceof_function(instance_ce, ce);
1032            }
1033        }
1034    }
1035
1036    RETURN_BOOL(retval);
1037}
1038/* }}} */
1039
1040/* {{{ proto bool is_subclass_of(mixed object_or_string, string class_name [, bool allow_string])
1041   Returns true if the object has this class as one of its parents */
1042ZEND_FUNCTION(is_subclass_of)
1043{
1044    is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1045}
1046/* }}} */
1047
1048/* {{{ proto bool is_a(mixed object_or_string, string class_name [, bool allow_string])
1049   Returns true if the first argument is an object and is this class or has this class as one of its parents, */
1050ZEND_FUNCTION(is_a)
1051{
1052    is_a_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1053}
1054/* }}} */
1055
1056/* {{{ add_class_vars */
1057static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value)
1058{
1059    zend_property_info *prop_info;
1060    zval *prop, prop_copy;
1061    zend_string *key;
1062
1063    ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
1064        if (((prop_info->flags & ZEND_ACC_SHADOW) &&
1065             prop_info->ce != EG(scope)) ||
1066            ((prop_info->flags & ZEND_ACC_PROTECTED) &&
1067             !zend_check_protected(prop_info->ce, EG(scope))) ||
1068            ((prop_info->flags & ZEND_ACC_PRIVATE) &&
1069              ce != EG(scope) &&
1070              prop_info->ce != EG(scope))) {
1071            continue;
1072        }
1073        prop = NULL;
1074        if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
1075            prop = &ce->default_static_members_table[prop_info->offset];
1076        } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
1077            prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
1078        }
1079        if (!prop || Z_TYPE_P(prop) == IS_UNDEF) {
1080            continue;
1081        }
1082
1083        /* copy: enforce read only access */
1084        ZVAL_DEREF(prop);
1085        if (UNEXPECTED(Z_COPYABLE_P(prop))) {
1086            ZVAL_DUP(&prop_copy, prop);
1087            prop = &prop_copy;
1088        } else {
1089            Z_TRY_ADDREF_P(prop);
1090        }
1091
1092        /* this is necessary to make it able to work with default array
1093         * properties, returned to user */
1094        if (Z_OPT_CONSTANT_P(prop)) {
1095            if (UNEXPECTED(zval_update_constant_ex(prop, 0, NULL) != SUCCESS)) {
1096                return;
1097            }
1098        }
1099
1100        zend_hash_add_new(Z_ARRVAL_P(return_value), key, prop);
1101    } ZEND_HASH_FOREACH_END();
1102}
1103/* }}} */
1104
1105/* {{{ proto array get_class_vars(string class_name)
1106   Returns an array of default properties of the class. */
1107ZEND_FUNCTION(get_class_vars)
1108{
1109    zend_string *class_name;
1110    zend_class_entry *ce;
1111
1112    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) {
1113        return;
1114    }
1115
1116    ce = zend_lookup_class(class_name);
1117    if (!ce) {
1118        RETURN_FALSE;
1119    } else {
1120        array_init(return_value);
1121        if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
1122            if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
1123                return;
1124            }
1125        }
1126        add_class_vars(ce, 0, return_value);
1127        add_class_vars(ce, 1, return_value);
1128    }
1129}
1130/* }}} */
1131
1132/* {{{ proto array get_object_vars(object obj)
1133   Returns an array of object properties */
1134ZEND_FUNCTION(get_object_vars)
1135{
1136    zval *obj;
1137    zval *value;
1138    HashTable *properties;
1139    zend_string *key;
1140    zend_object *zobj;
1141
1142#ifndef FAST_ZPP
1143    if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
1144        return;
1145    }
1146#else
1147    ZEND_PARSE_PARAMETERS_START(1, 1)
1148        Z_PARAM_OBJECT(obj)
1149    ZEND_PARSE_PARAMETERS_END();
1150#endif
1151
1152    if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
1153        RETURN_FALSE;
1154    }
1155
1156    properties = Z_OBJ_HT_P(obj)->get_properties(obj);
1157
1158    if (properties == NULL) {
1159        RETURN_FALSE;
1160    }
1161
1162    zobj = Z_OBJ_P(obj);
1163
1164    if (!zobj->ce->default_properties_count && properties == zobj->properties) {
1165        /* fast copy */
1166        if (EXPECTED(zobj->handlers == &std_object_handlers)) {
1167            if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
1168                GC_REFCOUNT(properties)++;
1169            }
1170            RETURN_ARR(properties);
1171        }
1172        RETURN_ARR(zend_array_dup(properties));
1173    } else {
1174        array_init_size(return_value, zend_hash_num_elements(properties));
1175
1176        ZEND_HASH_FOREACH_STR_KEY_VAL_IND(properties, key, value) {
1177            if (key) {
1178                if (zend_check_property_access(zobj, key) == SUCCESS) {
1179                    /* Not separating references */
1180                    if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
1181                    if (ZSTR_VAL(key)[0] == 0) {
1182                        const char *prop_name, *class_name;
1183                        size_t prop_len;
1184                        zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len);
1185                        zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value);
1186                    } else {
1187                        zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
1188                    }
1189                }
1190            }
1191        } ZEND_HASH_FOREACH_END();
1192    }
1193}
1194/* }}} */
1195
1196static int same_name(zend_string *key, zend_string *name) /* {{{ */
1197{
1198    zend_string *lcname;
1199    int ret;
1200
1201    if (key == name) {
1202        return 1;
1203    }
1204    if (ZSTR_LEN(key) != ZSTR_LEN(name)) {
1205        return 0;
1206    }
1207    lcname = zend_string_tolower(name);
1208    ret = memcmp(ZSTR_VAL(lcname), ZSTR_VAL(key), ZSTR_LEN(key)) == 0;
1209    zend_string_release(lcname);
1210    return ret;
1211}
1212/* }}} */
1213
1214/* {{{ proto array get_class_methods(mixed class)
1215   Returns an array of method names for class or class instance. */
1216ZEND_FUNCTION(get_class_methods)
1217{
1218    zval *klass;
1219    zval method_name;
1220    zend_class_entry *ce = NULL;
1221    zend_function *mptr;
1222    zend_string *key;
1223
1224    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &klass) == FAILURE) {
1225        return;
1226    }
1227
1228    if (Z_TYPE_P(klass) == IS_OBJECT) {
1229        ce = Z_OBJCE_P(klass);
1230    } else if (Z_TYPE_P(klass) == IS_STRING) {
1231        ce = zend_lookup_class(Z_STR_P(klass));
1232    }
1233
1234    if (!ce) {
1235        RETURN_NULL();
1236    }
1237
1238    array_init(return_value);
1239
1240    ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) {
1241
1242        if ((mptr->common.fn_flags & ZEND_ACC_PUBLIC)
1243         || (EG(scope) &&
1244             (((mptr->common.fn_flags & ZEND_ACC_PROTECTED) &&
1245               zend_check_protected(mptr->common.scope, EG(scope)))
1246           || ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
1247               EG(scope) == mptr->common.scope)))) {
1248            size_t len = ZSTR_LEN(mptr->common.function_name);
1249
1250            /* Do not display old-style inherited constructors */
1251            if (!key) {
1252                ZVAL_STR_COPY(&method_name, mptr->common.function_name);
1253                zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
1254            } else if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0 ||
1255                mptr->common.scope == ce ||
1256                zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0) {
1257
1258                if (mptr->type == ZEND_USER_FUNCTION &&
1259                    (!mptr->op_array.refcount || *mptr->op_array.refcount > 1) &&
1260                     !same_name(key, mptr->common.function_name)) {
1261                    ZVAL_STR_COPY(&method_name, zend_find_alias_name(mptr->common.scope, key));
1262                    zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
1263                } else {
1264                    ZVAL_STR_COPY(&method_name, mptr->common.function_name);
1265                    zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &method_name);
1266                }
1267            }
1268        }
1269    } ZEND_HASH_FOREACH_END();
1270}
1271/* }}} */
1272
1273/* {{{ proto bool method_exists(object object, string method)
1274   Checks if the class method exists */
1275ZEND_FUNCTION(method_exists)
1276{
1277    zval *klass;
1278    zend_string *method_name;
1279    zend_string *lcname;
1280    zend_class_entry * ce;
1281
1282#ifndef FAST_ZPP
1283    if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &klass, &method_name) == FAILURE) {
1284        return;
1285    }
1286#else
1287    ZEND_PARSE_PARAMETERS_START(2, 2)
1288        Z_PARAM_ZVAL(klass)
1289        Z_PARAM_STR(method_name)
1290    ZEND_PARSE_PARAMETERS_END();
1291#endif
1292    if (Z_TYPE_P(klass) == IS_OBJECT) {
1293        ce = Z_OBJCE_P(klass);
1294    } else if (Z_TYPE_P(klass) == IS_STRING) {
1295        if ((ce = zend_lookup_class(Z_STR_P(klass))) == NULL) {
1296            RETURN_FALSE;
1297        }
1298    } else {
1299        RETURN_FALSE;
1300    }
1301
1302    lcname = zend_string_tolower(method_name);
1303    if (zend_hash_exists(&ce->function_table, lcname)) {
1304        zend_string_release(lcname);
1305        RETURN_TRUE;
1306    } else {
1307        union _zend_function *func = NULL;
1308
1309        if (Z_TYPE_P(klass) == IS_OBJECT
1310        && Z_OBJ_HT_P(klass)->get_method != NULL
1311        && (func = Z_OBJ_HT_P(klass)->get_method(&Z_OBJ_P(klass), method_name, NULL)) != NULL
1312        ) {
1313            if (func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
1314                /* Returns true to the fake Closure's __invoke */
1315                RETVAL_BOOL(func->common.scope == zend_ce_closure
1316                    && zend_string_equals_literal(method_name, ZEND_INVOKE_FUNC_NAME));
1317
1318                zend_string_release(lcname);
1319                zend_string_release(func->common.function_name);
1320                zend_free_trampoline(func);
1321                return;
1322            }
1323            zend_string_release(lcname);
1324            RETURN_TRUE;
1325        }
1326    }
1327    zend_string_release(lcname);
1328    RETURN_FALSE;
1329}
1330/* }}} */
1331
1332/* {{{ proto bool property_exists(mixed object_or_class, string property_name)
1333   Checks if the object or class has a property */
1334ZEND_FUNCTION(property_exists)
1335{
1336    zval *object;
1337    zend_string *property;
1338    zend_class_entry *ce;
1339    zend_property_info *property_info;
1340    zval property_z;
1341
1342    if (zend_parse_parameters(ZEND_NUM_ARGS(), "zS", &object, &property) == FAILURE) {
1343        return;
1344    }
1345
1346    if (property == NULL) {
1347        RETURN_FALSE;
1348    }
1349
1350    if (Z_TYPE_P(object) == IS_STRING) {
1351        ce = zend_lookup_class(Z_STR_P(object));
1352        if (!ce) {
1353            RETURN_FALSE;
1354        }
1355    } else if (Z_TYPE_P(object) == IS_OBJECT) {
1356        ce = Z_OBJCE_P(object);
1357    } else {
1358        zend_error(E_WARNING, "First parameter must either be an object or the name of an existing class");
1359        RETURN_NULL();
1360    }
1361
1362    if ((property_info = zend_hash_find_ptr(&ce->properties_info, property)) != NULL
1363        && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
1364        RETURN_TRUE;
1365    }
1366
1367    ZVAL_STR(&property_z, property);
1368
1369    if (Z_TYPE_P(object) ==  IS_OBJECT &&
1370        Z_OBJ_HANDLER_P(object, has_property) &&
1371        Z_OBJ_HANDLER_P(object, has_property)(object, &property_z, 2, NULL)) {
1372        RETURN_TRUE;
1373    }
1374    RETURN_FALSE;
1375}
1376/* }}} */
1377
1378/* {{{ proto bool class_exists(string classname [, bool autoload])
1379   Checks if the class exists */
1380ZEND_FUNCTION(class_exists)
1381{
1382    zend_string *class_name;
1383    zend_string *lc_name;
1384    zend_class_entry *ce;
1385    zend_bool autoload = 1;
1386
1387#ifndef FAST_ZPP
1388    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &class_name, &autoload) == FAILURE) {
1389        return;
1390    }
1391#else
1392    ZEND_PARSE_PARAMETERS_START(1, 2)
1393        Z_PARAM_STR(class_name)
1394        Z_PARAM_OPTIONAL
1395        Z_PARAM_BOOL(autoload)
1396    ZEND_PARSE_PARAMETERS_END();
1397#endif
1398
1399    if (!autoload) {
1400        if (ZSTR_VAL(class_name)[0] == '\\') {
1401            /* Ignore leading "\" */
1402            lc_name = zend_string_alloc(ZSTR_LEN(class_name) - 1, 0);
1403            zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1);
1404        } else {
1405            lc_name = zend_string_tolower(class_name);
1406        }
1407
1408        ce = zend_hash_find_ptr(EG(class_table), lc_name);
1409        zend_string_release(lc_name);
1410    } else {
1411        ce = zend_lookup_class(class_name);
1412    }
1413
1414    if (ce) {
1415        RETURN_BOOL((ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT)) == 0);
1416    } else {
1417        RETURN_FALSE;
1418    }
1419}
1420/* }}} */
1421
1422/* {{{ proto bool interface_exists(string classname [, bool autoload])
1423   Checks if the class exists */
1424ZEND_FUNCTION(interface_exists)
1425{
1426    zend_string *iface_name, *lc_name;
1427    zend_class_entry *ce;
1428    zend_bool autoload = 1;
1429
1430#ifndef FAST_ZPP
1431    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &iface_name, &autoload) == FAILURE) {
1432        return;
1433    }
1434#else
1435    ZEND_PARSE_PARAMETERS_START(1, 2)
1436        Z_PARAM_STR(iface_name)
1437        Z_PARAM_OPTIONAL
1438        Z_PARAM_BOOL(autoload)
1439    ZEND_PARSE_PARAMETERS_END();
1440#endif
1441
1442    if (!autoload) {
1443        if (ZSTR_VAL(iface_name)[0] == '\\') {
1444            /* Ignore leading "\" */
1445            lc_name = zend_string_alloc(ZSTR_LEN(iface_name) - 1, 0);
1446            zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(iface_name) + 1, ZSTR_LEN(iface_name) - 1);
1447        } else {
1448            lc_name = zend_string_tolower(iface_name);
1449        }
1450        ce = zend_hash_find_ptr(EG(class_table), lc_name);
1451        zend_string_release(lc_name);
1452        RETURN_BOOL(ce && ce->ce_flags & ZEND_ACC_INTERFACE);
1453    }
1454
1455    ce = zend_lookup_class(iface_name);
1456    if (ce) {
1457        RETURN_BOOL((ce->ce_flags & ZEND_ACC_INTERFACE) > 0);
1458    } else {
1459        RETURN_FALSE;
1460    }
1461}
1462/* }}} */
1463
1464/* {{{ proto bool trait_exists(string traitname [, bool autoload])
1465 Checks if the trait exists */
1466ZEND_FUNCTION(trait_exists)
1467{
1468    zend_string *trait_name, *lc_name;
1469    zend_class_entry *ce;
1470    zend_bool autoload = 1;
1471
1472#ifndef FAST_ZPP
1473    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|b", &trait_name, &autoload) == FAILURE) {
1474        return;
1475    }
1476#else
1477    ZEND_PARSE_PARAMETERS_START(1, 2)
1478        Z_PARAM_STR(trait_name)
1479        Z_PARAM_OPTIONAL
1480        Z_PARAM_BOOL(autoload)
1481    ZEND_PARSE_PARAMETERS_END();
1482#endif
1483
1484    if (!autoload) {
1485        if (ZSTR_VAL(trait_name)[0] == '\\') {
1486            /* Ignore leading "\" */
1487            lc_name = zend_string_alloc(ZSTR_LEN(trait_name) - 1, 0);
1488            zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(trait_name) + 1, ZSTR_LEN(trait_name) - 1);
1489        } else {
1490            lc_name = zend_string_tolower(trait_name);
1491        }
1492
1493        ce = zend_hash_find_ptr(EG(class_table), lc_name);
1494        zend_string_release(lc_name);
1495    } else {
1496        ce = zend_lookup_class(trait_name);
1497    }
1498
1499    if (ce) {
1500        RETURN_BOOL((ce->ce_flags & ZEND_ACC_TRAIT) != 0);
1501    } else {
1502        RETURN_FALSE;
1503    }
1504}
1505/* }}} */
1506
1507/* {{{ proto bool function_exists(string function_name)
1508   Checks if the function exists */
1509ZEND_FUNCTION(function_exists)
1510{
1511    zend_string *name;
1512    zend_function *func;
1513    zend_string *lcname;
1514
1515#ifndef FAST_ZPP
1516    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
1517        return;
1518    }
1519#else
1520    ZEND_PARSE_PARAMETERS_START(1, 1)
1521        Z_PARAM_STR(name)
1522    ZEND_PARSE_PARAMETERS_END();
1523#endif
1524
1525    if (ZSTR_VAL(name)[0] == '\\') {
1526        /* Ignore leading "\" */
1527        lcname = zend_string_alloc(ZSTR_LEN(name) - 1, 0);
1528        zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1);
1529    } else {
1530        lcname = zend_string_tolower(name);
1531    }
1532
1533    func = zend_hash_find_ptr(EG(function_table), lcname);
1534    zend_string_release(lcname);
1535
1536    /*
1537     * A bit of a hack, but not a bad one: we see if the handler of the function
1538     * is actually one that displays "function is disabled" message.
1539     */
1540    RETURN_BOOL(func && (func->type != ZEND_INTERNAL_FUNCTION ||
1541        func->internal_function.handler != zif_display_disabled_function));
1542}
1543/* }}} */
1544
1545/* {{{ proto bool class_alias(string user_class_name , string alias_name [, bool autoload])
1546   Creates an alias for user defined class */
1547ZEND_FUNCTION(class_alias)
1548{
1549    zend_string *class_name;
1550    char *alias_name;
1551    zend_class_entry *ce;
1552    size_t alias_name_len;
1553    zend_bool autoload = 1;
1554
1555    if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ss|b", &class_name, &alias_name, &alias_name_len, &autoload) == FAILURE) {
1556        return;
1557    }
1558
1559    ce = zend_lookup_class_ex(class_name, NULL, autoload);
1560
1561    if (ce) {
1562        if (ce->type == ZEND_USER_CLASS) {
1563            if (zend_register_class_alias_ex(alias_name, alias_name_len, ce) == SUCCESS) {
1564                RETURN_TRUE;
1565            } else {
1566                zend_error(E_WARNING, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), alias_name);
1567                RETURN_FALSE;
1568            }
1569        } else {
1570            zend_error(E_WARNING, "First argument of class_alias() must be a name of user defined class");
1571            RETURN_FALSE;
1572        }
1573    } else {
1574        zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name));
1575        RETURN_FALSE;
1576    }
1577}
1578/* }}} */
1579
1580#if ZEND_DEBUG
1581/* {{{ proto void leak([int num_bytes])
1582   Cause an intentional memory leak, for testing/debugging purposes */
1583ZEND_FUNCTION(leak)
1584{
1585    zend_long leakbytes = 3;
1586
1587    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &leakbytes) == FAILURE) {
1588        return;
1589    }
1590
1591    emalloc(leakbytes);
1592}
1593/* }}} */
1594
1595/* {{{ proto void leak_variable(mixed variable [, bool leak_data])
1596   Leak a variable that is a resource or an object */
1597ZEND_FUNCTION(leak_variable)
1598{
1599    zval *zv;
1600    zend_bool leak_data = 0;
1601
1602    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &zv, &leak_data) == FAILURE) {
1603        return;
1604    }
1605
1606    if (!leak_data) {
1607        Z_ADDREF_P(zv);
1608    } else if (Z_TYPE_P(zv) == IS_RESOURCE) {
1609        Z_ADDREF_P(zv);
1610    } else if (Z_TYPE_P(zv) == IS_OBJECT) {
1611        Z_ADDREF_P(zv);
1612    } else {
1613        zend_error(E_WARNING, "Leaking non-zval data is only applicable to resources and objects");
1614    }
1615}
1616/* }}} */
1617
1618
1619#ifdef ZEND_TEST_EXCEPTIONS
1620/* {{{ proto void crash(void)
1621   Crash the script */
1622ZEND_FUNCTION(crash)
1623{
1624    char *nowhere = NULL;
1625
1626    if (zend_parse_parameters_none() == FAILURE) {
1627        return;
1628    }
1629
1630    memcpy(nowhere, "something", sizeof("something"));
1631}
1632/* }}} */
1633#endif
1634
1635#endif /* ZEND_DEBUG */
1636
1637/* {{{ proto array get_included_files(void)
1638   Returns an array with the file names that were include_once()'d */
1639ZEND_FUNCTION(get_included_files)
1640{
1641    zend_string *entry;
1642
1643    if (zend_parse_parameters_none() == FAILURE) {
1644        return;
1645    }
1646
1647    array_init(return_value);
1648    ZEND_HASH_FOREACH_STR_KEY(&EG(included_files), entry) {
1649        if (entry) {
1650            add_next_index_str(return_value, zend_string_copy(entry));
1651        }
1652    } ZEND_HASH_FOREACH_END();
1653}
1654/* }}} */
1655
1656/* {{{ proto void trigger_error(string message [, int error_type])
1657   Generates a user-level error/warning/notice message */
1658ZEND_FUNCTION(trigger_error)
1659{
1660    zend_long error_type = E_USER_NOTICE;
1661    char *message;
1662    size_t message_len;
1663
1664    if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &message, &message_len, &error_type) == FAILURE) {
1665        return;
1666    }
1667
1668    switch (error_type) {
1669        case E_USER_ERROR:
1670        case E_USER_WARNING:
1671        case E_USER_NOTICE:
1672        case E_USER_DEPRECATED:
1673            break;
1674        default:
1675            zend_error(E_WARNING, "Invalid error type specified");
1676            RETURN_FALSE;
1677            break;
1678    }
1679
1680    zend_error((int)error_type, "%s", message);
1681    RETURN_TRUE;
1682}
1683/* }}} */
1684
1685/* {{{ proto string set_error_handler(callable error_handler [, int error_types])
1686   Sets a user-defined error handler function.  Returns the previously defined error handler, or false on error */
1687ZEND_FUNCTION(set_error_handler)
1688{
1689    zval *error_handler;
1690    zend_string *error_handler_name = NULL;
1691    zend_long error_type = E_ALL;
1692
1693    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &error_handler, &error_type) == FAILURE) {
1694        return;
1695    }
1696
1697    if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */
1698        if (!zend_is_callable(error_handler, 0, &error_handler_name)) {
1699            zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
1700                       get_active_function_name(), error_handler_name?ZSTR_VAL(error_handler_name):"unknown");
1701            zend_string_release(error_handler_name);
1702            return;
1703        }
1704        zend_string_release(error_handler_name);
1705    }
1706
1707    if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1708        ZVAL_COPY(return_value, &EG(user_error_handler));
1709
1710        zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting));
1711        zend_stack_push(&EG(user_error_handlers), &EG(user_error_handler));
1712    }
1713
1714    if (Z_TYPE_P(error_handler) == IS_NULL) { /* unset user-defined handler */
1715        ZVAL_UNDEF(&EG(user_error_handler));
1716        return;
1717    }
1718
1719    ZVAL_COPY(&EG(user_error_handler), error_handler);
1720    EG(user_error_handler_error_reporting) = (int)error_type;
1721}
1722/* }}} */
1723
1724/* {{{ proto void restore_error_handler(void)
1725   Restores the previously defined error handler function */
1726ZEND_FUNCTION(restore_error_handler)
1727{
1728    if (zend_parse_parameters_none() == FAILURE) {
1729        return;
1730    }
1731
1732    if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
1733        zval zeh;
1734
1735        ZVAL_COPY_VALUE(&zeh, &EG(user_error_handler));
1736        ZVAL_UNDEF(&EG(user_error_handler));
1737        zval_ptr_dtor(&zeh);
1738    }
1739
1740    if (zend_stack_is_empty(&EG(user_error_handlers))) {
1741        ZVAL_UNDEF(&EG(user_error_handler));
1742    } else {
1743        zval *tmp;
1744        EG(user_error_handler_error_reporting) = zend_stack_int_top(&EG(user_error_handlers_error_reporting));
1745        zend_stack_del_top(&EG(user_error_handlers_error_reporting));
1746        tmp = zend_stack_top(&EG(user_error_handlers));
1747        ZVAL_COPY_VALUE(&EG(user_error_handler), tmp);
1748        zend_stack_del_top(&EG(user_error_handlers));
1749    }
1750    RETURN_TRUE;
1751}
1752/* }}} */
1753
1754/* {{{ proto mixed set_exception_handler(callable exception_handler)
1755   Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
1756ZEND_FUNCTION(set_exception_handler)
1757{
1758    zval *exception_handler;
1759    zend_string *exception_handler_name = NULL;
1760
1761    if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &exception_handler) == FAILURE) {
1762        return;
1763    }
1764
1765    if (Z_TYPE_P(exception_handler) != IS_NULL) { /* NULL == unset */
1766        if (!zend_is_callable(exception_handler, 0, &exception_handler_name)) {
1767            zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback",
1768                       get_active_function_name(), exception_handler_name?ZSTR_VAL(exception_handler_name):"unknown");
1769            zend_string_release(exception_handler_name);
1770            return;
1771        }
1772        zend_string_release(exception_handler_name);
1773    }
1774
1775    if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1776        ZVAL_COPY(return_value, &EG(user_exception_handler));
1777
1778        zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
1779    }
1780
1781    if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */
1782        ZVAL_UNDEF(&EG(user_exception_handler));
1783        return;
1784    }
1785
1786    ZVAL_COPY(&EG(user_exception_handler), exception_handler);
1787}
1788/* }}} */
1789
1790/* {{{ proto void restore_exception_handler(void)
1791   Restores the previously defined exception handler function */
1792ZEND_FUNCTION(restore_exception_handler)
1793{
1794    if (zend_parse_parameters_none() == FAILURE) {
1795        return;
1796    }
1797
1798    if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
1799        zval_ptr_dtor(&EG(user_exception_handler));
1800    }
1801    if (zend_stack_is_empty(&EG(user_exception_handlers))) {
1802        ZVAL_UNDEF(&EG(user_exception_handler));
1803    } else {
1804        zval *tmp = zend_stack_top(&EG(user_exception_handlers));
1805        ZVAL_COPY_VALUE(&EG(user_exception_handler), tmp);
1806        zend_stack_del_top(&EG(user_exception_handlers));
1807    }
1808    RETURN_TRUE;
1809}
1810/* }}} */
1811
1812static int copy_class_or_interface_name(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
1813{
1814    zend_class_entry *ce = (zend_class_entry *)Z_PTR_P(el);
1815    zval *array = va_arg(args, zval *);
1816    uint32_t mask = va_arg(args, uint32_t);
1817    uint32_t comply = va_arg(args, uint32_t);
1818    uint32_t comply_mask = (comply)? mask:0;
1819
1820    if ((hash_key->key && ZSTR_VAL(hash_key->key)[0] != 0)
1821        && (comply_mask == (ce->ce_flags & mask))) {
1822        if (ce->refcount > 1 &&
1823            !same_name(hash_key->key, ce->name)) {
1824            add_next_index_str(array, zend_string_copy(hash_key->key));
1825        } else {
1826            add_next_index_str(array, zend_string_copy(ce->name));
1827        }
1828    }
1829    return ZEND_HASH_APPLY_KEEP;
1830}
1831/* }}} */
1832
1833/* {{{ proto array get_declared_traits()
1834   Returns an array of all declared traits. */
1835ZEND_FUNCTION(get_declared_traits)
1836{
1837    uint32_t mask = ZEND_ACC_TRAIT;
1838    uint32_t comply = 1;
1839
1840    if (zend_parse_parameters_none() == FAILURE) {
1841        return;
1842    }
1843
1844    array_init(return_value);
1845    zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
1846}
1847/* }}} */
1848
1849/* {{{ proto array get_declared_classes()
1850   Returns an array of all declared classes. */
1851ZEND_FUNCTION(get_declared_classes)
1852{
1853    uint32_t mask = ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
1854    uint32_t comply = 0;
1855
1856    if (zend_parse_parameters_none() == FAILURE) {
1857        return;
1858    }
1859
1860    array_init(return_value);
1861    zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
1862}
1863/* }}} */
1864
1865/* {{{ proto array get_declared_interfaces()
1866   Returns an array of all declared interfaces. */
1867ZEND_FUNCTION(get_declared_interfaces)
1868{
1869    uint32_t mask = ZEND_ACC_INTERFACE;
1870    uint32_t comply = 1;
1871
1872    if (zend_parse_parameters_none() == FAILURE) {
1873        return;
1874    }
1875
1876    array_init(return_value);
1877    zend_hash_apply_with_arguments(EG(class_table), copy_class_or_interface_name, 3, return_value, mask, comply);
1878}
1879/* }}} */
1880
1881static int copy_function_name(zval *zv, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
1882{
1883    zend_function *func = Z_PTR_P(zv);
1884    zval *internal_ar = va_arg(args, zval *),
1885         *user_ar     = va_arg(args, zval *);
1886
1887    if (hash_key->key == NULL || ZSTR_VAL(hash_key->key)[0] == 0) {
1888        return 0;
1889    }
1890
1891    if (func->type == ZEND_INTERNAL_FUNCTION) {
1892        add_next_index_str(internal_ar, zend_string_copy(hash_key->key));
1893    } else if (func->type == ZEND_USER_FUNCTION) {
1894        add_next_index_str(user_ar, zend_string_copy(hash_key->key));
1895    }
1896
1897    return 0;
1898}
1899/* }}} */
1900
1901/* {{{ proto array get_defined_functions(void)
1902   Returns an array of all defined functions */
1903ZEND_FUNCTION(get_defined_functions)
1904{
1905    zval internal, user;
1906
1907    if (zend_parse_parameters_none() == FAILURE) {
1908        return;
1909    }
1910
1911    array_init(&internal);
1912    array_init(&user);
1913    array_init(return_value);
1914
1915    zend_hash_apply_with_arguments(EG(function_table), copy_function_name, 2, &internal, &user);
1916
1917    zend_hash_str_add_new(Z_ARRVAL_P(return_value), "internal", sizeof("internal")-1, &internal);
1918    zend_hash_str_add_new(Z_ARRVAL_P(return_value), "user", sizeof("user")-1, &user);
1919}
1920/* }}} */
1921
1922/* {{{ proto array get_defined_vars(void)
1923   Returns an associative array of names and values of all currently defined variable names (variables in the current scope) */
1924ZEND_FUNCTION(get_defined_vars)
1925{
1926    zend_array *symbol_table = zend_rebuild_symbol_table();
1927
1928    RETURN_ARR(zend_array_dup(symbol_table));
1929}
1930/* }}} */
1931
1932#define LAMBDA_TEMP_FUNCNAME    "__lambda_func"
1933/* {{{ proto string create_function(string args, string code)
1934   Creates an anonymous function, and returns its name (funny, eh?) */
1935ZEND_FUNCTION(create_function)
1936{
1937    zend_string *function_name;
1938    char *eval_code, *function_args, *function_code;
1939    size_t eval_code_length, function_args_len, function_code_len;
1940    int retval;
1941    char *eval_name;
1942
1943    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &function_args, &function_args_len, &function_code, &function_code_len) == FAILURE) {
1944        return;
1945    }
1946
1947    eval_code = (char *) emalloc(sizeof("function " LAMBDA_TEMP_FUNCNAME)
1948            +function_args_len
1949            +2  /* for the args parentheses */
1950            +2  /* for the curly braces */
1951            +function_code_len);
1952
1953    eval_code_length = sizeof("function " LAMBDA_TEMP_FUNCNAME "(") - 1;
1954    memcpy(eval_code, "function " LAMBDA_TEMP_FUNCNAME "(", eval_code_length);
1955
1956    memcpy(eval_code + eval_code_length, function_args, function_args_len);
1957    eval_code_length += function_args_len;
1958
1959    eval_code[eval_code_length++] = ')';
1960    eval_code[eval_code_length++] = '{';
1961
1962    memcpy(eval_code + eval_code_length, function_code, function_code_len);
1963    eval_code_length += function_code_len;
1964
1965    eval_code[eval_code_length++] = '}';
1966    eval_code[eval_code_length] = '\0';
1967
1968    eval_name = zend_make_compiled_string_description("runtime-created function");
1969    retval = zend_eval_stringl(eval_code, eval_code_length, NULL, eval_name);
1970    efree(eval_code);
1971    efree(eval_name);
1972
1973    if (retval==SUCCESS) {
1974        zend_op_array *func;
1975        HashTable *static_variables;
1976
1977        func = zend_hash_str_find_ptr(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
1978        if (!func) {
1979            zend_error_noreturn(E_CORE_ERROR, "Unexpected inconsistency in create_function()");
1980            RETURN_FALSE;
1981        }
1982        if (func->refcount) {
1983            (*func->refcount)++;
1984        }
1985        static_variables = func->static_variables;
1986        func->static_variables = NULL;
1987        zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
1988        func->static_variables = static_variables;
1989
1990        function_name = zend_string_alloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG, 0);
1991        ZSTR_VAL(function_name)[0] = '\0';
1992
1993        do {
1994            ZSTR_LEN(function_name) = snprintf(ZSTR_VAL(function_name) + 1, sizeof("lambda_")+MAX_LENGTH_OF_LONG, "lambda_%d", ++EG(lambda_count)) + 1;
1995        } while (zend_hash_add_ptr(EG(function_table), function_name, func) == NULL);
1996        RETURN_NEW_STR(function_name);
1997    } else {
1998        zend_hash_str_del(EG(function_table), LAMBDA_TEMP_FUNCNAME, sizeof(LAMBDA_TEMP_FUNCNAME)-1);
1999        RETURN_FALSE;
2000    }
2001}
2002/* }}} */
2003
2004#if ZEND_DEBUG
2005ZEND_FUNCTION(zend_test_func)
2006{
2007    zval *arg1, *arg2;
2008
2009    zend_get_parameters(ZEND_NUM_ARGS(), 2, &arg1, &arg2);
2010}
2011
2012ZEND_FUNCTION(zend_test_func2)
2013{
2014    zval *arg1, *arg2;
2015
2016    zend_get_parameters(ZEND_NUM_ARGS(), 2, &arg1, &arg2);
2017}
2018
2019
2020#ifdef ZTS
2021ZEND_FUNCTION(zend_thread_id)
2022{
2023    RETURN_LONG((zend_long)tsrm_thread_id());
2024}
2025#endif
2026#endif
2027
2028/* {{{ proto string get_resource_type(resource res)
2029   Get the resource type name for a given resource */
2030ZEND_FUNCTION(get_resource_type)
2031{
2032    const char *resource_type;
2033    zval *z_resource_type;
2034
2035    if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_resource_type) == FAILURE) {
2036        return;
2037    }
2038
2039    resource_type = zend_rsrc_list_get_rsrc_type(Z_RES_P(z_resource_type));
2040    if (resource_type) {
2041        RETURN_STRING(resource_type);
2042    } else {
2043        RETURN_STRING("Unknown");
2044    }
2045}
2046/* }}} */
2047
2048/* {{{ proto array get_resources([string resouce_type])
2049   Get an array with all active resources */
2050ZEND_FUNCTION(get_resources)
2051{
2052    zend_string *type = NULL;
2053    zend_string *key;
2054    zend_ulong index;
2055    zval *val;
2056
2057    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &type) == FAILURE) {
2058        return;
2059    }
2060
2061    if (!type) {
2062        array_init(return_value);
2063        ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
2064            if (!key) {
2065                Z_ADDREF_P(val);
2066                zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
2067            }
2068        } ZEND_HASH_FOREACH_END();
2069    } else if (zend_string_equals_literal(type, "Unknown")) {
2070        array_init(return_value);
2071        ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
2072            if (!key && Z_RES_TYPE_P(val) <= 0) {
2073                Z_ADDREF_P(val);
2074                zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
2075            }
2076        } ZEND_HASH_FOREACH_END();
2077    } else {
2078        int id = zend_fetch_list_dtor_id(ZSTR_VAL(type));
2079
2080        if (id <= 0) {
2081            zend_error(E_WARNING, "get_resources():  Unknown resource type '%s'", ZSTR_VAL(type));
2082            RETURN_FALSE;
2083        }
2084
2085        array_init(return_value);
2086        ZEND_HASH_FOREACH_KEY_VAL(&EG(regular_list), index, key, val) {
2087            if (!key && Z_RES_TYPE_P(val) == id) {
2088                Z_ADDREF_P(val);
2089                zend_hash_index_add_new(Z_ARRVAL_P(return_value), index, val);
2090            }
2091        } ZEND_HASH_FOREACH_END();
2092    }
2093}
2094/* }}} */
2095
2096static int add_extension_info(zval *item, void *arg) /* {{{ */
2097{
2098    zval *name_array = (zval *)arg;
2099    zend_module_entry *module = (zend_module_entry*)Z_PTR_P(item);
2100    add_next_index_string(name_array, module->name);
2101    return 0;
2102}
2103/* }}} */
2104
2105static int add_zendext_info(zend_extension *ext, void *arg) /* {{{ */
2106{
2107    zval *name_array = (zval *)arg;
2108    add_next_index_string(name_array, ext->name);
2109    return 0;
2110}
2111/* }}} */
2112
2113static int add_constant_info(zval *item, void *arg) /* {{{ */
2114{
2115    zval *name_array = (zval *)arg;
2116    zend_constant *constant = (zend_constant*)Z_PTR_P(item);
2117    zval const_val;
2118
2119    if (!constant->name) {
2120        /* skip special constants */
2121        return 0;
2122    }
2123
2124    ZVAL_DUP(&const_val, &constant->value);
2125    zend_hash_add_new(Z_ARRVAL_P(name_array), constant->name, &const_val);
2126    return 0;
2127}
2128/* }}} */
2129
2130/* {{{ proto array get_loaded_extensions([bool zend_extensions])
2131   Return an array containing names of loaded extensions */
2132ZEND_FUNCTION(get_loaded_extensions)
2133{
2134    zend_bool zendext = 0;
2135
2136    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &zendext) == FAILURE) {
2137        return;
2138    }
2139
2140    array_init(return_value);
2141
2142    if (zendext) {
2143        zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t)add_zendext_info, return_value);
2144    } else {
2145        zend_hash_apply_with_argument(&module_registry, add_extension_info, return_value);
2146    }
2147}
2148/* }}} */
2149
2150/* {{{ proto array get_defined_constants([bool categorize])
2151   Return an array containing the names and values of all defined constants */
2152ZEND_FUNCTION(get_defined_constants)
2153{
2154    zend_bool categorize = 0;
2155
2156    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &categorize) == FAILURE) {
2157        return;
2158    }
2159
2160    array_init(return_value);
2161
2162    if (categorize) {
2163        zend_constant *val;
2164        int module_number;
2165        zval *modules, const_val;
2166        char **module_names;
2167        zend_module_entry *module;
2168        int i = 1;
2169
2170        modules = ecalloc(zend_hash_num_elements(&module_registry) + 2, sizeof(zval));
2171        module_names = emalloc((zend_hash_num_elements(&module_registry) + 2) * sizeof(char *));
2172
2173        module_names[0] = "internal";
2174        ZEND_HASH_FOREACH_PTR(&module_registry, module) {
2175            module_names[module->module_number] = (char *)module->name;
2176            i++;
2177        } ZEND_HASH_FOREACH_END();
2178        module_names[i] = "user";
2179
2180        ZEND_HASH_FOREACH_PTR(EG(zend_constants), val) {
2181            if (!val->name) {
2182                /* skip special constants */
2183                continue;
2184            }
2185
2186            if (val->module_number == PHP_USER_CONSTANT) {
2187                module_number = i;
2188            } else if (val->module_number > i || val->module_number < 0) {
2189                /* should not happen */
2190                continue;
2191            } else {
2192                module_number = val->module_number;
2193            }
2194
2195            if (Z_TYPE(modules[module_number]) == IS_UNDEF) {
2196                array_init(&modules[module_number]);
2197                add_assoc_zval(return_value, module_names[module_number], &modules[module_number]);
2198            }
2199
2200            ZVAL_DUP(&const_val, &val->value);
2201            zend_hash_add_new(Z_ARRVAL(modules[module_number]), val->name, &const_val);
2202        } ZEND_HASH_FOREACH_END();
2203
2204        efree(module_names);
2205        efree(modules);
2206    } else {
2207        zend_hash_apply_with_argument(EG(zend_constants), add_constant_info, return_value);
2208    }
2209}
2210/* }}} */
2211
2212static void debug_backtrace_get_args(zend_execute_data *call, zval *arg_array) /* {{{ */
2213{
2214    uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
2215
2216    array_init_size(arg_array, num_args);
2217    if (num_args) {
2218        uint32_t i = 0;
2219        zval *p = ZEND_CALL_ARG(call, 1);
2220
2221        zend_hash_real_init(Z_ARRVAL_P(arg_array), 1);
2222        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(arg_array)) {
2223            if (call->func->type == ZEND_USER_FUNCTION) {
2224                uint32_t first_extra_arg = call->func->op_array.num_args;
2225
2226                if (ZEND_CALL_NUM_ARGS(call) > first_extra_arg) {
2227                    while (i < first_extra_arg) {
2228                        if (Z_OPT_REFCOUNTED_P(p)) Z_ADDREF_P(p);
2229                        ZEND_HASH_FILL_ADD(p);
2230                        p++;
2231                        i++;
2232                    }
2233                    p = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
2234                }
2235            }
2236
2237            while (i < num_args) {
2238                if (Z_OPT_REFCOUNTED_P(p)) Z_ADDREF_P(p);
2239                ZEND_HASH_FILL_ADD(p);
2240                p++;
2241                i++;
2242            }
2243        } ZEND_HASH_FILL_END();
2244    }
2245}
2246/* }}} */
2247
2248void debug_print_backtrace_args(zval *arg_array) /* {{{ */
2249{
2250    zval *tmp;
2251    int i = 0;
2252
2253    ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arg_array), tmp) {
2254        if (i++) {
2255            ZEND_PUTS(", ");
2256        }
2257        zend_print_flat_zval_r(tmp);
2258    } ZEND_HASH_FOREACH_END();
2259}
2260/* }}} */
2261
2262/* {{{ proto void debug_print_backtrace([int options[, int limit]]) */
2263ZEND_FUNCTION(debug_print_backtrace)
2264{
2265    zend_execute_data *call, *ptr, *skip;
2266    zend_object *object;
2267    int lineno, frameno = 0;
2268    zend_function *func;
2269    const char *function_name;
2270    const char *filename;
2271    zend_string *class_name = NULL;
2272    char *call_type;
2273    const char *include_filename = NULL;
2274    zval arg_array;
2275    int indent = 0;
2276    zend_long options = 0;
2277    zend_long limit = 0;
2278
2279    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
2280        return;
2281    }
2282
2283    ZVAL_UNDEF(&arg_array);
2284    ptr = EX(prev_execute_data);
2285
2286    /* skip debug_backtrace() */
2287    call = ptr;
2288    ptr = ptr->prev_execute_data;
2289
2290    while (ptr && (limit == 0 || frameno < limit)) {
2291        frameno++;
2292        class_name = NULL;
2293        call_type = NULL;
2294        ZVAL_UNDEF(&arg_array);
2295
2296        ptr = zend_generator_check_placeholder_frame(ptr);
2297
2298        skip = ptr;
2299        /* skip internal handler */
2300        if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
2301            skip->prev_execute_data &&
2302            skip->prev_execute_data->func &&
2303            ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
2304            skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
2305            skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
2306            skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
2307            skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
2308            skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2309            skip = skip->prev_execute_data;
2310        }
2311
2312        if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
2313            filename = ZSTR_VAL(skip->func->op_array.filename);
2314            if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
2315                if (EG(opline_before_exception)) {
2316                    lineno = EG(opline_before_exception)->lineno;
2317                } else {
2318                    lineno = skip->func->op_array.line_end;
2319                }
2320            } else {
2321                lineno = skip->opline->lineno;
2322            }
2323        } else {
2324            filename = NULL;
2325            lineno = 0;
2326        }
2327
2328        /* $this may be passed into regular internal functions */
2329        object = Z_OBJ(call->This);
2330
2331        if (call->func) {
2332            func = call->func;
2333            function_name = (func->common.scope &&
2334                             func->common.scope->trait_aliases) ?
2335                ZSTR_VAL(zend_resolve_method_name(
2336                    (object ? object->ce : func->common.scope), func)) :
2337                (func->common.function_name ?
2338                    ZSTR_VAL(func->common.function_name) : NULL);
2339        } else {
2340            func = NULL;
2341            function_name = NULL;
2342        }
2343
2344        if (function_name) {
2345            if (object) {
2346                if (func->common.scope) {
2347                    class_name = func->common.scope->name;
2348                } else {
2349                    class_name = object->ce->name;
2350                }
2351
2352                call_type = "->";
2353            } else if (func->common.scope) {
2354                class_name = func->common.scope->name;
2355                call_type = "::";
2356            } else {
2357                class_name = NULL;
2358                call_type = NULL;
2359            }
2360            if (func->type != ZEND_EVAL_CODE) {
2361                if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0) {
2362                    debug_backtrace_get_args(call, &arg_array);
2363                }
2364            }
2365        } else {
2366            /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
2367            zend_bool build_filename_arg = 1;
2368
2369            if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2370                /* can happen when calling eval from a custom sapi */
2371                function_name = "unknown";
2372                build_filename_arg = 0;
2373            } else
2374            switch (ptr->opline->extended_value) {
2375                case ZEND_EVAL:
2376                    function_name = "eval";
2377                    build_filename_arg = 0;
2378                    break;
2379                case ZEND_INCLUDE:
2380                    function_name = "include";
2381                    break;
2382                case ZEND_REQUIRE:
2383                    function_name = "require";
2384                    break;
2385                case ZEND_INCLUDE_ONCE:
2386                    function_name = "include_once";
2387                    break;
2388                case ZEND_REQUIRE_ONCE:
2389                    function_name = "require_once";
2390                    break;
2391                default:
2392                    /* this can actually happen if you use debug_backtrace() in your error_handler and
2393                     * you're in the top-scope */
2394                    function_name = "unknown";
2395                    build_filename_arg = 0;
2396                    break;
2397            }
2398
2399            if (build_filename_arg && include_filename) {
2400                array_init(&arg_array);
2401                add_next_index_string(&arg_array, (char*)include_filename);
2402            }
2403            call_type = NULL;
2404        }
2405        zend_printf("#%-2d ", indent);
2406        if (class_name) {
2407            ZEND_PUTS(ZSTR_VAL(class_name));
2408            ZEND_PUTS(call_type);
2409        }
2410        zend_printf("%s(", function_name);
2411        if (Z_TYPE(arg_array) != IS_UNDEF) {
2412            debug_print_backtrace_args(&arg_array);
2413            zval_ptr_dtor(&arg_array);
2414        }
2415        if (filename) {
2416            zend_printf(") called at [%s:%d]\n", filename, lineno);
2417        } else {
2418            zend_execute_data *prev_call = skip;
2419            zend_execute_data *prev = skip->prev_execute_data;
2420
2421            while (prev) {
2422                if (prev_call &&
2423                    prev_call->func &&
2424                    !ZEND_USER_CODE(prev_call->func->common.type)) {
2425                    prev = NULL;
2426                    break;
2427                }
2428                if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
2429                    zend_printf(") called at [%s:%d]\n", ZSTR_VAL(prev->func->op_array.filename), prev->opline->lineno);
2430                    break;
2431                }
2432                prev_call = prev;
2433                prev = prev->prev_execute_data;
2434            }
2435            if (!prev) {
2436                ZEND_PUTS(")\n");
2437            }
2438        }
2439        include_filename = filename;
2440        call = skip;
2441        ptr = skip->prev_execute_data;
2442        ++indent;
2443    }
2444}
2445
2446/* }}} */
2447
2448ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit) /* {{{ */
2449{
2450    zend_execute_data *call, *ptr, *skip;
2451    zend_object *object;
2452    int lineno, frameno = 0;
2453    zend_function *func;
2454    zend_string *function_name;
2455    zend_string *filename;
2456    zend_string *include_filename = NULL;
2457    zval stack_frame;
2458
2459    call = NULL;
2460    ptr = EG(current_execute_data);
2461    if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type)) {
2462        call = ptr;
2463        ptr = ptr->prev_execute_data;
2464    }
2465
2466    if (ptr) {
2467        if (skip_last) {
2468            /* skip debug_backtrace() */
2469            call = ptr;
2470            ptr = ptr->prev_execute_data;
2471        } else {
2472            /* skip "new Exception()" */
2473            if (ptr->func && ZEND_USER_CODE(ptr->func->common.type) && (ptr->opline->opcode == ZEND_NEW)) {
2474                call = ptr;
2475                ptr = ptr->prev_execute_data;
2476            }
2477        }
2478    }
2479    if (!call) {
2480        call = ptr;
2481        ptr = ptr->prev_execute_data;
2482    }
2483
2484    array_init(return_value);
2485
2486    while (ptr && (limit == 0 || frameno < limit)) {
2487        frameno++;
2488        array_init(&stack_frame);
2489
2490        ptr = zend_generator_check_placeholder_frame(ptr);
2491
2492        skip = ptr;
2493        /* skip internal handler */
2494        if ((!skip->func || !ZEND_USER_CODE(skip->func->common.type)) &&
2495            skip->prev_execute_data &&
2496            skip->prev_execute_data->func &&
2497            ZEND_USER_CODE(skip->prev_execute_data->func->common.type) &&
2498            skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL &&
2499            skip->prev_execute_data->opline->opcode != ZEND_DO_ICALL &&
2500            skip->prev_execute_data->opline->opcode != ZEND_DO_UCALL &&
2501            skip->prev_execute_data->opline->opcode != ZEND_DO_FCALL_BY_NAME &&
2502            skip->prev_execute_data->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2503            skip = skip->prev_execute_data;
2504        }
2505
2506        if (skip->func && ZEND_USER_CODE(skip->func->common.type)) {
2507            filename = skip->func->op_array.filename;
2508            if (skip->opline->opcode == ZEND_HANDLE_EXCEPTION) {
2509                if (EG(opline_before_exception)) {
2510                    lineno = EG(opline_before_exception)->lineno;
2511                } else {
2512                    lineno = skip->func->op_array.line_end;
2513                }
2514            } else {
2515                lineno = skip->opline->lineno;
2516            }
2517            add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, zend_string_copy(filename));
2518            add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, lineno);
2519
2520            /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function
2521             * and debug_baktrace() might have been called by the error_handler. in this case we don't
2522             * want to pop anything of the argument-stack */
2523        } else {
2524            zend_execute_data *prev_call = skip;
2525            zend_execute_data *prev = skip->prev_execute_data;
2526
2527            while (prev) {
2528                if (prev_call &&
2529                    prev_call->func &&
2530                    !ZEND_USER_CODE(prev_call->func->common.type) &&
2531                    !(prev_call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
2532                    break;
2533                }
2534                if (prev->func && ZEND_USER_CODE(prev->func->common.type)) {
2535                    add_assoc_str_ex(&stack_frame, "file", sizeof("file")-1, zend_string_copy(prev->func->op_array.filename));
2536                    add_assoc_long_ex(&stack_frame, "line", sizeof("line")-1, prev->opline->lineno);
2537                    break;
2538                }
2539                prev_call = prev;
2540                prev = prev->prev_execute_data;
2541            }
2542            filename = NULL;
2543        }
2544
2545        /* $this may be passed into regular internal functions */
2546        object = call ? Z_OBJ(call->This) : NULL;
2547
2548        if (call && call->func) {
2549            func = call->func;
2550            function_name = (func->common.scope &&
2551                             func->common.scope->trait_aliases) ?
2552                zend_resolve_method_name(
2553                    (object ? object->ce : func->common.scope), func) :
2554                func->common.function_name;
2555        } else {
2556            func = NULL;
2557            function_name = NULL;
2558        }
2559
2560        if (function_name) {
2561            add_assoc_str_ex(&stack_frame, "function", sizeof("function")-1, zend_string_copy(function_name));
2562
2563            if (object) {
2564                if (func->common.scope) {
2565                    add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(func->common.scope->name));
2566                } else {
2567                    add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(object->ce->name));
2568
2569                }
2570                if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
2571                    zval zv;
2572                    ZVAL_OBJ(&zv, object);
2573                    add_assoc_zval_ex(&stack_frame, "object", sizeof("object")-1, &zv);
2574                    Z_ADDREF(zv);
2575                }
2576
2577                add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
2578            } else if (func->common.scope) {
2579                add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, zend_string_copy(func->common.scope->name));
2580                add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "::");
2581            }
2582
2583            if ((options & DEBUG_BACKTRACE_IGNORE_ARGS) == 0 &&
2584                func->type != ZEND_EVAL_CODE) {
2585                zval args;
2586
2587                debug_backtrace_get_args(call, &args);
2588                add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &args);
2589            }
2590        } else {
2591            /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
2592            zend_bool build_filename_arg = 1;
2593            const char *pseudo_function_name;
2594
2595            if (!ptr->func || !ZEND_USER_CODE(ptr->func->common.type) || ptr->opline->opcode != ZEND_INCLUDE_OR_EVAL) {
2596                /* can happen when calling eval from a custom sapi */
2597                pseudo_function_name = "unknown";
2598                build_filename_arg = 0;
2599            } else
2600            switch (ptr->opline->extended_value) {
2601                case ZEND_EVAL:
2602                    pseudo_function_name = "eval";
2603                    build_filename_arg = 0;
2604                    break;
2605                case ZEND_INCLUDE:
2606                    pseudo_function_name = "include";
2607                    break;
2608                case ZEND_REQUIRE:
2609                    pseudo_function_name = "require";
2610                    break;
2611                case ZEND_INCLUDE_ONCE:
2612                    pseudo_function_name = "include_once";
2613                    break;
2614                case ZEND_REQUIRE_ONCE:
2615                    pseudo_function_name = "require_once";
2616                    break;
2617                default:
2618                    /* this can actually happen if you use debug_backtrace() in your error_handler and
2619                     * you're in the top-scope */
2620                    pseudo_function_name = "unknown";
2621                    build_filename_arg = 0;
2622                    break;
2623            }
2624
2625            if (build_filename_arg && include_filename) {
2626                zval arg_array;
2627
2628                array_init(&arg_array);
2629
2630                /* include_filename always points to the last filename of the last last called-function.
2631                   if we have called include in the frame above - this is the file we have included.
2632                 */
2633
2634                add_next_index_str(&arg_array, zend_string_copy(include_filename));
2635                add_assoc_zval_ex(&stack_frame, "args", sizeof("args")-1, &arg_array);
2636            }
2637
2638            add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char *) pseudo_function_name);
2639        }
2640
2641        zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &stack_frame);
2642
2643        include_filename = filename;
2644
2645        call = skip;
2646        ptr = skip->prev_execute_data;
2647    }
2648}
2649/* }}} */
2650
2651/* {{{ proto array debug_backtrace([int options[, int limit]])
2652   Return backtrace as array */
2653ZEND_FUNCTION(debug_backtrace)
2654{
2655    zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2656    zend_long limit = 0;
2657
2658    if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &options, &limit) == FAILURE) {
2659        return;
2660    }
2661
2662    zend_fetch_debug_backtrace(return_value, 1, options, limit);
2663}
2664/* }}} */
2665
2666/* {{{ proto bool extension_loaded(string extension_name)
2667   Returns true if the named extension is loaded */
2668ZEND_FUNCTION(extension_loaded)
2669{
2670    zend_string *extension_name;
2671    zend_string *lcname;
2672
2673    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
2674        return;
2675    }
2676
2677    lcname = zend_string_tolower(extension_name);
2678    if (zend_hash_exists(&module_registry, lcname)) {
2679        RETVAL_TRUE;
2680    } else {
2681        RETVAL_FALSE;
2682    }
2683    zend_string_release(lcname);
2684}
2685/* }}} */
2686
2687/* {{{ proto array get_extension_funcs(string extension_name)
2688   Returns an array with the names of functions belonging to the named extension */
2689ZEND_FUNCTION(get_extension_funcs)
2690{
2691    zend_string *extension_name;
2692    zend_string *lcname;
2693    int array;
2694    zend_module_entry *module;
2695    zend_function *zif;
2696
2697    if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &extension_name) == FAILURE) {
2698        return;
2699    }
2700    if (strncasecmp(ZSTR_VAL(extension_name), "zend", sizeof("zend"))) {
2701        lcname = zend_string_tolower(extension_name);
2702        module = zend_hash_find_ptr(&module_registry, lcname);
2703        zend_string_release(lcname);
2704    } else {
2705        module = zend_hash_str_find_ptr(&module_registry, "core", sizeof("core") - 1);
2706    }
2707
2708    if (!module) {
2709        RETURN_FALSE;
2710    }
2711
2712    if (module->functions) {
2713        /* avoid BC break, if functions list is empty, will return an empty array */
2714        array_init(return_value);
2715        array = 1;
2716    } else {
2717        array = 0;
2718    }
2719
2720    ZEND_HASH_FOREACH_PTR(CG(function_table), zif) {
2721        if (zif->common.type == ZEND_INTERNAL_FUNCTION
2722            && zif->internal_function.module == module) {
2723            if (!array) {
2724                array_init(return_value);
2725                array = 1;
2726            }
2727            add_next_index_str(return_value, zend_string_copy(zif->common.function_name));
2728        }
2729    } ZEND_HASH_FOREACH_END();
2730
2731    if (!array) {
2732        RETURN_FALSE;
2733    }
2734}
2735/* }}} */
2736
2737/*
2738 * Local variables:
2739 * tab-width: 4
2740 * c-basic-offset: 4
2741 * indent-tabs-mode: t
2742 * End:
2743 */
2744