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