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