17cb0480dSMarcus Boerger/*
27cb0480dSMarcus Boerger   +----------------------------------------------------------------------+
3d0cb7153SJohannes Schlüter   | PHP Version 7                                                        |
47cb0480dSMarcus Boerger   +----------------------------------------------------------------------+
5a6519d05SXinchen Hui   | Copyright (c) 1997-2018 The PHP Group                                |
67cb0480dSMarcus Boerger   +----------------------------------------------------------------------+
75bd93221Sfoobar   | This source file is subject to version 3.01 of the PHP license,      |
87cb0480dSMarcus Boerger   | that is bundled with this package in the file LICENSE, and is        |
97cb0480dSMarcus Boerger   | available through the world-wide-web at the following url:           |
105bd93221Sfoobar   | http://www.php.net/license/3_01.txt                                  |
117cb0480dSMarcus Boerger   | If you did not receive a copy of the PHP license and are unable to   |
127cb0480dSMarcus Boerger   | obtain it through the world-wide-web, please send a note to          |
137cb0480dSMarcus Boerger   | license@php.net so we can mail you a copy immediately.               |
147cb0480dSMarcus Boerger   +----------------------------------------------------------------------+
157cb0480dSMarcus Boerger   | Authors: Timm Friebe <thekid@thekid.de>                              |
167cb0480dSMarcus Boerger   |          George Schlossnagle <george@omniti.com>                     |
177cb0480dSMarcus Boerger   |          Andrei Zmievski <andrei@gravitonic.com>                     |
187cb0480dSMarcus Boerger   |          Marcus Boerger <helly@php.net>                              |
197cb0480dSMarcus Boerger   |          Johannes Schlueter <johannes@php.net>                       |
207cb0480dSMarcus Boerger   +----------------------------------------------------------------------+
217cb0480dSMarcus Boerger*/
227cb0480dSMarcus Boerger
237cb0480dSMarcus Boerger#ifdef HAVE_CONFIG_H
247cb0480dSMarcus Boerger#include "config.h"
257cb0480dSMarcus Boerger#endif
267cb0480dSMarcus Boerger
277cb0480dSMarcus Boerger#include "php.h"
287cb0480dSMarcus Boerger#include "php_ini.h"
297cb0480dSMarcus Boerger#include "php_reflection.h"
307cb0480dSMarcus Boerger#include "ext/standard/info.h"
317cb0480dSMarcus Boerger
327cb0480dSMarcus Boerger#include "zend.h"
337cb0480dSMarcus Boerger#include "zend_API.h"
347cb0480dSMarcus Boerger#include "zend_exceptions.h"
357cb0480dSMarcus Boerger#include "zend_operators.h"
367cb0480dSMarcus Boerger#include "zend_constants.h"
377cb0480dSMarcus Boerger#include "zend_ini.h"
387cb0480dSMarcus Boerger#include "zend_interfaces.h"
39d5ef2f46SDmitry Stogov#include "zend_closures.h"
40aa3c7aa4SBob Weinand#include "zend_generators.h"
4126af5759SJohannes Schlüter#include "zend_extensions.h"
42aa3c7aa4SBob Weinand#include "zend_builtin_functions.h"
43f3f594a4SNikita Popov#include "zend_smart_str.h"
447cb0480dSMarcus Boerger
45c5237d82SDmitry Stogov#define reflection_update_property(object, name, value) do { \
46f4cfaf36SDmitry Stogov		zval member; \
475b044aacSNikita Popov		ZVAL_STR(&member, name); \
48bdeb220fSAnatol Belski		zend_std_write_property(object, &member, value, NULL); \
49a8a17a72SXinchen Hui		Z_TRY_DELREF_P(value); \
50c5237d82SDmitry Stogov		zval_ptr_dtor(&member); \
51c5237d82SDmitry Stogov	} while (0)
52c5237d82SDmitry Stogov
535b044aacSNikita Popov#define reflection_update_property_name(object, value) \
545b044aacSNikita Popov	reflection_update_property(object, ZSTR_KNOWN(ZEND_STR_NAME), value)
555b044aacSNikita Popov
565b044aacSNikita Popov#define reflection_update_property_class(object, value) \
575b044aacSNikita Popov	reflection_update_property(object, ZSTR_KNOWN(ZEND_STR_CLASS), value)
585b044aacSNikita Popov
597cb0480dSMarcus Boerger/* Class entry pointers */
607cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflector_ptr;
617cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_exception_ptr;
627cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_ptr;
6313fe33c2SHannes MagnussonPHPAPI zend_class_entry *reflection_function_abstract_ptr;
647cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_function_ptr;
65aa3c7aa4SBob WeinandPHPAPI zend_class_entry *reflection_generator_ptr;
667cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_parameter_ptr;
67ec281fefSMatteo BeccatiPHPAPI zend_class_entry *reflection_type_ptr;
68622d2f41SAaron PiotrowskiPHPAPI zend_class_entry *reflection_named_type_ptr;
697cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_class_ptr;
707cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_object_ptr;
717cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_method_ptr;
727cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_property_ptr;
73a75c1950SDmitry StogovPHPAPI zend_class_entry *reflection_class_constant_ptr;
747cb0480dSMarcus BoergerPHPAPI zend_class_entry *reflection_extension_ptr;
7526af5759SJohannes SchlüterPHPAPI zend_class_entry *reflection_zend_extension_ptr;
767cb0480dSMarcus Boerger
777cb0480dSMarcus Boerger/* Exception throwing macro */
787cb0480dSMarcus Boerger#define _DO_THROW(msg)                                                                                      \
79bdeb220fSAnatol Belski	zend_throw_exception(reflection_exception_ptr, msg, 0);                                       \
807cb0480dSMarcus Boerger	return;                                                                                                 \
817cb0480dSMarcus Boerger
827cb0480dSMarcus Boerger#define RETURN_ON_EXCEPTION                                                                                 \
83f4cfaf36SDmitry Stogov	if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {                            \
847cb0480dSMarcus Boerger		return;                                                                                             \
857cb0480dSMarcus Boerger	}
867cb0480dSMarcus Boerger
875864ce8aSDmitry Stogov#define GET_REFLECTION_OBJECT()	                                                                   			\
885864ce8aSDmitry Stogov	intern = Z_REFLECTION_P(getThis());                                                      				\
89c58b0cb4SDmitry Stogov	if (intern->ptr == NULL) {                                                            \
907cb0480dSMarcus Boerger		RETURN_ON_EXCEPTION                                                                                 \
91771e5cc2SAaron Piotrowski		zend_throw_error(NULL, "Internal error: Failed to retrieve the reflection object");        \
92907476f3SAaron Piotrowski		return;                                                                                             \
937cb0480dSMarcus Boerger	}                                                                                                       \
945864ce8aSDmitry Stogov
955864ce8aSDmitry Stogov#define GET_REFLECTION_OBJECT_PTR(target)                                                                   \
965864ce8aSDmitry Stogov	GET_REFLECTION_OBJECT()																					\
977cb0480dSMarcus Boerger	target = intern->ptr;                                                                                   \
987cb0480dSMarcus Boerger
997cb0480dSMarcus Boerger/* Class constants */
100c3e3c98eSAnatol Belski#define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value)                                        \
101bdeb220fSAnatol Belski	zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (zend_long)value);
1027cb0480dSMarcus Boerger
10397b7620aSJohannes Schlüter/* {{{ Object structure */
10497b7620aSJohannes Schlüter
1057cb0480dSMarcus Boerger/* Struct for properties */
1067cb0480dSMarcus Boergertypedef struct _property_reference {
1077cb0480dSMarcus Boerger	zend_class_entry *ce;
1088e67ec82SAntony Dovgal	zend_property_info prop;
109bddb085aSNikita Popov	zend_string *unmangled_name;
1107cb0480dSMarcus Boerger} property_reference;
1117cb0480dSMarcus Boerger
1127cb0480dSMarcus Boerger/* Struct for parameters */
1137cb0480dSMarcus Boergertypedef struct _parameter_reference {
1146f9f0bf2SAnatol Belski	uint32_t offset;
115e52d2b88SBarbu Paul - Gheorghe	zend_bool required;
1167cb0480dSMarcus Boerger	struct _zend_arg_info *arg_info;
1177cb0480dSMarcus Boerger	zend_function *fptr;
1187cb0480dSMarcus Boerger} parameter_reference;
1197cb0480dSMarcus Boerger
120ec281fefSMatteo Beccati/* Struct for type hints */
121ec281fefSMatteo Beccatitypedef struct _type_reference {
122cf8898fbSSara Golemon	struct _zend_arg_info *arg_info;
123ec281fefSMatteo Beccati	zend_function *fptr;
124ec281fefSMatteo Beccati} type_reference;
125cf8898fbSSara Golemon
12605d896ccSMarcus Boergertypedef enum {
12705d896ccSMarcus Boerger	REF_TYPE_OTHER,      /* Must be 0 */
12805d896ccSMarcus Boerger	REF_TYPE_FUNCTION,
129aa3c7aa4SBob Weinand	REF_TYPE_GENERATOR,
13005d896ccSMarcus Boerger	REF_TYPE_PARAMETER,
131ec281fefSMatteo Beccati	REF_TYPE_TYPE,
132224bfb38SFelipe Pena	REF_TYPE_PROPERTY,
133a75c1950SDmitry Stogov	REF_TYPE_CLASS_CONSTANT
13405d896ccSMarcus Boerger} reflection_type_t;
13505d896ccSMarcus Boerger
1367cb0480dSMarcus Boerger/* Struct for reflection objects */
1377cb0480dSMarcus Boergertypedef struct {
138c077742bSDmitry Stogov	zval dummy; /* holder for the second property */
139f4cfaf36SDmitry Stogov	zval obj;
140f1ba5389SAnatol Belski	void *ptr;
1417cb0480dSMarcus Boerger	zend_class_entry *ce;
142f1ba5389SAnatol Belski	reflection_type_t ref_type;
143ceaf5905SSebastian Bergmann	unsigned int ignore_visibility:1;
144897a4d25SXinchen Hui	zend_object zo;
1457cb0480dSMarcus Boerger} reflection_object;
1467cb0480dSMarcus Boerger
1477409fd4bSReeze Xiastatic inline reflection_object *reflection_object_from_obj(zend_object *obj) {
148897a4d25SXinchen Hui	return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
149897a4d25SXinchen Hui}
150897a4d25SXinchen Hui
151897a4d25SXinchen Hui#define Z_REFLECTION_P(zv)  reflection_object_from_obj(Z_OBJ_P((zv)))
15297b7620aSJohannes Schlüter/* }}} */
15397b7620aSJohannes Schlüter
1547cb0480dSMarcus Boergerstatic zend_object_handlers reflection_object_handlers;
1557cb0480dSMarcus Boerger
1565b044aacSNikita Popovstatic zval *_default_load_name(zval *object) /* {{{ */
157887189caSDmitry Stogov{
1584dfbfe93SXinchen Hui	return zend_hash_find_ex_ind(Z_OBJPROP_P(object), ZSTR_KNOWN(ZEND_STR_NAME), 1);
159887189caSDmitry Stogov}
1607409fd4bSReeze Xia/* }}} */
161887189caSDmitry Stogov
1625b044aacSNikita Popovstatic void _default_get_name(zval *object, zval *return_value) /* {{{ */
1637cb0480dSMarcus Boerger{
164f4cfaf36SDmitry Stogov	zval *value;
1657cb0480dSMarcus Boerger
1665b044aacSNikita Popov	if ((value = _default_load_name(object)) == NULL) {
1677cb0480dSMarcus Boerger		RETURN_FALSE;
1687cb0480dSMarcus Boerger	}
1697b16205fSNikita Popov	ZVAL_COPY(return_value, value);
1707cb0480dSMarcus Boerger}
17197b7620aSJohannes Schlüter/* }}} */
1727cb0480dSMarcus Boerger
173bdeb220fSAnatol Belskistatic zend_function *_copy_function(zend_function *fptr) /* {{{ */
174066ea4f6SChristian Seiler{
175066ea4f6SChristian Seiler	if (fptr
1765e8133f4SDmitry Stogov		&& (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
177066ea4f6SChristian Seiler	{
178066ea4f6SChristian Seiler		zend_function *copy_fptr;
179066ea4f6SChristian Seiler		copy_fptr = emalloc(sizeof(zend_function));
180066ea4f6SChristian Seiler		memcpy(copy_fptr, fptr, sizeof(zend_function));
181c3e3c98eSAnatol Belski		copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
182066ea4f6SChristian Seiler		return copy_fptr;
183066ea4f6SChristian Seiler	} else {
184066ea4f6SChristian Seiler		/* no copy needed */
185066ea4f6SChristian Seiler		return fptr;
186066ea4f6SChristian Seiler	}
187066ea4f6SChristian Seiler}
188066ea4f6SChristian Seiler/* }}} */
189066ea4f6SChristian Seiler
190bdeb220fSAnatol Belskistatic void _free_function(zend_function *fptr) /* {{{ */
1917cb0480dSMarcus Boerger{
19205d896ccSMarcus Boerger	if (fptr
1935e8133f4SDmitry Stogov		&& (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
1946d083e2cSMarcus Boerger	{
1955eb1f92fSDmitry Stogov		zend_string_release_ex(fptr->internal_function.function_name, 0);
1965e8133f4SDmitry Stogov		zend_free_trampoline(fptr);
1977cb0480dSMarcus Boerger	}
1987cb0480dSMarcus Boerger}
19905d896ccSMarcus Boerger/* }}} */
2007cb0480dSMarcus Boerger
201bdeb220fSAnatol Belskistatic void reflection_free_objects_storage(zend_object *object) /* {{{ */
2027cb0480dSMarcus Boerger{
203897a4d25SXinchen Hui	reflection_object *intern = reflection_object_from_obj(object);
20405d896ccSMarcus Boerger	parameter_reference *reference;
205224bfb38SFelipe Pena	property_reference *prop_reference;
206ec281fefSMatteo Beccati	type_reference *typ_reference;
2077cb0480dSMarcus Boerger
20805d896ccSMarcus Boerger	if (intern->ptr) {
20905d896ccSMarcus Boerger		switch (intern->ref_type) {
21005d896ccSMarcus Boerger		case REF_TYPE_PARAMETER:
21105d896ccSMarcus Boerger			reference = (parameter_reference*)intern->ptr;
212bdeb220fSAnatol Belski			_free_function(reference->fptr);
213ec281fefSMatteo Beccati			efree(intern->ptr);
214ec281fefSMatteo Beccati			break;
215ec281fefSMatteo Beccati		case REF_TYPE_TYPE:
216ec281fefSMatteo Beccati			typ_reference = (type_reference*)intern->ptr;
217ec281fefSMatteo Beccati			_free_function(typ_reference->fptr);
21805d896ccSMarcus Boerger			efree(intern->ptr);
21905d896ccSMarcus Boerger			break;
22005d896ccSMarcus Boerger		case REF_TYPE_FUNCTION:
221bdeb220fSAnatol Belski			_free_function(intern->ptr);
22205d896ccSMarcus Boerger			break;
22305d896ccSMarcus Boerger		case REF_TYPE_PROPERTY:
224224bfb38SFelipe Pena			prop_reference = (property_reference*)intern->ptr;
225bddb085aSNikita Popov			zend_string_release_ex(prop_reference->unmangled_name, 0);
226224bfb38SFelipe Pena			efree(intern->ptr);
227224bfb38SFelipe Pena			break;
228aa3c7aa4SBob Weinand		case REF_TYPE_GENERATOR:
229a75c1950SDmitry Stogov		case REF_TYPE_CLASS_CONSTANT:
23005d896ccSMarcus Boerger		case REF_TYPE_OTHER:
23105d896ccSMarcus Boerger			break;
23205d896ccSMarcus Boerger		}
23305d896ccSMarcus Boerger	}
23405d896ccSMarcus Boerger	intern->ptr = NULL;
235f4cfaf36SDmitry Stogov	zval_ptr_dtor(&intern->obj);
236bdeb220fSAnatol Belski	zend_object_std_dtor(object);
2377cb0480dSMarcus Boerger}
23897b7620aSJohannes Schlüter/* }}} */
2397cb0480dSMarcus Boerger
240c1af9f28SNikita Popovstatic HashTable *reflection_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */
241c1af9f28SNikita Popov{
242c1af9f28SNikita Popov	reflection_object *intern = Z_REFLECTION_P(obj);
243c1af9f28SNikita Popov	*gc_data = &intern->obj;
244c1af9f28SNikita Popov	*gc_data_count = 1;
245c1af9f28SNikita Popov	return zend_std_get_properties(obj);
246c1af9f28SNikita Popov}
247c1af9f28SNikita Popov/* }}} */
248c1af9f28SNikita Popov
249bdeb220fSAnatol Belskistatic zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
2507cb0480dSMarcus Boerger{
251b72b1a4eSNikita Popov	reflection_object *intern = zend_object_alloc(sizeof(reflection_object), class_type);
2527cb0480dSMarcus Boerger
253bdeb220fSAnatol Belski	zend_object_std_init(&intern->zo, class_type);
254c5237d82SDmitry Stogov	object_properties_init(&intern->zo, class_type);
255f4cfaf36SDmitry Stogov	intern->zo.handlers = &reflection_object_handlers;
256897a4d25SXinchen Hui	return &intern->zo;
2577cb0480dSMarcus Boerger}
25897b7620aSJohannes Schlüter/* }}} */
2597cb0480dSMarcus Boerger
260bdeb220fSAnatol Belskistatic zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
2617cb0480dSMarcus Boerger{
2627cb0480dSMarcus Boerger	object_init_ex(object, pce);
2637cb0480dSMarcus Boerger	return object;
2647cb0480dSMarcus Boerger}
26597b7620aSJohannes Schlüter/* }}} */
2667cb0480dSMarcus Boerger
267f3f594a4SNikita Popovstatic void _const_string(smart_str *str, char *name, zval *value, char *indent);
268f3f594a4SNikita Popovstatic void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent);
269bddb085aSNikita Popovstatic void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent);
270f3f594a4SNikita Popovstatic void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char* indent);
271f3f594a4SNikita Popovstatic void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent);
272f3f594a4SNikita Popovstatic void _extension_string(smart_str *str, zend_module_entry *module, char *indent);
273f3f594a4SNikita Popovstatic void _zend_extension_string(smart_str *str, zend_extension *extension, char *indent);
2747cb0480dSMarcus Boerger
2757cb0480dSMarcus Boerger/* {{{ _class_string */
276f3f594a4SNikita Popovstatic void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char *indent)
2777cb0480dSMarcus Boerger{
2787cb0480dSMarcus Boerger	int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
279a1145c0cSNikita Popov	zend_string *sub_indent = strpprintf(0, "%s    ", indent);
2807cb0480dSMarcus Boerger
2817cb0480dSMarcus Boerger	/* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
282f2df6a4aSDmitry Stogov	if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
283f3f594a4SNikita Popov		smart_str_append_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment));
284f3f594a4SNikita Popov		smart_str_appendc(str, '\n');
2857cb0480dSMarcus Boerger	}
2867cb0480dSMarcus Boerger
2874a1ecf0eSDmitry Stogov	if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
288f3f594a4SNikita Popov		smart_str_append_printf(str, "%sObject of class [ ", indent);
2897cb0480dSMarcus Boerger	} else {
29019afc82eSJohannes Schlüter		char *kind = "Class";
29119afc82eSJohannes Schlüter		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
29219afc82eSJohannes Schlüter			kind = "Interface";
2938c81d80eSGuilherme Blanco		} else if (ce->ce_flags & ZEND_ACC_TRAIT) {
29419afc82eSJohannes Schlüter			kind = "Trait";
29519afc82eSJohannes Schlüter		}
296f3f594a4SNikita Popov		smart_str_append_printf(str, "%s%s [ ", indent, kind);
2977cb0480dSMarcus Boerger	}
298f3f594a4SNikita Popov	smart_str_append_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
299f2df6a4aSDmitry Stogov	if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
300f3f594a4SNikita Popov		smart_str_append_printf(str, ":%s", ce->info.internal.module->name);
3017cb0480dSMarcus Boerger	}
302f3f594a4SNikita Popov	smart_str_append_printf(str, "> ");
3037cb0480dSMarcus Boerger	if (ce->get_iterator != NULL) {
304f3f594a4SNikita Popov		smart_str_append_printf(str, "<iterateable> ");
3057cb0480dSMarcus Boerger	}
3067cb0480dSMarcus Boerger	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
307f3f594a4SNikita Popov		smart_str_append_printf(str, "interface ");
3088c81d80eSGuilherme Blanco	} else if (ce->ce_flags & ZEND_ACC_TRAIT) {
309f3f594a4SNikita Popov		smart_str_append_printf(str, "trait ");
3107cb0480dSMarcus Boerger	} else {
3117cb0480dSMarcus Boerger		if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
312f3f594a4SNikita Popov			smart_str_append_printf(str, "abstract ");
3137cb0480dSMarcus Boerger		}
314094d409bSGuilherme Blanco		if (ce->ce_flags & ZEND_ACC_FINAL) {
315f3f594a4SNikita Popov			smart_str_append_printf(str, "final ");
316516c2f59SStanislav Malyshev		}
317f3f594a4SNikita Popov		smart_str_append_printf(str, "class ");
3187cb0480dSMarcus Boerger	}
319f3f594a4SNikita Popov	smart_str_append_printf(str, "%s", ZSTR_VAL(ce->name));
3207cb0480dSMarcus Boerger	if (ce->parent) {
321f3f594a4SNikita Popov		smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
3227cb0480dSMarcus Boerger	}
3237cb0480dSMarcus Boerger
3247cb0480dSMarcus Boerger	if (ce->num_interfaces) {
3256f9f0bf2SAnatol Belski		uint32_t i;
3267cb0480dSMarcus Boerger
327dd9e9f26SHannes Magnusson		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
328f3f594a4SNikita Popov			smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
329dd9e9f26SHannes Magnusson		} else {
330f3f594a4SNikita Popov			smart_str_append_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
331dd9e9f26SHannes Magnusson		}
3327cb0480dSMarcus Boerger		for (i = 1; i < ce->num_interfaces; ++i) {
333f3f594a4SNikita Popov			smart_str_append_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
3347cb0480dSMarcus Boerger		}
3357cb0480dSMarcus Boerger	}
336f3f594a4SNikita Popov	smart_str_append_printf(str, " ] {\n");
3377cb0480dSMarcus Boerger
3387cb0480dSMarcus Boerger	/* The information where a class is declared is only available for user classes */
3397cb0480dSMarcus Boerger	if (ce->type == ZEND_USER_CLASS) {
340f3f594a4SNikita Popov		smart_str_append_printf(str, "%s  @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
341f2df6a4aSDmitry Stogov						ce->info.user.line_start, ce->info.user.line_end);
3427cb0480dSMarcus Boerger	}
3437cb0480dSMarcus Boerger
3447cb0480dSMarcus Boerger	/* Constants */
345f3f594a4SNikita Popov	smart_str_append_printf(str, "\n");
34695446b44SXinchen Hui	count = zend_hash_num_elements(&ce->constants_table);
347f3f594a4SNikita Popov	smart_str_append_printf(str, "%s  - Constants [%d] {\n", indent, count);
34895446b44SXinchen Hui	if (count > 0) {
34995446b44SXinchen Hui		zend_string *key;
350a75c1950SDmitry Stogov		zend_class_constant *c;
35195446b44SXinchen Hui
352a75c1950SDmitry Stogov		ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
353a1145c0cSNikita Popov			_class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent));
3549064dca5SXinchen Hui			if (UNEXPECTED(EG(exception))) {
3559c5717d0SXinchen Hui				return;
3569c5717d0SXinchen Hui			}
35795446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
35895446b44SXinchen Hui	}
359f3f594a4SNikita Popov	smart_str_append_printf(str, "%s  }\n", indent);
3607cb0480dSMarcus Boerger
3617cb0480dSMarcus Boerger	/* Static properties */
36295446b44SXinchen Hui	/* counting static properties */
36395446b44SXinchen Hui	count = zend_hash_num_elements(&ce->properties_info);
36495446b44SXinchen Hui	if (count > 0) {
36595446b44SXinchen Hui		zend_property_info *prop;
36695446b44SXinchen Hui
36795446b44SXinchen Hui		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
36895446b44SXinchen Hui			if(prop->flags & ZEND_ACC_SHADOW) {
36995446b44SXinchen Hui				count_shadow_props++;
37095446b44SXinchen Hui			} else if (prop->flags & ZEND_ACC_STATIC) {
37195446b44SXinchen Hui				count_static_props++;
37295446b44SXinchen Hui			}
37395446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
37495446b44SXinchen Hui	}
3757cb0480dSMarcus Boerger
37695446b44SXinchen Hui	/* static properties */
377f3f594a4SNikita Popov	smart_str_append_printf(str, "\n%s  - Static properties [%d] {\n", indent, count_static_props);
37895446b44SXinchen Hui	if (count_static_props > 0) {
37995446b44SXinchen Hui		zend_property_info *prop;
3807cb0480dSMarcus Boerger
38195446b44SXinchen Hui		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
38295446b44SXinchen Hui			if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
383a1145c0cSNikita Popov				_property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
38495446b44SXinchen Hui			}
38595446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
38695446b44SXinchen Hui	}
387f3f594a4SNikita Popov	smart_str_append_printf(str, "%s  }\n", indent);
388516c2f59SStanislav Malyshev
3897cb0480dSMarcus Boerger	/* Static methods */
39095446b44SXinchen Hui	/* counting static methods */
39195446b44SXinchen Hui	count = zend_hash_num_elements(&ce->function_table);
39295446b44SXinchen Hui	if (count > 0) {
39395446b44SXinchen Hui		zend_function *mptr;
39495446b44SXinchen Hui
39595446b44SXinchen Hui		ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
39695446b44SXinchen Hui			if (mptr->common.fn_flags & ZEND_ACC_STATIC
39795446b44SXinchen Hui				&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
39895446b44SXinchen Hui			{
39995446b44SXinchen Hui				count_static_funcs++;
40095446b44SXinchen Hui			}
40195446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
40295446b44SXinchen Hui	}
4037cb0480dSMarcus Boerger
40495446b44SXinchen Hui	/* static methods */
405f3f594a4SNikita Popov	smart_str_append_printf(str, "\n%s  - Static methods [%d] {", indent, count_static_funcs);
40695446b44SXinchen Hui	if (count_static_funcs > 0) {
40795446b44SXinchen Hui		zend_function *mptr;
4087cb0480dSMarcus Boerger
40995446b44SXinchen Hui		ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
41095446b44SXinchen Hui			if (mptr->common.fn_flags & ZEND_ACC_STATIC
41195446b44SXinchen Hui				&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
41295446b44SXinchen Hui			{
413f3f594a4SNikita Popov				smart_str_append_printf(str, "\n");
414a1145c0cSNikita Popov				_function_string(str, mptr, ce, ZSTR_VAL(sub_indent));
41595446b44SXinchen Hui			}
41695446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
41795446b44SXinchen Hui	} else {
418f3f594a4SNikita Popov		smart_str_append_printf(str, "\n");
41995446b44SXinchen Hui	}
420f3f594a4SNikita Popov	smart_str_append_printf(str, "%s  }\n", indent);
4217cb0480dSMarcus Boerger
4227cb0480dSMarcus Boerger	/* Default/Implicit properties */
42395446b44SXinchen Hui	count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
424f3f594a4SNikita Popov	smart_str_append_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
42595446b44SXinchen Hui	if (count > 0) {
42695446b44SXinchen Hui		zend_property_info *prop;
42795446b44SXinchen Hui
42895446b44SXinchen Hui		ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
42995446b44SXinchen Hui			if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
430a1145c0cSNikita Popov				_property_string(str, prop, NULL, ZSTR_VAL(sub_indent));
43195446b44SXinchen Hui			}
43295446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
43395446b44SXinchen Hui	}
434f3f594a4SNikita Popov	smart_str_append_printf(str, "%s  }\n", indent);
4357cb0480dSMarcus Boerger
4364a1ecf0eSDmitry Stogov	if (obj && Z_TYPE_P(obj) == IS_OBJECT && Z_OBJ_HT_P(obj)->get_properties) {
437bdeb220fSAnatol Belski		HashTable    *properties = Z_OBJ_HT_P(obj)->get_properties(obj);
4381eb43521SDmitry Stogov		zend_string  *prop_name;
439f3f594a4SNikita Popov		smart_str prop_str = {0};
4407cb0480dSMarcus Boerger
4417cb0480dSMarcus Boerger		count = 0;
442485f28aaSKalle Sommer Nielsen		if (properties && zend_hash_num_elements(properties)) {
4431eb43521SDmitry Stogov			ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
4444a2e40bbSDmitry Stogov				if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
4451eb43521SDmitry Stogov					if (!zend_hash_exists(&ce->properties_info, prop_name)) {
4461eb43521SDmitry Stogov						count++;
447a1145c0cSNikita Popov						_property_string(&prop_str, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent));
4487cb0480dSMarcus Boerger					}
4497cb0480dSMarcus Boerger				}
4501eb43521SDmitry Stogov			} ZEND_HASH_FOREACH_END();
4517cb0480dSMarcus Boerger		}
4527cb0480dSMarcus Boerger
453f3f594a4SNikita Popov		smart_str_append_printf(str, "\n%s  - Dynamic properties [%d] {\n", indent, count);
454f3f594a4SNikita Popov		smart_str_append_smart_str(str, &prop_str);
455f3f594a4SNikita Popov		smart_str_append_printf(str, "%s  }\n", indent);
456f3f594a4SNikita Popov		smart_str_free(&prop_str);
4577cb0480dSMarcus Boerger	}
4587cb0480dSMarcus Boerger
4597cb0480dSMarcus Boerger	/* Non static methods */
46095446b44SXinchen Hui	count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
46195446b44SXinchen Hui	if (count > 0) {
46295446b44SXinchen Hui		zend_function *mptr;
46395446b44SXinchen Hui		zend_string *key;
464f3f594a4SNikita Popov		smart_str method_str = {0};
465a04b6ed6SDmitry Stogov
46695446b44SXinchen Hui		count = 0;
46795446b44SXinchen Hui		ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) {
46895446b44SXinchen Hui			if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
46995446b44SXinchen Hui				&& ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
47095446b44SXinchen Hui			{
47195446b44SXinchen Hui				size_t len = ZSTR_LEN(mptr->common.function_name);
47295446b44SXinchen Hui
47395446b44SXinchen Hui				/* Do not display old-style inherited constructors */
47495446b44SXinchen Hui				if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0
47595446b44SXinchen Hui					|| mptr->common.scope == ce
47695446b44SXinchen Hui					|| !key
47795446b44SXinchen Hui					|| zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0)
47895446b44SXinchen Hui				{
47995446b44SXinchen Hui					zend_function *closure;
48095446b44SXinchen Hui					/* see if this is a closure */
48195446b44SXinchen Hui					if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
48295446b44SXinchen Hui						&& memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
48395446b44SXinchen Hui						&& (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
4846d083e2cSMarcus Boerger					{
48595446b44SXinchen Hui						mptr = closure;
48695446b44SXinchen Hui					} else {
48795446b44SXinchen Hui						closure = NULL;
488a04b6ed6SDmitry Stogov					}
489f3f594a4SNikita Popov					smart_str_appendc(&method_str, '\n');
490a1145c0cSNikita Popov					_function_string(&method_str, mptr, ce, ZSTR_VAL(sub_indent));
49195446b44SXinchen Hui					count++;
49295446b44SXinchen Hui					_free_function(closure);
4937cb0480dSMarcus Boerger				}
494626881d9SMarcus Boerger			}
49595446b44SXinchen Hui		} ZEND_HASH_FOREACH_END();
496f3f594a4SNikita Popov		smart_str_append_printf(str, "\n%s  - Methods [%d] {", indent, count);
497f3f594a4SNikita Popov		smart_str_append_smart_str(str, &method_str);
49895446b44SXinchen Hui		if (!count) {
499f3f594a4SNikita Popov			smart_str_append_printf(str, "\n");
5007cb0480dSMarcus Boerger		}
501f3f594a4SNikita Popov		smart_str_free(&method_str);
50295446b44SXinchen Hui	} else {
503f3f594a4SNikita Popov		smart_str_append_printf(str, "\n%s  - Methods [0] {\n", indent);
50495446b44SXinchen Hui	}
505f3f594a4SNikita Popov	smart_str_append_printf(str, "%s  }\n", indent);
506516c2f59SStanislav Malyshev
507f3f594a4SNikita Popov	smart_str_append_printf(str, "%s}\n", indent);
5085eb1f92fSDmitry Stogov	zend_string_release_ex(sub_indent, 0);
5097cb0480dSMarcus Boerger}
5107cb0480dSMarcus Boerger/* }}} */
5117cb0480dSMarcus Boerger
5127cb0480dSMarcus Boerger/* {{{ _const_string */
513f3f594a4SNikita Popovstatic void _const_string(smart_str *str, char *name, zval *value, char *indent)
5147cb0480dSMarcus Boerger{
5150d43a277SNikita Popov	char *type = zend_zval_type_name(value);
5166a1b4c99SJohannes Schlüter
517eb190b4eSnikita	if (Z_TYPE_P(value) == IS_ARRAY) {
518f3f594a4SNikita Popov		smart_str_append_printf(str, "%s    Constant [ %s %s ] { Array }\n",
519eb190b4eSnikita						indent, type, name);
520fcb13fabSDmitry Stogov	} else if (Z_TYPE_P(value) == IS_STRING) {
521fcb13fabSDmitry Stogov		smart_str_append_printf(str, "%s    Constant [ %s %s ] { %s }\n",
522fcb13fabSDmitry Stogov						indent, type, name, Z_STRVAL_P(value));
523eb190b4eSnikita	} else {
524ccc12b82SDmitry Stogov		zend_string *tmp_value_str;
525ccc12b82SDmitry Stogov		zend_string *value_str = zval_get_tmp_string(value, &tmp_value_str);
526f3f594a4SNikita Popov		smart_str_append_printf(str, "%s    Constant [ %s %s ] { %s }\n",
52757c99836SNikita Popov						indent, type, name, ZSTR_VAL(value_str));
528ccc12b82SDmitry Stogov		zend_tmp_string_release(tmp_value_str);
5296a1b4c99SJohannes Schlüter	}
5307cb0480dSMarcus Boerger}
5317cb0480dSMarcus Boerger/* }}} */
5327cb0480dSMarcus Boerger
533a75c1950SDmitry Stogov/* {{{ _class_const_string */
534f3f594a4SNikita Popovstatic void _class_const_string(smart_str *str, char *name, zend_class_constant *c, char *indent)
535a75c1950SDmitry Stogov{
536a75c1950SDmitry Stogov	char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
5374b0f9586SNikita Popov	char *type;
538a75c1950SDmitry Stogov
5394b0f9586SNikita Popov	zval_update_constant_ex(&c->value, c->ce);
5404b0f9586SNikita Popov	type = zend_zval_type_name(&c->value);
5414b0f9586SNikita Popov
542981b94e0SNikita Popov	if (Z_TYPE(c->value) == IS_ARRAY) {
543f3f594a4SNikita Popov		smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
544981b94e0SNikita Popov						indent, visibility, type, name);
545981b94e0SNikita Popov	} else {
546ccc12b82SDmitry Stogov		zend_string *tmp_value_str;
547ccc12b82SDmitry Stogov		zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
548981b94e0SNikita Popov
549f3f594a4SNikita Popov		smart_str_append_printf(str, "%sConstant [ %s %s %s ] { %s }\n",
550981b94e0SNikita Popov						indent, visibility, type, name, ZSTR_VAL(value_str));
551a75c1950SDmitry Stogov
552ccc12b82SDmitry Stogov		zend_tmp_string_release(tmp_value_str);
553981b94e0SNikita Popov	}
554a75c1950SDmitry Stogov}
555a75c1950SDmitry Stogov/* }}} */
556a75c1950SDmitry Stogov
5577cb0480dSMarcus Boerger/* {{{ _get_recv_opcode */
5586f9f0bf2SAnatol Belskistatic zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
5597cb0480dSMarcus Boerger{
5607cb0480dSMarcus Boerger	zend_op *op = op_array->opcodes;
5617cb0480dSMarcus Boerger	zend_op *end = op + op_array->last;
5627cb0480dSMarcus Boerger
5637cb0480dSMarcus Boerger	++offset;
5647cb0480dSMarcus Boerger	while (op < end) {
565b7a7b1a6SStanislav Malyshev		if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
566323b2733SDmitry Stogov		    || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == offset)
5676d083e2cSMarcus Boerger		{
5686d083e2cSMarcus Boerger			return op;
5696d083e2cSMarcus Boerger		}
5706d083e2cSMarcus Boerger		++op;
5717cb0480dSMarcus Boerger	}
5727cb0480dSMarcus Boerger	return NULL;
5737cb0480dSMarcus Boerger}
5747cb0480dSMarcus Boerger/* }}} */
5757cb0480dSMarcus Boerger
5767cb0480dSMarcus Boerger/* {{{ _parameter_string */
577f3f594a4SNikita Popovstatic void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, char* indent)
5787cb0480dSMarcus Boerger{
579f3f594a4SNikita Popov	smart_str_append_printf(str, "Parameter #%d [ ", offset);
580e52d2b88SBarbu Paul - Gheorghe	if (!required) {
581f3f594a4SNikita Popov		smart_str_append_printf(str, "<optional> ");
5827cb0480dSMarcus Boerger	} else {
583f3f594a4SNikita Popov		smart_str_append_printf(str, "<required> ");
5847cb0480dSMarcus Boerger	}
585141d1ba9SDmitry Stogov	if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
586f3f594a4SNikita Popov		smart_str_append_printf(str, "%s ",
587141d1ba9SDmitry Stogov			ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type)));
588141d1ba9SDmitry Stogov		if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
589f3f594a4SNikita Popov			smart_str_append_printf(str, "or NULL ");
5907cb0480dSMarcus Boerger		}
591141d1ba9SDmitry Stogov	} else if (ZEND_TYPE_IS_CODE(arg_info->type)) {
592141d1ba9SDmitry Stogov		smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type)));
593141d1ba9SDmitry Stogov		if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
594f3f594a4SNikita Popov			smart_str_append_printf(str, "or NULL ");
5957cb0480dSMarcus Boerger		}
5967cb0480dSMarcus Boerger	}
5977cb0480dSMarcus Boerger	if (arg_info->pass_by_reference) {
598f3f594a4SNikita Popov		smart_str_appendc(str, '&');
5997cb0480dSMarcus Boerger	}
6000d7a6388SNikita Popov	if (arg_info->is_variadic) {
601f3f594a4SNikita Popov		smart_str_appends(str, "...");
6020d7a6388SNikita Popov	}
6037cb0480dSMarcus Boerger	if (arg_info->name) {
604f3f594a4SNikita Popov		smart_str_append_printf(str, "$%s",
605ed84bff4SDmitry Stogov			(fptr->type == ZEND_INTERNAL_FUNCTION &&
606ed84bff4SDmitry Stogov			 !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
6075dd427eaSDmitry Stogov			((zend_internal_arg_info*)arg_info)->name :
6084a2e40bbSDmitry Stogov			ZSTR_VAL(arg_info->name));
6097cb0480dSMarcus Boerger	} else {
610f3f594a4SNikita Popov		smart_str_append_printf(str, "$param%d", offset);
6117cb0480dSMarcus Boerger	}
612e52d2b88SBarbu Paul - Gheorghe	if (fptr->type == ZEND_USER_FUNCTION && !required) {
6137cb0480dSMarcus Boerger		zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
61494dd8372SDmitry Stogov		if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
6150d43a277SNikita Popov			zval zv;
616d909b633SDmitry Stogov
617f3f594a4SNikita Popov			smart_str_appends(str, " = ");
6187b16205fSNikita Popov			ZVAL_COPY(&zv, RT_CONSTANT(precv, precv->op2));
6199064dca5SXinchen Hui			if (UNEXPECTED(zval_update_constant_ex(&zv, fptr->common.scope) == FAILURE)) {
6209c5717d0SXinchen Hui				zval_ptr_dtor(&zv);
6219c5717d0SXinchen Hui				return;
6229c5717d0SXinchen Hui			}
62317d027edSDmitry Stogov			if (Z_TYPE(zv) == IS_TRUE) {
624f3f594a4SNikita Popov				smart_str_appends(str, "true");
62517d027edSDmitry Stogov			} else if (Z_TYPE(zv) == IS_FALSE) {
626f3f594a4SNikita Popov				smart_str_appends(str, "false");
627f4cfaf36SDmitry Stogov			} else if (Z_TYPE(zv) == IS_NULL) {
628f3f594a4SNikita Popov				smart_str_appends(str, "NULL");
629f4cfaf36SDmitry Stogov			} else if (Z_TYPE(zv) == IS_STRING) {
630f3f594a4SNikita Popov				smart_str_appendc(str, '\'');
631f3f594a4SNikita Popov				smart_str_appendl(str, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 15));
632c3e3c98eSAnatol Belski				if (Z_STRLEN(zv) > 15) {
633f3f594a4SNikita Popov					smart_str_appends(str, "...");
6347cb0480dSMarcus Boerger				}
635f3f594a4SNikita Popov				smart_str_appendc(str, '\'');
636f4cfaf36SDmitry Stogov			} else if (Z_TYPE(zv) == IS_ARRAY) {
637f3f594a4SNikita Popov				smart_str_appends(str, "Array");
6387cb0480dSMarcus Boerger			} else {
639ccc12b82SDmitry Stogov				zend_string *tmp_zv_str;
640ccc12b82SDmitry Stogov				zend_string *zv_str = zval_get_tmp_string(&zv, &tmp_zv_str);
641f3f594a4SNikita Popov				smart_str_append(str, zv_str);
642ccc12b82SDmitry Stogov				zend_tmp_string_release(tmp_zv_str);
6437cb0480dSMarcus Boerger			}
6447cb0480dSMarcus Boerger			zval_ptr_dtor(&zv);
6457cb0480dSMarcus Boerger		}
6467cb0480dSMarcus Boerger	}
647f3f594a4SNikita Popov	smart_str_appends(str, " ]");
6487cb0480dSMarcus Boerger}
6497cb0480dSMarcus Boerger/* }}} */
6507cb0480dSMarcus Boerger
6517cb0480dSMarcus Boerger/* {{{ _function_parameter_string */
652f3f594a4SNikita Popovstatic void _function_parameter_string(smart_str *str, zend_function *fptr, char* indent)
6537cb0480dSMarcus Boerger{
6547cb0480dSMarcus Boerger	struct _zend_arg_info *arg_info = fptr->common.arg_info;
655e52d2b88SBarbu Paul - Gheorghe	uint32_t i, num_args, num_required = fptr->common.required_num_args;
6567cb0480dSMarcus Boerger
6577cb0480dSMarcus Boerger	if (!arg_info) {
6587cb0480dSMarcus Boerger		return;
6597cb0480dSMarcus Boerger	}
6607cb0480dSMarcus Boerger
6612646f7bcSDmitry Stogov	num_args = fptr->common.num_args;
6622646f7bcSDmitry Stogov	if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
6632646f7bcSDmitry Stogov		num_args++;
6642646f7bcSDmitry Stogov	}
665f3f594a4SNikita Popov	smart_str_appendc(str, '\n');
666f3f594a4SNikita Popov	smart_str_append_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
6672646f7bcSDmitry Stogov	for (i = 0; i < num_args; i++) {
668f3f594a4SNikita Popov		smart_str_append_printf(str, "%s  ", indent);
669e52d2b88SBarbu Paul - Gheorghe		_parameter_string(str, fptr, arg_info, i, i < num_required, indent);
670f3f594a4SNikita Popov		smart_str_appendc(str, '\n');
6717cb0480dSMarcus Boerger		arg_info++;
6727cb0480dSMarcus Boerger	}
673f3f594a4SNikita Popov	smart_str_append_printf(str, "%s}\n", indent);
6747cb0480dSMarcus Boerger}
6757cb0480dSMarcus Boerger/* }}} */
6767cb0480dSMarcus Boerger
677c6d89bd4SChristian Seiler/* {{{ _function_closure_string */
678f3f594a4SNikita Popovstatic void _function_closure_string(smart_str *str, zend_function *fptr, char* indent)
679c6d89bd4SChristian Seiler{
6806f9f0bf2SAnatol Belski	uint32_t i, count;
681f4cfaf36SDmitry Stogov	zend_string *key;
682c6d89bd4SChristian Seiler	HashTable *static_variables;
683c6d89bd4SChristian Seiler
684c6d89bd4SChristian Seiler	if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
685c6d89bd4SChristian Seiler		return;
686c6d89bd4SChristian Seiler	}
687c6d89bd4SChristian Seiler
688c6d89bd4SChristian Seiler	static_variables = fptr->op_array.static_variables;
689c6d89bd4SChristian Seiler	count = zend_hash_num_elements(static_variables);
690c6d89bd4SChristian Seiler
691c6d89bd4SChristian Seiler	if (!count) {
692c6d89bd4SChristian Seiler		return;
693c6d89bd4SChristian Seiler	}
694c6d89bd4SChristian Seiler
695f3f594a4SNikita Popov	smart_str_append_printf(str, "\n");
696f3f594a4SNikita Popov	smart_str_append_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
697c6d89bd4SChristian Seiler	i = 0;
6981eb43521SDmitry Stogov	ZEND_HASH_FOREACH_STR_KEY(static_variables, key) {
699f3f594a4SNikita Popov		smart_str_append_printf(str, "%s    Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
7001eb43521SDmitry Stogov	} ZEND_HASH_FOREACH_END();
701f3f594a4SNikita Popov	smart_str_append_printf(str, "%s}\n", indent);
702c6d89bd4SChristian Seiler}
703c6d89bd4SChristian Seiler/* }}} */
704c6d89bd4SChristian Seiler
7057cb0480dSMarcus Boerger/* {{{ _function_string */
706f3f594a4SNikita Popovstatic void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, char* indent)
7077cb0480dSMarcus Boerger{
708f3f594a4SNikita Popov	smart_str param_indent = {0};
7097cb0480dSMarcus Boerger	zend_function *overwrites;
710f4cfaf36SDmitry Stogov	zend_string *lc_name;
7117cb0480dSMarcus Boerger
7127cb0480dSMarcus Boerger	/* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
713516c2f59SStanislav Malyshev	 * What's "wrong" is that any whitespace before the doc comment start is
7147cb0480dSMarcus Boerger	 * swallowed, leading to an unaligned comment.
7157cb0480dSMarcus Boerger	 */
7167cb0480dSMarcus Boerger	if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
717f3f594a4SNikita Popov		smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
7187cb0480dSMarcus Boerger	}
7197cb0480dSMarcus Boerger
720f3f594a4SNikita Popov	smart_str_appendl(str, indent, strlen(indent));
721f3f594a4SNikita Popov	smart_str_append_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
722f3f594a4SNikita Popov	smart_str_append_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
723941b0651SMarcus Boerger	if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
724f3f594a4SNikita Popov		smart_str_appends(str, ", deprecated");
725941b0651SMarcus Boerger	}
7267cb0480dSMarcus Boerger	if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
727f3f594a4SNikita Popov		smart_str_append_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
7287cb0480dSMarcus Boerger	}
729407c9833SMarcus Boerger
7307cb0480dSMarcus Boerger	if (scope && fptr->common.scope) {
7317cb0480dSMarcus Boerger		if (fptr->common.scope != scope) {
732f3f594a4SNikita Popov			smart_str_append_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
7337cb0480dSMarcus Boerger		} else if (fptr->common.scope->parent) {
734084c17feSDmitry Stogov			lc_name = zend_string_tolower(fptr->common.function_name);
735f4cfaf36SDmitry Stogov			if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
7367cb0480dSMarcus Boerger				if (fptr->common.scope != overwrites->common.scope) {
737f3f594a4SNikita Popov					smart_str_append_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
7387cb0480dSMarcus Boerger				}
7397cb0480dSMarcus Boerger			}
7405eb1f92fSDmitry Stogov			zend_string_release_ex(lc_name, 0);
7417cb0480dSMarcus Boerger		}
7427cb0480dSMarcus Boerger	}
7437cb0480dSMarcus Boerger	if (fptr->common.prototype && fptr->common.prototype->common.scope) {
744f3f594a4SNikita Popov		smart_str_append_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
7457cb0480dSMarcus Boerger	}
7467cb0480dSMarcus Boerger	if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
747f3f594a4SNikita Popov		smart_str_appends(str, ", ctor");
7487cb0480dSMarcus Boerger	}
7497cb0480dSMarcus Boerger	if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
750f3f594a4SNikita Popov		smart_str_appends(str, ", dtor");
7517cb0480dSMarcus Boerger	}
752f3f594a4SNikita Popov	smart_str_appends(str, "> ");
7537cb0480dSMarcus Boerger
7547cb0480dSMarcus Boerger	if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
755f3f594a4SNikita Popov		smart_str_appends(str, "abstract ");
7567cb0480dSMarcus Boerger	}
7577cb0480dSMarcus Boerger	if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
758f3f594a4SNikita Popov		smart_str_appends(str, "final ");
7597cb0480dSMarcus Boerger	}
7607cb0480dSMarcus Boerger	if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
761f3f594a4SNikita Popov		smart_str_appends(str, "static ");
7627cb0480dSMarcus Boerger	}
7637cb0480dSMarcus Boerger
764bbcd8c5bSJohannes Schlüter	if (fptr->common.scope) {
765bbcd8c5bSJohannes Schlüter		/* These are mutually exclusive */
766bbcd8c5bSJohannes Schlüter		switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
767bbcd8c5bSJohannes Schlüter			case ZEND_ACC_PUBLIC:
768f3f594a4SNikita Popov				smart_str_appends(str, "public ");
769bbcd8c5bSJohannes Schlüter				break;
770bbcd8c5bSJohannes Schlüter			case ZEND_ACC_PRIVATE:
771f3f594a4SNikita Popov				smart_str_appends(str, "private ");
772bbcd8c5bSJohannes Schlüter				break;
773bbcd8c5bSJohannes Schlüter			case ZEND_ACC_PROTECTED:
774f3f594a4SNikita Popov				smart_str_appends(str, "protected ");
775bbcd8c5bSJohannes Schlüter				break;
776bbcd8c5bSJohannes Schlüter			default:
777f3f594a4SNikita Popov				smart_str_appends(str, "<visibility error> ");
7786d083e2cSMarcus Boerger				break;
779bbcd8c5bSJohannes Schlüter		}
780f3f594a4SNikita Popov		smart_str_appends(str, "method ");
781bbcd8c5bSJohannes Schlüter	} else {
782f3f594a4SNikita Popov		smart_str_appends(str, "function ");
783bbcd8c5bSJohannes Schlüter	}
784bbcd8c5bSJohannes Schlüter
785f2df6a4aSDmitry Stogov	if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
786f3f594a4SNikita Popov		smart_str_appendc(str, '&');
7877cb0480dSMarcus Boerger	}
788f3f594a4SNikita Popov	smart_str_append_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
7897cb0480dSMarcus Boerger	/* The information where a function is declared is only available for user classes */
7907cb0480dSMarcus Boerger	if (fptr->type == ZEND_USER_FUNCTION) {
791f3f594a4SNikita Popov		smart_str_append_printf(str, "%s  @@ %s %d - %d\n", indent,
7924a2e40bbSDmitry Stogov						ZSTR_VAL(fptr->op_array.filename),
7936d083e2cSMarcus Boerger						fptr->op_array.line_start,
7946d083e2cSMarcus Boerger						fptr->op_array.line_end);
7957cb0480dSMarcus Boerger	}
796f3f594a4SNikita Popov	smart_str_append_printf(&param_indent, "%s  ", indent);
797f3f594a4SNikita Popov	smart_str_0(&param_indent);
798c6d89bd4SChristian Seiler	if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
799f3f594a4SNikita Popov		_function_closure_string(str, fptr, ZSTR_VAL(param_indent.s));
800c6d89bd4SChristian Seiler	}
801f3f594a4SNikita Popov	_function_parameter_string(str, fptr, ZSTR_VAL(param_indent.s));
802f3f594a4SNikita Popov	smart_str_free(&param_indent);
803c8576c5aSLevi Morrison	if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
804f3f594a4SNikita Popov		smart_str_append_printf(str, "  %s- Return [ ", indent);
805141d1ba9SDmitry Stogov		if (ZEND_TYPE_IS_CLASS(fptr->common.arg_info[-1].type)) {
806f3f594a4SNikita Popov			smart_str_append_printf(str, "%s ",
807141d1ba9SDmitry Stogov				ZSTR_VAL(ZEND_TYPE_NAME(fptr->common.arg_info[-1].type)));
808141d1ba9SDmitry Stogov			if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
809f3f594a4SNikita Popov				smart_str_appends(str, "or NULL ");
810c8576c5aSLevi Morrison			}
811141d1ba9SDmitry Stogov		} else if (ZEND_TYPE_IS_CODE(fptr->common.arg_info[-1].type)) {
812141d1ba9SDmitry Stogov			smart_str_append_printf(str, "%s ", zend_get_type_by_const(ZEND_TYPE_CODE(fptr->common.arg_info[-1].type)));
813141d1ba9SDmitry Stogov			if (ZEND_TYPE_ALLOW_NULL(fptr->common.arg_info[-1].type)) {
814f3f594a4SNikita Popov				smart_str_appends(str, "or NULL ");
815c8576c5aSLevi Morrison			}
816c8576c5aSLevi Morrison		}
817f3f594a4SNikita Popov		smart_str_appends(str, "]\n");
818c8576c5aSLevi Morrison	}
819f3f594a4SNikita Popov	smart_str_append_printf(str, "%s}\n", indent);
8207cb0480dSMarcus Boerger}
8217cb0480dSMarcus Boerger/* }}} */
8227cb0480dSMarcus Boerger
8237cb0480dSMarcus Boerger/* {{{ _property_string */
824bddb085aSNikita Popovstatic void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, char* indent)
8257cb0480dSMarcus Boerger{
826f3f594a4SNikita Popov	smart_str_append_printf(str, "%sProperty [ ", indent);
8277cb0480dSMarcus Boerger	if (!prop) {
828f3f594a4SNikita Popov		smart_str_append_printf(str, "<dynamic> public $%s", prop_name);
8297cb0480dSMarcus Boerger	} else {
8307cb0480dSMarcus Boerger		if (!(prop->flags & ZEND_ACC_STATIC)) {
8317cb0480dSMarcus Boerger			if (prop->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
832f3f594a4SNikita Popov				smart_str_appends(str, "<implicit> ");
8337cb0480dSMarcus Boerger			} else {
834f3f594a4SNikita Popov				smart_str_appends(str, "<default> ");
8357cb0480dSMarcus Boerger			}
8367cb0480dSMarcus Boerger		}
837516c2f59SStanislav Malyshev
8387cb0480dSMarcus Boerger		/* These are mutually exclusive */
8397cb0480dSMarcus Boerger		switch (prop->flags & ZEND_ACC_PPP_MASK) {
8407cb0480dSMarcus Boerger			case ZEND_ACC_PUBLIC:
841f3f594a4SNikita Popov				smart_str_appends(str, "public ");
8427cb0480dSMarcus Boerger				break;
8437cb0480dSMarcus Boerger			case ZEND_ACC_PRIVATE:
844f3f594a4SNikita Popov				smart_str_appends(str, "private ");
8457cb0480dSMarcus Boerger				break;
8467cb0480dSMarcus Boerger			case ZEND_ACC_PROTECTED:
847f3f594a4SNikita Popov				smart_str_appends(str, "protected ");
8487cb0480dSMarcus Boerger				break;
8497cb0480dSMarcus Boerger		}
850bddb085aSNikita Popov		if (prop->flags & ZEND_ACC_STATIC) {
851f3f594a4SNikita Popov			smart_str_appends(str, "static ");
8527cb0480dSMarcus Boerger		}
853bddb085aSNikita Popov		if (!prop_name) {
854bddb085aSNikita Popov			const char *class_name;
855bddb085aSNikita Popov			zend_unmangle_property_name(prop->name, &class_name, &prop_name);
856bddb085aSNikita Popov		}
857f3f594a4SNikita Popov		smart_str_append_printf(str, "$%s", prop_name);
8587cb0480dSMarcus Boerger	}
8597cb0480dSMarcus Boerger
860f3f594a4SNikita Popov	smart_str_appends(str, " ]\n");
8617cb0480dSMarcus Boerger}
8627cb0480dSMarcus Boerger/* }}} */
8637cb0480dSMarcus Boerger
864bdeb220fSAnatol Belskistatic int _extension_ini_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
8657cb0480dSMarcus Boerger{
866ff5870a2SXinchen Hui	zend_ini_entry *ini_entry = (zend_ini_entry*)Z_PTR_P(el);
867f3f594a4SNikita Popov	smart_str *str = va_arg(args, smart_str *);
8687cb0480dSMarcus Boerger	char *indent = va_arg(args, char *);
8697cb0480dSMarcus Boerger	int number = va_arg(args, int);
8707cb0480dSMarcus Boerger	char *comma = "";
8717cb0480dSMarcus Boerger
8727cb0480dSMarcus Boerger	if (number == ini_entry->module_number) {
873f3f594a4SNikita Popov		smart_str_append_printf(str, "    %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
874c64a4a13SHannes Magnusson		if (ini_entry->modifiable == ZEND_INI_ALL) {
875f3f594a4SNikita Popov			smart_str_appends(str, "ALL");
8767cb0480dSMarcus Boerger		} else {
8777cb0480dSMarcus Boerger			if (ini_entry->modifiable & ZEND_INI_USER) {
878f3f594a4SNikita Popov				smart_str_appends(str, "USER");
8797cb0480dSMarcus Boerger				comma = ",";
8807cb0480dSMarcus Boerger			}
8817cb0480dSMarcus Boerger			if (ini_entry->modifiable & ZEND_INI_PERDIR) {
882f3f594a4SNikita Popov				smart_str_append_printf(str, "%sPERDIR", comma);
8837cb0480dSMarcus Boerger				comma = ",";
8847cb0480dSMarcus Boerger			}
8857cb0480dSMarcus Boerger			if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
886f3f594a4SNikita Popov				smart_str_append_printf(str, "%sSYSTEM", comma);
8877cb0480dSMarcus Boerger			}
8887cb0480dSMarcus Boerger		}
8896d083e2cSMarcus Boerger
890f3f594a4SNikita Popov		smart_str_appends(str, "> ]\n");
891f3f594a4SNikita Popov		smart_str_append_printf(str, "    %s  Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
8927cb0480dSMarcus Boerger		if (ini_entry->modified) {
893f3f594a4SNikita Popov			smart_str_append_printf(str, "    %s  Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
8947cb0480dSMarcus Boerger		}
895f3f594a4SNikita Popov		smart_str_append_printf(str, "    %s}\n", indent);
8967cb0480dSMarcus Boerger	}
8977cb0480dSMarcus Boerger	return ZEND_HASH_APPLY_KEEP;
8987cb0480dSMarcus Boerger}
89997b7620aSJohannes Schlüter/* }}} */
9007cb0480dSMarcus Boerger
901bdeb220fSAnatol Belskistatic int _extension_class_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
9027cb0480dSMarcus Boerger{
903ff5870a2SXinchen Hui	zend_class_entry *ce = (zend_class_entry*)Z_PTR_P(el);
904f3f594a4SNikita Popov	smart_str *str = va_arg(args, smart_str *);
9057cb0480dSMarcus Boerger	char *indent = va_arg(args, char *);
9067cb0480dSMarcus Boerger	struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
9077cb0480dSMarcus Boerger	int *num_classes = va_arg(args, int*);
9087cb0480dSMarcus Boerger
909ff5870a2SXinchen Hui	if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
910efa7f87dSRemi Collet		/* dump class if it is not an alias */
9114a2e40bbSDmitry Stogov		if (!zend_binary_strcasecmp(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key))) {
912f3f594a4SNikita Popov			smart_str_append_printf(str, "\n");
913bdeb220fSAnatol Belski			_class_string(str, ce, NULL, indent);
914efa7f87dSRemi Collet			(*num_classes)++;
915efa7f87dSRemi Collet		}
9167cb0480dSMarcus Boerger	}
9177cb0480dSMarcus Boerger	return ZEND_HASH_APPLY_KEEP;
9187cb0480dSMarcus Boerger}
91997b7620aSJohannes Schlüter/* }}} */
9207cb0480dSMarcus Boerger
921bdeb220fSAnatol Belskistatic int _extension_const_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
9227cb0480dSMarcus Boerger{
923ff5870a2SXinchen Hui	zend_constant *constant = (zend_constant*)Z_PTR_P(el);
924f3f594a4SNikita Popov	smart_str *str = va_arg(args, smart_str *);
9257cb0480dSMarcus Boerger	char *indent = va_arg(args, char *);
9267cb0480dSMarcus Boerger	struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
9277cb0480dSMarcus Boerger	int *num_classes = va_arg(args, int*);
9287cb0480dSMarcus Boerger
929ab8094c6SDmitry Stogov	if (ZEND_CONSTANT_MODULE_NUMBER(constant)  == module->module_number) {
9304a2e40bbSDmitry Stogov		_const_string(str, ZSTR_VAL(constant->name), &constant->value, indent);
9317cb0480dSMarcus Boerger		(*num_classes)++;
9327cb0480dSMarcus Boerger	}
9337cb0480dSMarcus Boerger	return ZEND_HASH_APPLY_KEEP;
9347cb0480dSMarcus Boerger}
93597b7620aSJohannes Schlüter/* }}} */
9367cb0480dSMarcus Boerger
937f3f594a4SNikita Popovstatic void _extension_string(smart_str *str, zend_module_entry *module, char *indent) /* {{{ */
9387cb0480dSMarcus Boerger{
939f3f594a4SNikita Popov	smart_str_append_printf(str, "%sExtension [ ", indent);
9407cb0480dSMarcus Boerger	if (module->type == MODULE_PERSISTENT) {
941