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