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