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