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