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