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