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