root/ext/reflection/php_reflection.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. string_init
  2. string_printf
  3. string_write
  4. string_append
  5. string_free
  6. reflection_object_from_obj
  7. _default_load_entry
  8. _default_get_entry
  9. _default_lookup_entry
  10. _copy_function
  11. _free_function
  12. reflection_free_objects_storage
  13. reflection_objects_new
  14. reflection_instantiate
  15. _class_string
  16. _const_string
  17. _get_recv_op
  18. _parameter_string
  19. _function_parameter_string
  20. _function_closure_string
  21. _function_string
  22. _property_string
  23. _extension_ini_string
  24. _extension_class_string
  25. _extension_const_string
  26. _extension_string
  27. _zend_extension_string
  28. _function_check_flag
  29. zend_reflection_class_factory
  30. reflection_extension_factory
  31. reflection_parameter_factory
  32. reflection_type_factory
  33. reflection_function_factory
  34. reflection_method_factory
  35. reflection_property_factory
  36. _reflection_export
  37. _reflection_param_get_default_param
  38. _reflection_param_get_default_precv
  39. ZEND_METHOD
  40. ZEND_METHOD
  41. ZEND_METHOD
  42. ZEND_METHOD
  43. ZEND_METHOD
  44. ZEND_METHOD
  45. ZEND_METHOD
  46. ZEND_METHOD
  47. ZEND_METHOD
  48. ZEND_METHOD
  49. ZEND_METHOD
  50. ZEND_METHOD
  51. ZEND_METHOD
  52. ZEND_METHOD
  53. ZEND_METHOD
  54. ZEND_METHOD
  55. ZEND_METHOD
  56. ZEND_METHOD
  57. ZEND_METHOD
  58. ZEND_METHOD
  59. ZEND_METHOD
  60. ZEND_METHOD
  61. ZEND_METHOD
  62. ZEND_METHOD
  63. ZEND_METHOD
  64. ZEND_METHOD
  65. ZEND_METHOD
  66. ZEND_METHOD
  67. ZEND_METHOD
  68. ZEND_METHOD
  69. ZEND_METHOD
  70. ZEND_METHOD
  71. ZEND_METHOD
  72. ZEND_METHOD
  73. ZEND_METHOD
  74. ZEND_METHOD
  75. ZEND_METHOD
  76. ZEND_METHOD
  77. ZEND_METHOD
  78. ZEND_METHOD
  79. ZEND_METHOD
  80. ZEND_METHOD
  81. ZEND_METHOD
  82. ZEND_METHOD
  83. ZEND_METHOD
  84. ZEND_METHOD
  85. ZEND_METHOD
  86. ZEND_METHOD
  87. ZEND_METHOD
  88. ZEND_METHOD
  89. ZEND_METHOD
  90. ZEND_METHOD
  91. ZEND_METHOD
  92. ZEND_METHOD
  93. ZEND_METHOD
  94. ZEND_METHOD
  95. ZEND_METHOD
  96. ZEND_METHOD
  97. ZEND_METHOD
  98. ZEND_METHOD
  99. ZEND_METHOD
  100. ZEND_METHOD
  101. ZEND_METHOD
  102. ZEND_METHOD
  103. ZEND_METHOD
  104. ZEND_METHOD
  105. ZEND_METHOD
  106. ZEND_METHOD
  107. ZEND_METHOD
  108. ZEND_METHOD
  109. ZEND_METHOD
  110. ZEND_METHOD
  111. ZEND_METHOD
  112. ZEND_METHOD
  113. ZEND_METHOD
  114. ZEND_METHOD
  115. ZEND_METHOD
  116. ZEND_METHOD
  117. ZEND_METHOD
  118. ZEND_METHOD
  119. ZEND_METHOD
  120. ZEND_METHOD
  121. ZEND_METHOD
  122. ZEND_METHOD
  123. ZEND_METHOD
  124. reflection_class_object_ctor
  125. ZEND_METHOD
  126. add_class_vars
  127. ZEND_METHOD
  128. ZEND_METHOD
  129. ZEND_METHOD
  130. ZEND_METHOD
  131. ZEND_METHOD
  132. ZEND_METHOD
  133. ZEND_METHOD
  134. ZEND_METHOD
  135. ZEND_METHOD
  136. ZEND_METHOD
  137. ZEND_METHOD
  138. ZEND_METHOD
  139. ZEND_METHOD
  140. ZEND_METHOD
  141. ZEND_METHOD
  142. ZEND_METHOD
  143. _addmethod
  144. _addmethod_va
  145. ZEND_METHOD
  146. ZEND_METHOD
  147. ZEND_METHOD
  148. _addproperty
  149. _adddynproperty
  150. ZEND_METHOD
  151. ZEND_METHOD
  152. ZEND_METHOD
  153. ZEND_METHOD
  154. _class_check_flag
  155. ZEND_METHOD
  156. ZEND_METHOD
  157. ZEND_METHOD
  158. ZEND_METHOD
  159. ZEND_METHOD
  160. ZEND_METHOD
  161. ZEND_METHOD
  162. ZEND_METHOD
  163. ZEND_METHOD
  164. ZEND_METHOD
  165. ZEND_METHOD
  166. ZEND_METHOD
  167. ZEND_METHOD
  168. ZEND_METHOD
  169. ZEND_METHOD
  170. ZEND_METHOD
  171. ZEND_METHOD
  172. ZEND_METHOD
  173. ZEND_METHOD
  174. ZEND_METHOD
  175. ZEND_METHOD
  176. ZEND_METHOD
  177. ZEND_METHOD
  178. ZEND_METHOD
  179. ZEND_METHOD
  180. ZEND_METHOD
  181. ZEND_METHOD
  182. ZEND_METHOD
  183. ZEND_METHOD
  184. ZEND_METHOD
  185. ZEND_METHOD
  186. _property_check_flag
  187. ZEND_METHOD
  188. ZEND_METHOD
  189. ZEND_METHOD
  190. ZEND_METHOD
  191. ZEND_METHOD
  192. ZEND_METHOD
  193. ZEND_METHOD
  194. ZEND_METHOD
  195. ZEND_METHOD
  196. ZEND_METHOD
  197. ZEND_METHOD
  198. ZEND_METHOD
  199. ZEND_METHOD
  200. ZEND_METHOD
  201. ZEND_METHOD
  202. ZEND_METHOD
  203. ZEND_METHOD
  204. _addconstant
  205. ZEND_METHOD
  206. _addinientry
  207. ZEND_METHOD
  208. add_extension_class
  209. ZEND_METHOD
  210. ZEND_METHOD
  211. ZEND_METHOD
  212. ZEND_METHOD
  213. ZEND_METHOD
  214. ZEND_METHOD
  215. ZEND_METHOD
  216. ZEND_METHOD
  217. ZEND_METHOD
  218. ZEND_METHOD
  219. ZEND_METHOD
  220. ZEND_METHOD
  221. ZEND_METHOD
  222. ZEND_METHOD
  223. _reflection_write_property
  224. PHP_MINIT_FUNCTION
  225. PHP_MINFO_FUNCTION

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Timm Friebe <thekid@thekid.de>                              |
  16    |          George Schlossnagle <george@omniti.com>                     |
  17    |          Andrei Zmievski <andrei@gravitonic.com>                     |
  18    |          Marcus Boerger <helly@php.net>                              |
  19    |          Johannes Schlueter <johannes@php.net>                       |
  20    +----------------------------------------------------------------------+
  21 */
  22 
  23 /* $Id: 50d0ba002342d41efa753927261e5e09f295ecf9 $ */
  24 
  25 #ifdef HAVE_CONFIG_H
  26 #include "config.h"
  27 #endif
  28 
  29 #include "php.h"
  30 #include "php_ini.h"
  31 #include "php_reflection.h"
  32 #include "ext/standard/info.h"
  33 
  34 #include "zend.h"
  35 #include "zend_API.h"
  36 #include "zend_exceptions.h"
  37 #include "zend_operators.h"
  38 #include "zend_constants.h"
  39 #include "zend_ini.h"
  40 #include "zend_interfaces.h"
  41 #include "zend_closures.h"
  42 #include "zend_generators.h"
  43 #include "zend_extensions.h"
  44 #include "zend_builtin_functions.h"
  45 
  46 #define reflection_update_property(object, name, value) do { \
  47                 zval member; \
  48                 ZVAL_STRINGL(&member, name, sizeof(name)-1); \
  49                 zend_std_write_property(object, &member, value, NULL); \
  50                 if (Z_REFCOUNTED_P(value)) Z_DELREF_P(value); \
  51                 zval_ptr_dtor(&member); \
  52         } while (0)
  53 
  54 /* Class entry pointers */
  55 PHPAPI zend_class_entry *reflector_ptr;
  56 PHPAPI zend_class_entry *reflection_exception_ptr;
  57 PHPAPI zend_class_entry *reflection_ptr;
  58 PHPAPI zend_class_entry *reflection_function_abstract_ptr;
  59 PHPAPI zend_class_entry *reflection_function_ptr;
  60 PHPAPI zend_class_entry *reflection_generator_ptr;
  61 PHPAPI zend_class_entry *reflection_parameter_ptr;
  62 PHPAPI zend_class_entry *reflection_type_ptr;
  63 PHPAPI zend_class_entry *reflection_class_ptr;
  64 PHPAPI zend_class_entry *reflection_object_ptr;
  65 PHPAPI zend_class_entry *reflection_method_ptr;
  66 PHPAPI zend_class_entry *reflection_property_ptr;
  67 PHPAPI zend_class_entry *reflection_extension_ptr;
  68 PHPAPI zend_class_entry *reflection_zend_extension_ptr;
  69 
  70 #if MBO_0
  71 ZEND_BEGIN_MODULE_GLOBALS(reflection)
  72         int dummy;
  73 ZEND_END_MODULE_GLOBALS(reflection)
  74 
  75 #ifdef ZTS
  76 # define REFLECTION_G(v) \
  77         ZEND_TSRMG(reflection_globals_id, zend_reflection_globals*, v)
  78 extern int reflection_globals_id;
  79 #else
  80 # define REFLECTION_G(v) (reflection_globals.v)
  81 extern zend_reflection_globals reflectionglobals;
  82 #endif
  83 
  84 ZEND_DECLARE_MODULE_GLOBALS(reflection)
  85 #endif /* MBO_0 */
  86 
  87 /* Method macros */
  88 
  89 #define METHOD_NOTSTATIC(ce)                                                                                \
  90         if (!Z_OBJ(EX(This)) || !instanceof_function(Z_OBJCE(EX(This)), ce)) {           \
  91                 php_error_docref(NULL, E_ERROR, "%s() cannot be called statically", get_active_function_name());        \
  92                 return;                                                                                             \
  93         }                                                                                                       \
  94 
  95 /* Exception throwing macro */
  96 #define _DO_THROW(msg)                                                                                      \
  97         zend_throw_exception(reflection_exception_ptr, msg, 0);                                       \
  98         return;                                                                                                 \
  99 
 100 #define RETURN_ON_EXCEPTION                                                                                 \
 101         if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {                            \
 102                 return;                                                                                             \
 103         }
 104 
 105 #define GET_REFLECTION_OBJECT()                                                                                         \
 106         intern = Z_REFLECTION_P(getThis());                                                                                     \
 107         if (intern->ptr == NULL) {                                                                              \
 108                 RETURN_ON_EXCEPTION                                                                                 \
 109                 php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the reflection object");                    \
 110         }                                                                                                       \
 111 
 112 #define GET_REFLECTION_OBJECT_PTR(target)                                                                   \
 113         GET_REFLECTION_OBJECT()                                                                                                                                                                 \
 114         target = intern->ptr;                                                                                   \
 115 
 116 /* Class constants */
 117 #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value)                                        \
 118         zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (zend_long)value);
 119 
 120 /* {{{ Smart string functions */
 121 typedef struct _string {
 122         zend_string *buf;
 123         size_t alloced;
 124 } string;
 125 
 126 static void string_init(string *str)
 127 {
 128         str->buf= zend_string_alloc(1024, 0);
 129         str->alloced = 1024;
 130         ZSTR_VAL(str->buf)[0] = '\0';
 131         ZSTR_LEN(str->buf) = 0;
 132 }
 133 
 134 static string *string_printf(string *str, const char *format, ...)
 135 {
 136         size_t len;
 137         va_list arg;
 138         char *s_tmp;
 139 
 140         va_start(arg, format);
 141         len = zend_vspprintf(&s_tmp, 0, format, arg);
 142         if (len) {
 143                 register size_t nlen = (ZSTR_LEN(str->buf) + 1 + len + (1024 - 1)) & ~(1024 - 1);
 144                 if (str->alloced < nlen) {
 145                         size_t old_len = ZSTR_LEN(str->buf);
 146                         str->alloced = nlen;
 147                         str->buf = zend_string_extend(str->buf, str->alloced, 0);
 148                         ZSTR_LEN(str->buf) = old_len;
 149                 }
 150                 memcpy(ZSTR_VAL(str->buf) + ZSTR_LEN(str->buf), s_tmp, len + 1);
 151                 ZSTR_LEN(str->buf) += len;
 152         }
 153         efree(s_tmp);
 154         va_end(arg);
 155         return str;
 156 }
 157 
 158 static string *string_write(string *str, char *buf, size_t len)
 159 {
 160         register size_t nlen = (ZSTR_LEN(str->buf) + 1 + len + (1024 - 1)) & ~(1024 - 1);
 161         if (str->alloced < nlen) {
 162                 size_t old_len = ZSTR_LEN(str->buf);
 163                 str->alloced = nlen;
 164                 str->buf = zend_string_extend(str->buf, str->alloced, 0);
 165                 ZSTR_LEN(str->buf) = old_len;
 166         }
 167         memcpy(ZSTR_VAL(str->buf) + ZSTR_LEN(str->buf), buf, len);
 168         ZSTR_LEN(str->buf) += len;
 169         ZSTR_VAL(str->buf)[ZSTR_LEN(str->buf)] = '\0';
 170         return str;
 171 }
 172 
 173 static string *string_append(string *str, string *append)
 174 {
 175         if (ZSTR_LEN(append->buf) > 0) {
 176                 string_write(str, ZSTR_VAL(append->buf), ZSTR_LEN(append->buf));
 177         }
 178         return str;
 179 }
 180 
 181 static void string_free(string *str)
 182 {
 183         zend_string_release(str->buf);
 184         str->alloced = 0;
 185         str->buf = NULL;
 186 }
 187 /* }}} */
 188 
 189 /* {{{ Object structure */
 190 
 191 /* Struct for properties */
 192 typedef struct _property_reference {
 193         zend_class_entry *ce;
 194         zend_property_info prop;
 195 } property_reference;
 196 
 197 /* Struct for parameters */
 198 typedef struct _parameter_reference {
 199         uint32_t offset;
 200         uint32_t required;
 201         struct _zend_arg_info *arg_info;
 202         zend_function *fptr;
 203 } parameter_reference;
 204 
 205 /* Struct for type hints */
 206 typedef struct _type_reference {
 207         struct _zend_arg_info *arg_info;
 208         zend_function *fptr;
 209 } type_reference;
 210 
 211 typedef enum {
 212         REF_TYPE_OTHER,      /* Must be 0 */
 213         REF_TYPE_FUNCTION,
 214         REF_TYPE_GENERATOR,
 215         REF_TYPE_PARAMETER,
 216         REF_TYPE_TYPE,
 217         REF_TYPE_PROPERTY,
 218         REF_TYPE_DYNAMIC_PROPERTY
 219 } reflection_type_t;
 220 
 221 /* Struct for reflection objects */
 222 typedef struct {
 223         zval dummy; /* holder for the second property */
 224         zval obj;
 225         void *ptr;
 226         zend_class_entry *ce;
 227         reflection_type_t ref_type;
 228         unsigned int ignore_visibility:1;
 229         zend_object zo;
 230 } reflection_object;
 231 
 232 static inline reflection_object *reflection_object_from_obj(zend_object *obj) {
 233         return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo));
 234 }
 235 
 236 #define Z_REFLECTION_P(zv)  reflection_object_from_obj(Z_OBJ_P((zv)))
 237 /* }}} */
 238 
 239 static zend_object_handlers reflection_object_handlers;
 240 
 241 static zval *_default_load_entry(zval *object, char *name, size_t name_len) /* {{{ */
 242 {
 243         zval *value;
 244 
 245         if ((value = zend_hash_str_find_ind(Z_OBJPROP_P(object), name, name_len)) == NULL) {
 246                 return NULL;
 247         }
 248         return value;
 249 }
 250 /* }}} */
 251 
 252 static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value) /* {{{ */
 253 {
 254         zval *value;
 255 
 256         if ((value = _default_load_entry(object, name, name_len)) == NULL) {
 257                 RETURN_FALSE;
 258         }
 259         ZVAL_DUP(return_value, value);
 260 }
 261 /* }}} */
 262 
 263 #ifdef ilia_0
 264 static void _default_lookup_entry(zval *object, char *name, int name_len, zval **return_value) /* {{{ */
 265 {
 266         zval **value;
 267 
 268         if (zend_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
 269                 *return_value = NULL;
 270         } else {
 271                 *return_value = *value;
 272         }
 273 }
 274 /* }}} */
 275 #endif
 276 
 277 static zend_function *_copy_function(zend_function *fptr) /* {{{ */
 278 {
 279         if (fptr
 280                 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
 281         {
 282                 zend_function *copy_fptr;
 283                 copy_fptr = emalloc(sizeof(zend_function));
 284                 memcpy(copy_fptr, fptr, sizeof(zend_function));
 285                 copy_fptr->internal_function.function_name = zend_string_copy(fptr->internal_function.function_name);
 286                 return copy_fptr;
 287         } else {
 288                 /* no copy needed */
 289                 return fptr;
 290         }
 291 }
 292 /* }}} */
 293 
 294 static void _free_function(zend_function *fptr) /* {{{ */
 295 {
 296         if (fptr
 297                 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
 298         {
 299                 zend_string_release(fptr->internal_function.function_name);
 300                 zend_free_trampoline(fptr);
 301         }
 302 }
 303 /* }}} */
 304 
 305 static void reflection_free_objects_storage(zend_object *object) /* {{{ */
 306 {
 307         reflection_object *intern = reflection_object_from_obj(object);
 308         parameter_reference *reference;
 309         property_reference *prop_reference;
 310         type_reference *typ_reference;
 311 
 312         if (intern->ptr) {
 313                 switch (intern->ref_type) {
 314                 case REF_TYPE_PARAMETER:
 315                         reference = (parameter_reference*)intern->ptr;
 316                         _free_function(reference->fptr);
 317                         efree(intern->ptr);
 318                         break;
 319                 case REF_TYPE_TYPE:
 320                         typ_reference = (type_reference*)intern->ptr;
 321                         _free_function(typ_reference->fptr);
 322                         efree(intern->ptr);
 323                         break;
 324                 case REF_TYPE_FUNCTION:
 325                         _free_function(intern->ptr);
 326                         break;
 327                 case REF_TYPE_PROPERTY:
 328                         efree(intern->ptr);
 329                         break;
 330                 case REF_TYPE_DYNAMIC_PROPERTY:
 331                         prop_reference = (property_reference*)intern->ptr;
 332                         zend_string_release(prop_reference->prop.name);
 333                         efree(intern->ptr);
 334                         break;
 335                 case REF_TYPE_GENERATOR:
 336                         break;
 337                 case REF_TYPE_OTHER:
 338                         break;
 339                 }
 340         }
 341         intern->ptr = NULL;
 342         zval_ptr_dtor(&intern->obj);
 343         zend_object_std_dtor(object);
 344 }
 345 /* }}} */
 346 
 347 static zend_object *reflection_objects_new(zend_class_entry *class_type) /* {{{ */
 348 {
 349         reflection_object *intern;
 350 
 351         intern = ecalloc(1, sizeof(reflection_object) + zend_object_properties_size(class_type));
 352         intern->zo.ce = class_type;
 353 
 354         zend_object_std_init(&intern->zo, class_type);
 355         object_properties_init(&intern->zo, class_type);
 356         intern->zo.handlers = &reflection_object_handlers;
 357         return &intern->zo;
 358 }
 359 /* }}} */
 360 
 361 static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{ */
 362 {
 363         object_init_ex(object, pce);
 364         return object;
 365 }
 366 /* }}} */
 367 
 368 static void _const_string(string *str, char *name, zval *value, char *indent);
 369 static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent);
 370 static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent);
 371 static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent);
 372 static void _extension_string(string *str, zend_module_entry *module, char *indent);
 373 static void _zend_extension_string(string *str, zend_extension *extension, char *indent);
 374 
 375 /* {{{ _class_string */
 376 static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent)
 377 {
 378         int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
 379         string sub_indent;
 380 
 381         string_init(&sub_indent);
 382         string_printf(&sub_indent, "%s    ", indent);
 383 
 384         /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
 385         if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
 386                 string_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment));
 387                 string_write(str, "\n", 1);
 388         }
 389 
 390         if (obj && Z_TYPE_P(obj) == IS_OBJECT) {
 391                 string_printf(str, "%sObject of class [ ", indent);
 392         } else {
 393                 char *kind = "Class";
 394                 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
 395                         kind = "Interface";
 396                 } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
 397                         kind = "Trait";
 398                 }
 399                 string_printf(str, "%s%s [ ", indent, kind);
 400         }
 401         string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
 402         if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module) {
 403                 string_printf(str, ":%s", ce->info.internal.module->name);
 404         }
 405         string_printf(str, "> ");
 406         if (ce->get_iterator != NULL) {
 407                 string_printf(str, "<iterateable> ");
 408         }
 409         if (ce->ce_flags & ZEND_ACC_INTERFACE) {
 410                 string_printf(str, "interface ");
 411         } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
 412                 string_printf(str, "trait ");
 413         } else {
 414                 if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
 415                         string_printf(str, "abstract ");
 416                 }
 417                 if (ce->ce_flags & ZEND_ACC_FINAL) {
 418                         string_printf(str, "final ");
 419                 }
 420                 string_printf(str, "class ");
 421         }
 422         string_printf(str, "%s", ZSTR_VAL(ce->name));
 423         if (ce->parent) {
 424                 string_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
 425         }
 426 
 427         if (ce->num_interfaces) {
 428                 uint32_t i;
 429 
 430                 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
 431                         string_printf(str, " extends %s", ZSTR_VAL(ce->interfaces[0]->name));
 432                 } else {
 433                         string_printf(str, " implements %s", ZSTR_VAL(ce->interfaces[0]->name));
 434                 }
 435                 for (i = 1; i < ce->num_interfaces; ++i) {
 436                         string_printf(str, ", %s", ZSTR_VAL(ce->interfaces[i]->name));
 437                 }
 438         }
 439         string_printf(str, " ] {\n");
 440 
 441         /* The information where a class is declared is only available for user classes */
 442         if (ce->type == ZEND_USER_CLASS) {
 443                 string_printf(str, "%s  @@ %s %d-%d\n", indent, ZSTR_VAL(ce->info.user.filename),
 444                                                 ce->info.user.line_start, ce->info.user.line_end);
 445         }
 446 
 447         /* Constants */
 448         string_printf(str, "\n");
 449         count = zend_hash_num_elements(&ce->constants_table);
 450         string_printf(str, "%s  - Constants [%d] {\n", indent, count);
 451         if (count > 0) {
 452                 zend_string *key;
 453                 zval *value;
 454 
 455                 ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, value) {
 456                         zval_update_constant_ex(value, 1, NULL);
 457                         _const_string(str, ZSTR_VAL(key), value, indent);
 458                 } ZEND_HASH_FOREACH_END();
 459         }
 460         string_printf(str, "%s  }\n", indent);
 461 
 462         /* Static properties */
 463         /* counting static properties */
 464         count = zend_hash_num_elements(&ce->properties_info);
 465         if (count > 0) {
 466                 zend_property_info *prop;
 467 
 468                 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
 469                         if(prop->flags & ZEND_ACC_SHADOW) {
 470                                 count_shadow_props++;
 471                         } else if (prop->flags & ZEND_ACC_STATIC) {
 472                                 count_static_props++;
 473                         }
 474                 } ZEND_HASH_FOREACH_END();
 475         }
 476 
 477         /* static properties */
 478         string_printf(str, "\n%s  - Static properties [%d] {\n", indent, count_static_props);
 479         if (count_static_props > 0) {
 480                 zend_property_info *prop;
 481 
 482                 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
 483                         if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
 484                                 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent.buf));
 485                         }
 486                 } ZEND_HASH_FOREACH_END();
 487         }
 488         string_printf(str, "%s  }\n", indent);
 489 
 490         /* Static methods */
 491         /* counting static methods */
 492         count = zend_hash_num_elements(&ce->function_table);
 493         if (count > 0) {
 494                 zend_function *mptr;
 495 
 496                 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
 497                         if (mptr->common.fn_flags & ZEND_ACC_STATIC
 498                                 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
 499                         {
 500                                 count_static_funcs++;
 501                         }
 502                 } ZEND_HASH_FOREACH_END();
 503         }
 504 
 505         /* static methods */
 506         string_printf(str, "\n%s  - Static methods [%d] {", indent, count_static_funcs);
 507         if (count_static_funcs > 0) {
 508                 zend_function *mptr;
 509 
 510                 ZEND_HASH_FOREACH_PTR(&ce->function_table, mptr) {
 511                         if (mptr->common.fn_flags & ZEND_ACC_STATIC
 512                                 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
 513                         {
 514                                 string_printf(str, "\n");
 515                                 _function_string(str, mptr, ce, ZSTR_VAL(sub_indent.buf));
 516                         }
 517                 } ZEND_HASH_FOREACH_END();
 518         } else {
 519                 string_printf(str, "\n");
 520         }
 521         string_printf(str, "%s  }\n", indent);
 522 
 523         /* Default/Implicit properties */
 524         count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
 525         string_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
 526         if (count > 0) {
 527                 zend_property_info *prop;
 528 
 529                 ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop) {
 530                         if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
 531                                 _property_string(str, prop, NULL, ZSTR_VAL(sub_indent.buf));
 532                         }
 533                 } ZEND_HASH_FOREACH_END();
 534         }
 535         string_printf(str, "%s  }\n", indent);
 536 
 537         if (obj && Z_TYPE_P(obj) == IS_OBJECT && Z_OBJ_HT_P(obj)->get_properties) {
 538                 string       dyn;
 539                 HashTable    *properties = Z_OBJ_HT_P(obj)->get_properties(obj);
 540                 zend_string  *prop_name;
 541 
 542                 string_init(&dyn);
 543                 count = 0;
 544 
 545                 if (properties && zend_hash_num_elements(properties)) {
 546                         ZEND_HASH_FOREACH_STR_KEY(properties, prop_name) {
 547                                 if (prop_name && ZSTR_LEN(prop_name) && ZSTR_VAL(prop_name)[0]) { /* skip all private and protected properties */
 548                                         if (!zend_hash_exists(&ce->properties_info, prop_name)) {
 549                                                 count++;
 550                                                 _property_string(&dyn, NULL, ZSTR_VAL(prop_name), ZSTR_VAL(sub_indent.buf));
 551                                         }
 552                                 }
 553                         } ZEND_HASH_FOREACH_END();
 554                 }
 555 
 556                 string_printf(str, "\n%s  - Dynamic properties [%d] {\n", indent, count);
 557                 string_append(str, &dyn);
 558                 string_printf(str, "%s  }\n", indent);
 559                 string_free(&dyn);
 560         }
 561 
 562         /* Non static methods */
 563         count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
 564         if (count > 0) {
 565                 zend_function *mptr;
 566                 zend_string *key;
 567                 string dyn;
 568 
 569                 count = 0;
 570                 string_init(&dyn);
 571 
 572                 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, key, mptr) {
 573                         if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
 574                                 && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
 575                         {
 576                                 size_t len = ZSTR_LEN(mptr->common.function_name);
 577 
 578                                 /* Do not display old-style inherited constructors */
 579                                 if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0
 580                                         || mptr->common.scope == ce
 581                                         || !key
 582                                         || zend_binary_strcasecmp(ZSTR_VAL(key), ZSTR_LEN(key), ZSTR_VAL(mptr->common.function_name), len) == 0)
 583                                 {
 584                                         zend_function *closure;
 585                                         /* see if this is a closure */
 586                                         if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
 587                                                 && memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
 588                                                 && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
 589                                         {
 590                                                 mptr = closure;
 591                                         } else {
 592                                                 closure = NULL;
 593                                         }
 594                                         string_printf(&dyn, "\n");
 595                                         _function_string(&dyn, mptr, ce, ZSTR_VAL(sub_indent.buf));
 596                                         count++;
 597                                         _free_function(closure);
 598                                 }
 599                         }
 600                 } ZEND_HASH_FOREACH_END();
 601                 string_printf(str, "\n%s  - Methods [%d] {", indent, count);
 602                 if (!count) {
 603                         string_printf(str, "\n");
 604                 }
 605                 string_append(str, &dyn);
 606                 string_free(&dyn);
 607         } else {
 608                 string_printf(str, "\n%s  - Methods [0] {\n", indent);
 609         }
 610         string_printf(str, "%s  }\n", indent);
 611 
 612         string_printf(str, "%s}\n", indent);
 613         string_free(&sub_indent);
 614 }
 615 /* }}} */
 616 
 617 /* {{{ _const_string */
 618 static void _const_string(string *str, char *name, zval *value, char *indent)
 619 {
 620         char *type = zend_zval_type_name(value);
 621         zend_string *value_str = zval_get_string(value);
 622 
 623         string_printf(str, "%s    Constant [ %s %s ] { %s }\n",
 624                                         indent, type, name, ZSTR_VAL(value_str));
 625 
 626         zend_string_release(value_str);
 627 }
 628 /* }}} */
 629 
 630 /* {{{ _get_recv_opcode */
 631 static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
 632 {
 633         zend_op *op = op_array->opcodes;
 634         zend_op *end = op + op_array->last;
 635 
 636         ++offset;
 637         while (op < end) {
 638                 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT
 639                     || op->opcode == ZEND_RECV_VARIADIC) && op->op1.num == (zend_long)offset)
 640                 {
 641                         return op;
 642                 }
 643                 ++op;
 644         }
 645         return NULL;
 646 }
 647 /* }}} */
 648 
 649 /* {{{ _parameter_string */
 650 static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, uint32_t required, char* indent)
 651 {
 652         string_printf(str, "Parameter #%d [ ", offset);
 653         if (offset >= required) {
 654                 string_printf(str, "<optional> ");
 655         } else {
 656                 string_printf(str, "<required> ");
 657         }
 658         if (arg_info->class_name) {
 659                 string_printf(str, "%s ",
 660                         (fptr->type == ZEND_INTERNAL_FUNCTION &&
 661                          !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
 662                         ((zend_internal_arg_info*)arg_info)->class_name :
 663                         ZSTR_VAL(arg_info->class_name));
 664                 if (arg_info->allow_null) {
 665                         string_printf(str, "or NULL ");
 666                 }
 667         } else if (arg_info->type_hint) {
 668                 string_printf(str, "%s ", zend_get_type_by_const(arg_info->type_hint));
 669                 if (arg_info->allow_null) {
 670                         string_printf(str, "or NULL ");
 671                 }
 672         }
 673         if (arg_info->pass_by_reference) {
 674                 string_write(str, "&", sizeof("&")-1);
 675         }
 676         if (arg_info->is_variadic) {
 677                 string_write(str, "...", sizeof("...")-1);
 678         }
 679         if (arg_info->name) {
 680                 string_printf(str, "$%s",
 681                         (fptr->type == ZEND_INTERNAL_FUNCTION &&
 682                          !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
 683                         ((zend_internal_arg_info*)arg_info)->name :
 684                         ZSTR_VAL(arg_info->name));
 685         } else {
 686                 string_printf(str, "$param%d", offset);
 687         }
 688         if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
 689                 zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
 690                 if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
 691                         zval zv;
 692                         zend_class_entry *old_scope;
 693 
 694                         string_write(str, " = ", sizeof(" = ")-1);
 695                         ZVAL_DUP(&zv, RT_CONSTANT(&fptr->op_array, precv->op2));
 696                         old_scope = EG(scope);
 697                         EG(scope) = fptr->common.scope;
 698                         zval_update_constant_ex(&zv, 1, NULL);
 699                         EG(scope) = old_scope;
 700                         if (Z_TYPE(zv) == IS_TRUE) {
 701                                 string_write(str, "true", sizeof("true")-1);
 702                         } else if (Z_TYPE(zv) == IS_FALSE) {
 703                                 string_write(str, "false", sizeof("false")-1);
 704                         } else if (Z_TYPE(zv) == IS_NULL) {
 705                                 string_write(str, "NULL", sizeof("NULL")-1);
 706                         } else if (Z_TYPE(zv) == IS_STRING) {
 707                                 string_write(str, "'", sizeof("'")-1);
 708                                 string_write(str, Z_STRVAL(zv), MIN(Z_STRLEN(zv), 15));
 709                                 if (Z_STRLEN(zv) > 15) {
 710                                         string_write(str, "...", sizeof("...")-1);
 711                                 }
 712                                 string_write(str, "'", sizeof("'")-1);
 713                         } else if (Z_TYPE(zv) == IS_ARRAY) {
 714                                 string_write(str, "Array", sizeof("Array")-1);
 715                         } else {
 716                                 zend_string *zv_str = zval_get_string(&zv);
 717                                 string_write(str, ZSTR_VAL(zv_str), ZSTR_LEN(zv_str));
 718                                 zend_string_release(zv_str);
 719                         }
 720                         zval_ptr_dtor(&zv);
 721                 }
 722         }
 723         string_write(str, " ]", sizeof(" ]")-1);
 724 }
 725 /* }}} */
 726 
 727 /* {{{ _function_parameter_string */
 728 static void _function_parameter_string(string *str, zend_function *fptr, char* indent)
 729 {
 730         struct _zend_arg_info *arg_info = fptr->common.arg_info;
 731         uint32_t i, num_args, required = fptr->common.required_num_args;
 732 
 733         if (!arg_info) {
 734                 return;
 735         }
 736 
 737         num_args = fptr->common.num_args;
 738         if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
 739                 num_args++;
 740         }
 741         string_printf(str, "\n");
 742         string_printf(str, "%s- Parameters [%d] {\n", indent, num_args);
 743         for (i = 0; i < num_args; i++) {
 744                 string_printf(str, "%s  ", indent);
 745                 _parameter_string(str, fptr, arg_info, i, required, indent);
 746                 string_write(str, "\n", sizeof("\n")-1);
 747                 arg_info++;
 748         }
 749         string_printf(str, "%s}\n", indent);
 750 }
 751 /* }}} */
 752 
 753 /* {{{ _function_closure_string */
 754 static void _function_closure_string(string *str, zend_function *fptr, char* indent)
 755 {
 756         uint32_t i, count;
 757         zend_string *key;
 758         HashTable *static_variables;
 759 
 760         if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
 761                 return;
 762         }
 763 
 764         static_variables = fptr->op_array.static_variables;
 765         count = zend_hash_num_elements(static_variables);
 766 
 767         if (!count) {
 768                 return;
 769         }
 770 
 771         string_printf(str, "\n");
 772         string_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
 773         i = 0;
 774         ZEND_HASH_FOREACH_STR_KEY(static_variables, key) {
 775                 string_printf(str, "%s    Variable #%d [ $%s ]\n", indent, i++, ZSTR_VAL(key));
 776         } ZEND_HASH_FOREACH_END();
 777         string_printf(str, "%s}\n", indent);
 778 }
 779 /* }}} */
 780 
 781 /* {{{ _function_string */
 782 static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent)
 783 {
 784         string param_indent;
 785         zend_function *overwrites;
 786         zend_string *lc_name;
 787         size_t lc_name_len;
 788 
 789         /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
 790          * What's "wrong" is that any whitespace before the doc comment start is
 791          * swallowed, leading to an unaligned comment.
 792          */
 793         if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
 794                 string_printf(str, "%s%s\n", indent, ZSTR_VAL(fptr->op_array.doc_comment));
 795         }
 796 
 797         string_write(str, indent, strlen(indent));
 798         string_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
 799         string_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
 800         if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
 801                 string_printf(str, ", deprecated");
 802         }
 803         if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
 804                 string_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
 805         }
 806 
 807         if (scope && fptr->common.scope) {
 808                 if (fptr->common.scope != scope) {
 809                         string_printf(str, ", inherits %s", ZSTR_VAL(fptr->common.scope->name));
 810                 } else if (fptr->common.scope->parent) {
 811                         lc_name_len = ZSTR_LEN(fptr->common.function_name);
 812                         lc_name = zend_string_alloc(lc_name_len, 0);
 813                         zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(fptr->common.function_name), lc_name_len);
 814                         if ((overwrites = zend_hash_find_ptr(&fptr->common.scope->parent->function_table, lc_name)) != NULL) {
 815                                 if (fptr->common.scope != overwrites->common.scope) {
 816                                         string_printf(str, ", overwrites %s", ZSTR_VAL(overwrites->common.scope->name));
 817                                 }
 818                         }
 819                         efree(lc_name);
 820                 }
 821         }
 822         if (fptr->common.prototype && fptr->common.prototype->common.scope) {
 823                 string_printf(str, ", prototype %s", ZSTR_VAL(fptr->common.prototype->common.scope->name));
 824         }
 825         if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
 826                 string_printf(str, ", ctor");
 827         }
 828         if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
 829                 string_printf(str, ", dtor");
 830         }
 831         string_printf(str, "> ");
 832 
 833         if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
 834                 string_printf(str, "abstract ");
 835         }
 836         if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
 837                 string_printf(str, "final ");
 838         }
 839         if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
 840                 string_printf(str, "static ");
 841         }
 842 
 843         if (fptr->common.scope) {
 844                 /* These are mutually exclusive */
 845                 switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
 846                         case ZEND_ACC_PUBLIC:
 847                                 string_printf(str, "public ");
 848                                 break;
 849                         case ZEND_ACC_PRIVATE:
 850                                 string_printf(str, "private ");
 851                                 break;
 852                         case ZEND_ACC_PROTECTED:
 853                                 string_printf(str, "protected ");
 854                                 break;
 855                         default:
 856                                 string_printf(str, "<visibility error> ");
 857                                 break;
 858                 }
 859                 string_printf(str, "method ");
 860         } else {
 861                 string_printf(str, "function ");
 862         }
 863 
 864         if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
 865                 string_printf(str, "&");
 866         }
 867         string_printf(str, "%s ] {\n", ZSTR_VAL(fptr->common.function_name));
 868         /* The information where a function is declared is only available for user classes */
 869         if (fptr->type == ZEND_USER_FUNCTION) {
 870                 string_printf(str, "%s  @@ %s %d - %d\n", indent,
 871                                                 ZSTR_VAL(fptr->op_array.filename),
 872                                                 fptr->op_array.line_start,
 873                                                 fptr->op_array.line_end);
 874         }
 875         string_init(&param_indent);
 876         string_printf(&param_indent, "%s  ", indent);
 877         if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
 878                 _function_closure_string(str, fptr, ZSTR_VAL(param_indent.buf));
 879         }
 880         _function_parameter_string(str, fptr, ZSTR_VAL(param_indent.buf));
 881         string_free(&param_indent);
 882         if (fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
 883                 string_printf(str, "  %s- Return [ ", indent);
 884                 if (fptr->common.arg_info[-1].class_name) {
 885                         string_printf(str, "%s ",
 886                                 (fptr->type == ZEND_INTERNAL_FUNCTION &&
 887                                  !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
 888                                         ((zend_internal_arg_info*)(fptr->common.arg_info - 1))->class_name :
 889                                         ZSTR_VAL(fptr->common.arg_info[-1].class_name));
 890                         if (fptr->common.arg_info[-1].allow_null) {
 891                                 string_printf(str, "or NULL ");
 892                         }
 893                 } else if (fptr->common.arg_info[-1].type_hint) {
 894                         string_printf(str, "%s ", zend_get_type_by_const(fptr->common.arg_info[-1].type_hint));
 895                         if (fptr->common.arg_info[-1].allow_null) {
 896                                 string_printf(str, "or NULL ");
 897                         }
 898                 }
 899                 string_printf(str, "]\n");
 900         }
 901         string_printf(str, "%s}\n", indent);
 902 }
 903 /* }}} */
 904 
 905 /* {{{ _property_string */
 906 static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent)
 907 {
 908         const char *class_name;
 909 
 910         string_printf(str, "%sProperty [ ", indent);
 911         if (!prop) {
 912                 string_printf(str, "<dynamic> public $%s", prop_name);
 913         } else {
 914                 if (!(prop->flags & ZEND_ACC_STATIC)) {
 915                         if (prop->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
 916                                 string_write(str, "<implicit> ", sizeof("<implicit> ") - 1);
 917                         } else {
 918                                 string_write(str, "<default> ", sizeof("<default> ") - 1);
 919                         }
 920                 }
 921 
 922                 /* These are mutually exclusive */
 923                 switch (prop->flags & ZEND_ACC_PPP_MASK) {
 924                         case ZEND_ACC_PUBLIC:
 925                                 string_printf(str, "public ");
 926                                 break;
 927                         case ZEND_ACC_PRIVATE:
 928                                 string_printf(str, "private ");
 929                                 break;
 930                         case ZEND_ACC_PROTECTED:
 931                                 string_printf(str, "protected ");
 932                                 break;
 933                 }
 934                 if(prop->flags & ZEND_ACC_STATIC) {
 935                         string_printf(str, "static ");
 936                 }
 937 
 938                 zend_unmangle_property_name(prop->name, &class_name, (const char**)&prop_name);
 939                 string_printf(str, "$%s", prop_name);
 940         }
 941 
 942         string_printf(str, " ]\n");
 943 }
 944 /* }}} */
 945 
 946 static int _extension_ini_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 947 {
 948         zend_ini_entry *ini_entry = (zend_ini_entry*)Z_PTR_P(el);
 949         string *str = va_arg(args, string *);
 950         char *indent = va_arg(args, char *);
 951         int number = va_arg(args, int);
 952         char *comma = "";
 953 
 954         if (number == ini_entry->module_number) {
 955                 string_printf(str, "    %sEntry [ %s <", indent, ZSTR_VAL(ini_entry->name));
 956                 if (ini_entry->modifiable == ZEND_INI_ALL) {
 957                         string_printf(str, "ALL");
 958                 } else {
 959                         if (ini_entry->modifiable & ZEND_INI_USER) {
 960                                 string_printf(str, "USER");
 961                                 comma = ",";
 962                         }
 963                         if (ini_entry->modifiable & ZEND_INI_PERDIR) {
 964                                 string_printf(str, "%sPERDIR", comma);
 965                                 comma = ",";
 966                         }
 967                         if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
 968                                 string_printf(str, "%sSYSTEM", comma);
 969                         }
 970                 }
 971 
 972                 string_printf(str, "> ]\n");
 973                 string_printf(str, "    %s  Current = '%s'\n", indent, ini_entry->value ? ZSTR_VAL(ini_entry->value) : "");
 974                 if (ini_entry->modified) {
 975                         string_printf(str, "    %s  Default = '%s'\n", indent, ini_entry->orig_value ? ZSTR_VAL(ini_entry->orig_value) : "");
 976                 }
 977                 string_printf(str, "    %s}\n", indent);
 978         }
 979         return ZEND_HASH_APPLY_KEEP;
 980 }
 981 /* }}} */
 982 
 983 static int _extension_class_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
 984 {
 985         zend_class_entry *ce = (zend_class_entry*)Z_PTR_P(el);
 986         string *str = va_arg(args, string *);
 987         char *indent = va_arg(args, char *);
 988         struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
 989         int *num_classes = va_arg(args, int*);
 990 
 991         if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
 992                 /* dump class if it is not an alias */
 993                 if (!zend_binary_strcasecmp(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key))) {
 994                         string_printf(str, "\n");
 995                         _class_string(str, ce, NULL, indent);
 996                         (*num_classes)++;
 997                 }
 998         }
 999         return ZEND_HASH_APPLY_KEEP;
1000 }
1001 /* }}} */
1002 
1003 static int _extension_const_string(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
1004 {
1005         zend_constant *constant = (zend_constant*)Z_PTR_P(el);
1006         string *str = va_arg(args, string *);
1007         char *indent = va_arg(args, char *);
1008         struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
1009         int *num_classes = va_arg(args, int*);
1010 
1011         if (constant->module_number  == module->module_number) {
1012                 _const_string(str, ZSTR_VAL(constant->name), &constant->value, indent);
1013                 (*num_classes)++;
1014         }
1015         return ZEND_HASH_APPLY_KEEP;
1016 }
1017 /* }}} */
1018 
1019 static void _extension_string(string *str, zend_module_entry *module, char *indent) /* {{{ */
1020 {
1021         string_printf(str, "%sExtension [ ", indent);
1022         if (module->type == MODULE_PERSISTENT) {
1023                 string_printf(str, "<persistent>");
1024         }
1025         if (module->type == MODULE_TEMPORARY) {
1026                 string_printf(str, "<temporary>" );
1027         }
1028         string_printf(str, " extension #%d %s version %s ] {\n",
1029                                         module->module_number, module->name,
1030                                         (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
1031 
1032         if (module->deps) {
1033                 const zend_module_dep* dep = module->deps;
1034 
1035                 string_printf(str, "\n  - Dependencies {\n");
1036 
1037                 while(dep->name) {
1038                         string_printf(str, "%s    Dependency [ %s (", indent, dep->name);
1039 
1040                         switch(dep->type) {
1041                         case MODULE_DEP_REQUIRED:
1042                                 string_write(str, "Required", sizeof("Required") - 1);
1043                                 break;
1044                         case MODULE_DEP_CONFLICTS:
1045                                 string_write(str, "Conflicts", sizeof("Conflicts") - 1);
1046                                 break;
1047                         case MODULE_DEP_OPTIONAL:
1048                                 string_write(str, "Optional", sizeof("Optional") - 1);
1049                                 break;
1050                         default:
1051                                 string_write(str, "Error", sizeof("Error") - 1); /* shouldn't happen */
1052                                 break;
1053                         }
1054 
1055                         if (dep->rel) {
1056                                 string_printf(str, " %s", dep->rel);
1057                         }
1058                         if (dep->version) {
1059                                 string_printf(str, " %s", dep->version);
1060                         }
1061                         string_write(str, ") ]\n", sizeof(") ]\n") - 1);
1062                         dep++;
1063                 }
1064                 string_printf(str, "%s  }\n", indent);
1065         }
1066 
1067         {
1068                 string str_ini;
1069                 string_init(&str_ini);
1070                 zend_hash_apply_with_arguments(EG(ini_directives), (apply_func_args_t) _extension_ini_string, 3, &str_ini, indent, module->module_number);
1071                 if (ZSTR_LEN(str_ini.buf) > 0) {
1072                         string_printf(str, "\n  - INI {\n");
1073                         string_append(str, &str_ini);
1074                         string_printf(str, "%s  }\n", indent);
1075                 }
1076                 string_free(&str_ini);
1077         }
1078 
1079         {
1080                 string str_constants;
1081                 int num_constants = 0;
1082 
1083                 string_init(&str_constants);
1084                 zend_hash_apply_with_arguments(EG(zend_constants), (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
1085                 if (num_constants) {
1086                         string_printf(str, "\n  - Constants [%d] {\n", num_constants);
1087                         string_append(str, &str_constants);
1088                         string_printf(str, "%s  }\n", indent);
1089                 }
1090                 string_free(&str_constants);
1091         }
1092 
1093         {
1094                 zend_function *fptr;
1095                 int first = 1;
1096 
1097                 ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
1098                         if (fptr->common.type==ZEND_INTERNAL_FUNCTION
1099                                 && fptr->internal_function.module == module) {
1100                                 if (first) {
1101                                         string_printf(str, "\n  - Functions {\n");
1102                                         first = 0;
1103                                 }
1104                                 _function_string(str, fptr, NULL, "    ");
1105                         }
1106                 } ZEND_HASH_FOREACH_END();
1107                 if (!first) {
1108                         string_printf(str, "%s  }\n", indent);
1109                 }
1110         }
1111 
1112         {
1113                 string str_classes;
1114                 string sub_indent;
1115                 int num_classes = 0;
1116 
1117                 string_init(&sub_indent);
1118                 string_printf(&sub_indent, "%s    ", indent);
1119                 string_init(&str_classes);
1120                 zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) _extension_class_string, 4, &str_classes, ZSTR_VAL(sub_indent.buf), module, &num_classes);
1121                 if (num_classes) {
1122                         string_printf(str, "\n  - Classes [%d] {", num_classes);
1123                         string_append(str, &str_classes);
1124                         string_printf(str, "%s  }\n", indent);
1125                 }
1126                 string_free(&str_classes);
1127                 string_free(&sub_indent);
1128         }
1129 
1130         string_printf(str, "%s}\n", indent);
1131 }
1132 /* }}} */
1133 
1134 static void _zend_extension_string(string *str, zend_extension *extension, char *indent) /* {{{ */
1135 {
1136         string_printf(str, "%sZend Extension [ %s ", indent, extension->name);
1137 
1138         if (extension->version) {
1139                 string_printf(str, "%s ", extension->version);
1140         }
1141         if (extension->copyright) {
1142                 string_printf(str, "%s ", extension->copyright);
1143         }
1144         if (extension->author) {
1145                 string_printf(str, "by %s ", extension->author);
1146         }
1147         if (extension->URL) {
1148                 string_printf(str, "<%s> ", extension->URL);
1149         }
1150 
1151         string_printf(str, "]\n");
1152 }
1153 /* }}} */
1154 
1155 /* {{{ _function_check_flag */
1156 static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
1157 {
1158         reflection_object *intern;
1159         zend_function *mptr;
1160 
1161         if (zend_parse_parameters_none() == FAILURE) {
1162                 return;
1163         }
1164         GET_REFLECTION_OBJECT_PTR(mptr);
1165         RETURN_BOOL(mptr->common.fn_flags & mask);
1166 }
1167 /* }}} */
1168 
1169 /* {{{ zend_reflection_class_factory */
1170 PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
1171 {
1172         reflection_object *intern;
1173         zval name;
1174 
1175         ZVAL_STR_COPY(&name, ce->name);
1176         reflection_instantiate(reflection_class_ptr, object);
1177         intern = Z_REFLECTION_P(object);
1178         intern->ptr = ce;
1179         intern->ref_type = REF_TYPE_OTHER;
1180         intern->ce = ce;
1181         reflection_update_property(object, "name", &name);
1182 }
1183 /* }}} */
1184 
1185 /* {{{ reflection_extension_factory */
1186 static void reflection_extension_factory(zval *object, const char *name_str)
1187 {
1188         reflection_object *intern;
1189         zval name;
1190         size_t name_len = strlen(name_str);
1191         zend_string *lcname;
1192         struct _zend_module_entry *module;
1193 
1194         lcname = zend_string_alloc(name_len, 0);
1195         zend_str_tolower_copy(ZSTR_VAL(lcname), name_str, name_len);
1196         module = zend_hash_find_ptr(&module_registry, lcname);
1197         zend_string_free(lcname);
1198         if (!module) {
1199                 return;
1200         }
1201 
1202         reflection_instantiate(reflection_extension_ptr, object);
1203         intern = Z_REFLECTION_P(object);
1204         ZVAL_STRINGL(&name, module->name, name_len);
1205         intern->ptr = module;
1206         intern->ref_type = REF_TYPE_OTHER;
1207         intern->ce = NULL;
1208         reflection_update_property(object, "name", &name);
1209 }
1210 /* }}} */
1211 
1212 /* {{{ reflection_parameter_factory */
1213 static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, uint32_t required, zval *object)
1214 {
1215         reflection_object *intern;
1216         parameter_reference *reference;
1217         zval name;
1218 
1219         if (arg_info->name) {
1220                 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
1221                     !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
1222                         ZVAL_STRING(&name, ((zend_internal_arg_info*)arg_info)->name);
1223                 } else {
1224                         ZVAL_STR_COPY(&name, arg_info->name);
1225                 }
1226         } else {
1227                 ZVAL_NULL(&name);
1228         }
1229         reflection_instantiate(reflection_parameter_ptr, object);
1230         intern = Z_REFLECTION_P(object);
1231         reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
1232         reference->arg_info = arg_info;
1233         reference->offset = offset;
1234         reference->required = required;
1235         reference->fptr = fptr;
1236         intern->ptr = reference;
1237         intern->ref_type = REF_TYPE_PARAMETER;
1238         intern->ce = fptr->common.scope;
1239         if (closure_object) {
1240                 Z_ADDREF_P(closure_object);
1241                 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1242         }
1243         reflection_update_property(object, "name", &name);
1244 }
1245 /* }}} */
1246 
1247 /* {{{ reflection_type_factory */
1248 static void reflection_type_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, zval *object)
1249 {
1250         reflection_object *intern;
1251         type_reference *reference;
1252 
1253         reflection_instantiate(reflection_type_ptr, object);
1254         intern = Z_REFLECTION_P(object);
1255         reference = (type_reference*) emalloc(sizeof(type_reference));
1256         reference->arg_info = arg_info;
1257         reference->fptr = fptr;
1258         intern->ptr = reference;
1259         intern->ref_type = REF_TYPE_TYPE;
1260         intern->ce = fptr->common.scope;
1261         if (closure_object) {
1262                 Z_ADDREF_P(closure_object);
1263                 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1264         }
1265 }
1266 /* }}} */
1267 
1268 /* {{{ reflection_function_factory */
1269 static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
1270 {
1271         reflection_object *intern;
1272         zval name;
1273 
1274         ZVAL_STR_COPY(&name, function->common.function_name);
1275 
1276         reflection_instantiate(reflection_function_ptr, object);
1277         intern = Z_REFLECTION_P(object);
1278         intern->ptr = function;
1279         intern->ref_type = REF_TYPE_FUNCTION;
1280         intern->ce = NULL;
1281         if (closure_object) {
1282                 Z_ADDREF_P(closure_object);
1283                 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1284         }
1285         reflection_update_property(object, "name", &name);
1286 }
1287 /* }}} */
1288 
1289 /* {{{ reflection_method_factory */
1290 static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object)
1291 {
1292         reflection_object *intern;
1293         zval name;
1294         zval classname;
1295 
1296         ZVAL_STR_COPY(&name, (method->common.scope && method->common.scope->trait_aliases)?
1297                         zend_resolve_method_name(ce, method) : method->common.function_name);
1298         ZVAL_STR_COPY(&classname, method->common.scope->name);
1299         reflection_instantiate(reflection_method_ptr, object);
1300         intern = Z_REFLECTION_P(object);
1301         intern->ptr = method;
1302         intern->ref_type = REF_TYPE_FUNCTION;
1303         intern->ce = ce;
1304         if (closure_object) {
1305                 Z_ADDREF_P(closure_object);
1306                 ZVAL_COPY_VALUE(&intern->obj, closure_object);
1307         }
1308         reflection_update_property(object, "name", &name);
1309         reflection_update_property(object, "class", &classname);
1310 }
1311 /* }}} */
1312 
1313 /* {{{ reflection_property_factory */
1314 static void reflection_property_factory(zend_class_entry *ce, zend_property_info *prop, zval *object)
1315 {
1316         reflection_object *intern;
1317         zval name;
1318         zval classname;
1319         property_reference *reference;
1320         const char *class_name, *prop_name;
1321         size_t prop_name_len;
1322 
1323         zend_unmangle_property_name_ex(prop->name, &class_name, &prop_name, &prop_name_len);
1324 
1325         if (!(prop->flags & ZEND_ACC_PRIVATE)) {
1326                 /* we have to search the class hierarchy for this (implicit) public or protected property */
1327                 zend_class_entry *tmp_ce = ce, *store_ce = ce;
1328                 zend_property_info *tmp_info = NULL;
1329 
1330                 while (tmp_ce && (tmp_info = zend_hash_str_find_ptr(&tmp_ce->properties_info, prop_name, prop_name_len)) == NULL) {
1331                         ce = tmp_ce;
1332                         tmp_ce = tmp_ce->parent;
1333                 }
1334 
1335                 if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */
1336                         prop = tmp_info;
1337                 } else { /* not found, use initial value */
1338                         ce = store_ce;
1339                 }
1340         }
1341 
1342         ZVAL_STRINGL(&name, prop_name, prop_name_len);
1343         ZVAL_STR_COPY(&classname, prop->ce->name);
1344 
1345         reflection_instantiate(reflection_property_ptr, object);
1346         intern = Z_REFLECTION_P(object);
1347         reference = (property_reference*) emalloc(sizeof(property_reference));
1348         reference->ce = ce;
1349         reference->prop = *prop;
1350         intern->ptr = reference;
1351         intern->ref_type = REF_TYPE_PROPERTY;
1352         intern->ce = ce;
1353         intern->ignore_visibility = 0;
1354         reflection_update_property(object, "name", &name);
1355         reflection_update_property(object, "class", &classname);
1356 }
1357 /* }}} */
1358 
1359 /* {{{ _reflection_export */
1360 static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
1361 {
1362         zval reflector;
1363         zval output, *output_ptr = &output;
1364         zval *argument_ptr, *argument2_ptr;
1365         zval retval, params[2];
1366         int result;
1367         int return_output = 0;
1368         zend_fcall_info fci;
1369         zend_fcall_info_cache fcc;
1370 
1371         if (ctor_argc == 1) {
1372                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|b", &argument_ptr, &return_output) == FAILURE) {
1373                         return;
1374                 }
1375                 ZVAL_COPY_VALUE(&params[0], argument_ptr);
1376                 ZVAL_NULL(&params[1]);
1377         } else {
1378                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
1379                         return;
1380                 }
1381                 ZVAL_COPY_VALUE(&params[0], argument_ptr);
1382                 ZVAL_COPY_VALUE(&params[1], argument2_ptr);
1383         }
1384 
1385         /* Create object */
1386         if (object_and_properties_init(&reflector, ce_ptr, NULL) == FAILURE) {
1387                 _DO_THROW("Could not create reflector");
1388         }
1389 
1390         /* Call __construct() */
1391 
1392         fci.size = sizeof(fci);
1393         fci.function_table = NULL;
1394         ZVAL_UNDEF(&fci.function_name);
1395         fci.symbol_table = NULL;
1396         fci.object = Z_OBJ(reflector);
1397         fci.retval = &retval;
1398         fci.param_count = ctor_argc;
1399         fci.params = params;
1400         fci.no_separation = 1;
1401 
1402         fcc.initialized = 1;
1403         fcc.function_handler = ce_ptr->constructor;
1404         fcc.calling_scope = ce_ptr;
1405         fcc.called_scope = Z_OBJCE(reflector);
1406         fcc.object = Z_OBJ(reflector);
1407 
1408         result = zend_call_function(&fci, &fcc);
1409 
1410         zval_ptr_dtor(&retval);
1411 
1412         if (EG(exception)) {
1413                 zval_ptr_dtor(&reflector);
1414                 return;
1415         }
1416         if (result == FAILURE) {
1417                 zval_ptr_dtor(&reflector);
1418                 _DO_THROW("Could not create reflector");
1419         }
1420 
1421         /* Call static reflection::export */
1422         ZVAL_BOOL(&output, return_output);
1423         ZVAL_COPY_VALUE(&params[0], &reflector);
1424         ZVAL_COPY_VALUE(&params[1], output_ptr);
1425 
1426         ZVAL_STRINGL(&fci.function_name, "reflection::export", sizeof("reflection::export") - 1);
1427         fci.function_table = &reflection_ptr->function_table;
1428         fci.object = NULL;
1429         fci.retval = &retval;
1430         fci.param_count = 2;
1431         fci.params = params;
1432         fci.no_separation = 1;
1433 
1434         result = zend_call_function(&fci, NULL);
1435 
1436         zval_ptr_dtor(&fci.function_name);
1437 
1438         if (result == FAILURE && EG(exception) == NULL) {
1439                 zval_ptr_dtor(&reflector);
1440                 zval_ptr_dtor(&retval);
1441                 _DO_THROW("Could not execute reflection::export()");
1442         }
1443 
1444         if (return_output) {
1445                 ZVAL_COPY_VALUE(return_value, &retval);
1446         } else {
1447                 zval_ptr_dtor(&retval);
1448         }
1449 
1450         /* Destruct reflector which is no longer needed */
1451         zval_ptr_dtor(&reflector);
1452 }
1453 /* }}} */
1454 
1455 /* {{{ _reflection_param_get_default_param */
1456 static parameter_reference *_reflection_param_get_default_param(INTERNAL_FUNCTION_PARAMETERS)
1457 {
1458         reflection_object *intern;
1459         parameter_reference *param;
1460 
1461         intern = Z_REFLECTION_P(getThis());
1462         if (intern->ptr == NULL) {
1463                 if (EG(exception) && EG(exception)->ce == reflection_exception_ptr) {
1464                         return NULL;
1465                 }
1466                 php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the reflection object");
1467         }
1468 
1469         param = intern->ptr;
1470         if (param->fptr->type != ZEND_USER_FUNCTION) {
1471                 zend_throw_exception_ex(reflection_exception_ptr, 0, "Cannot determine default value for internal functions");
1472                 return NULL;
1473         }
1474 
1475         return param;
1476 }
1477 /* }}} */
1478 
1479 /* {{{ _reflection_param_get_default_precv */
1480 static zend_op *_reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAMETERS, parameter_reference *param)
1481 {
1482         zend_op *precv;
1483 
1484         if (param == NULL) {
1485                 return NULL;
1486         }
1487 
1488         precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
1489         if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
1490                 zend_throw_exception_ex(reflection_exception_ptr, 0, "Internal error: Failed to retrieve the default value");
1491                 return NULL;
1492         }
1493 
1494         return precv;
1495 }
1496 /* }}} */
1497 
1498 /* {{{ Preventing __clone from being called */
1499 ZEND_METHOD(reflection, __clone)
1500 {
1501         /* Should never be executable */
1502         _DO_THROW("Cannot clone object using __clone()");
1503 }
1504 /* }}} */
1505 
1506 /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return])
1507    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
1508 ZEND_METHOD(reflection, export)
1509 {
1510         zval *object, fname, retval;
1511         int result;
1512         zend_bool return_output = 0;
1513 
1514 #ifndef FAST_ZPP
1515         if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &object, reflector_ptr, &return_output) == FAILURE) {
1516                 return;
1517         }
1518 #else
1519         ZEND_PARSE_PARAMETERS_START(1, 2)
1520                 Z_PARAM_OBJECT_OF_CLASS(object, reflector_ptr)
1521                 Z_PARAM_OPTIONAL
1522                 Z_PARAM_BOOL(return_output)
1523         ZEND_PARSE_PARAMETERS_END();
1524 #endif
1525 
1526         /* Invoke the __toString() method */
1527         ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1);
1528         result= call_user_function_ex(NULL, object, &fname, &retval, 0, NULL, 0, NULL);
1529         zval_dtor(&fname);
1530 
1531         if (result == FAILURE) {
1532                 _DO_THROW("Invocation of method __toString() failed");
1533                 /* Returns from this function */
1534         }
1535 
1536         if (Z_TYPE(retval) == IS_UNDEF) {
1537                 php_error_docref(NULL, E_WARNING, "%s::__toString() did not return anything", ZSTR_VAL(Z_OBJCE_P(object)->name));
1538                 RETURN_FALSE;
1539         }
1540 
1541         if (return_output) {
1542                 ZVAL_COPY_VALUE(return_value, &retval);
1543         } else {
1544                 /* No need for _r variant, return of __toString should always be a string */
1545                 zend_print_zval(&retval, 0);
1546                 zend_printf("\n");
1547                 zval_ptr_dtor(&retval);
1548         }
1549 }
1550 /* }}} */
1551 
1552 /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
1553    Returns an array of modifier names */
1554 ZEND_METHOD(reflection, getModifierNames)
1555 {
1556         zend_long modifiers;
1557 
1558         if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &modifiers) == FAILURE) {
1559                 return;
1560         }
1561 
1562         array_init(return_value);
1563 
1564         if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1565                 add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1);
1566         }
1567         if (modifiers & ZEND_ACC_FINAL) {
1568                 add_next_index_stringl(return_value, "final", sizeof("final")-1);
1569         }
1570         if (modifiers & ZEND_ACC_IMPLICIT_PUBLIC) {
1571                 add_next_index_stringl(return_value, "public", sizeof("public")-1);
1572         }
1573 
1574         /* These are mutually exclusive */
1575         switch (modifiers & ZEND_ACC_PPP_MASK) {
1576                 case ZEND_ACC_PUBLIC:
1577                         add_next_index_stringl(return_value, "public", sizeof("public")-1);
1578                         break;
1579                 case ZEND_ACC_PRIVATE:
1580                         add_next_index_stringl(return_value, "private", sizeof("private")-1);
1581                         break;
1582                 case ZEND_ACC_PROTECTED:
1583                         add_next_index_stringl(return_value, "protected", sizeof("protected")-1);
1584                         break;
1585         }
1586 
1587         if (modifiers & ZEND_ACC_STATIC) {
1588                 add_next_index_stringl(return_value, "static", sizeof("static")-1);
1589         }
1590 }
1591 /* }}} */
1592 
1593 /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return])
1594    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
1595 ZEND_METHOD(reflection_function, export)
1596 {
1597         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
1598 }
1599 /* }}} */
1600 
1601 /* {{{ proto public void ReflectionFunction::__construct(string name)
1602    Constructor. Throws an Exception in case the given function does not exist */
1603 ZEND_METHOD(reflection_function, __construct)
1604 {
1605         zval name;
1606         zval *object;
1607         zval *closure = NULL;
1608         char *lcname, *nsname;
1609         reflection_object *intern;
1610         zend_function *fptr;
1611         char *name_str;
1612         size_t name_len;
1613 
1614         object = getThis();
1615         intern = Z_REFLECTION_P(object);
1616 
1617         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O", &closure, zend_ce_closure) == SUCCESS) {
1618                 fptr = (zend_function*)zend_get_closure_method_def(closure);
1619                 Z_ADDREF_P(closure);
1620         } else { 
1621                 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
1622                         return;
1623                 }
1624 
1625                 lcname = zend_str_tolower_dup(name_str, name_len);
1626 
1627                 /* Ignore leading "\" */
1628                 nsname = lcname;
1629                 if (lcname[0] == '\\') {
1630                         nsname = &lcname[1];
1631                         name_len--;
1632                 }
1633 
1634                 if ((fptr = zend_hash_str_find_ptr(EG(function_table), nsname, name_len)) == NULL) {
1635                         efree(lcname);
1636                         zend_throw_exception_ex(reflection_exception_ptr, 0,
1637                                 "Function %s() does not exist", name_str);
1638                         return;
1639                 }
1640                 efree(lcname);
1641         }
1642 
1643         ZVAL_STR_COPY(&name, fptr->common.function_name);
1644         reflection_update_property(object, "name", &name);
1645         intern->ptr = fptr;
1646         intern->ref_type = REF_TYPE_FUNCTION;
1647         if (closure) {
1648                 ZVAL_COPY_VALUE(&intern->obj, closure);
1649         } else {
1650                 ZVAL_UNDEF(&intern->obj);
1651         }
1652         intern->ce = NULL;
1653 }
1654 /* }}} */
1655 
1656 /* {{{ proto public string ReflectionFunction::__toString()
1657    Returns a string representation */
1658 ZEND_METHOD(reflection_function, __toString)
1659 {
1660         reflection_object *intern;
1661         zend_function *fptr;
1662         string str;
1663 
1664         if (zend_parse_parameters_none() == FAILURE) {
1665                 return;
1666         }
1667         GET_REFLECTION_OBJECT_PTR(fptr);
1668         string_init(&str);
1669         _function_string(&str, fptr, intern->ce, "");
1670         RETURN_NEW_STR(str.buf);
1671 }
1672 /* }}} */
1673 
1674 /* {{{ proto public string ReflectionFunction::getName()
1675    Returns this function's name */
1676 ZEND_METHOD(reflection_function, getName)
1677 {
1678         if (zend_parse_parameters_none() == FAILURE) {
1679                 return;
1680         }
1681         _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
1682 }
1683 /* }}} */
1684 
1685 /* {{{ proto public bool ReflectionFunction::isClosure()
1686    Returns whether this is a closure */
1687 ZEND_METHOD(reflection_function, isClosure)
1688 {
1689         reflection_object *intern;
1690         zend_function *fptr;
1691 
1692         if (zend_parse_parameters_none() == FAILURE) {
1693                 return;
1694         }
1695         GET_REFLECTION_OBJECT_PTR(fptr);
1696         RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
1697 }
1698 /* }}} */
1699 
1700 /* {{{ proto public bool ReflectionFunction::getClosureThis()
1701    Returns this pointer bound to closure */
1702 ZEND_METHOD(reflection_function, getClosureThis)
1703 {
1704         reflection_object *intern;
1705         zval* closure_this;
1706 
1707         if (zend_parse_parameters_none() == FAILURE) {
1708                 return;
1709         }
1710         GET_REFLECTION_OBJECT();
1711         if (!Z_ISUNDEF(intern->obj)) {
1712                 closure_this = zend_get_closure_this_ptr(&intern->obj);
1713                 if (!Z_ISUNDEF_P(closure_this)) {
1714                         ZVAL_COPY(return_value, closure_this);
1715                 }
1716         }
1717 }
1718 /* }}} */
1719 
1720 /* {{{ proto public ReflectionClass ReflectionFunction::getClosureScopeClass()
1721    Returns the scope associated to the closure */
1722 ZEND_METHOD(reflection_function, getClosureScopeClass)
1723 {
1724         reflection_object *intern;
1725         const zend_function *closure_func;
1726 
1727         if (zend_parse_parameters_none() == FAILURE) {
1728                 return;
1729         }
1730         GET_REFLECTION_OBJECT();
1731         if (!Z_ISUNDEF(intern->obj)) {
1732                 closure_func = zend_get_closure_method_def(&intern->obj);
1733                 if (closure_func && closure_func->common.scope) {
1734                         zend_reflection_class_factory(closure_func->common.scope, return_value);
1735                 }
1736         }
1737 }
1738 /* }}} */
1739 
1740 /* {{{ proto public mixed ReflectionFunction::getClosure()
1741    Returns a dynamically created closure for the function */
1742 ZEND_METHOD(reflection_function, getClosure)
1743 {
1744         reflection_object *intern;
1745         zend_function *fptr;
1746 
1747         if (zend_parse_parameters_none() == FAILURE) {
1748                 return;
1749         }
1750         GET_REFLECTION_OBJECT_PTR(fptr);
1751 
1752         if (!Z_ISUNDEF(intern->obj)) {
1753                 /* Closures are immutable objects */
1754                 ZVAL_COPY(return_value, &intern->obj);
1755         } else {
1756                 zend_create_fake_closure(return_value, fptr, NULL, NULL, NULL);
1757         }
1758 }
1759 /* }}} */
1760 
1761 /* {{{ proto public bool ReflectionFunction::isInternal()
1762    Returns whether this is an internal function */
1763 ZEND_METHOD(reflection_function, isInternal)
1764 {
1765         reflection_object *intern;
1766         zend_function *fptr;
1767 
1768         if (zend_parse_parameters_none() == FAILURE) {
1769                 return;
1770         }
1771         GET_REFLECTION_OBJECT_PTR(fptr);
1772         RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
1773 }
1774 /* }}} */
1775 
1776 /* {{{ proto public bool ReflectionFunction::isUserDefined()
1777    Returns whether this is a user-defined function */
1778 ZEND_METHOD(reflection_function, isUserDefined)
1779 {
1780         reflection_object *intern;
1781         zend_function *fptr;
1782 
1783         if (zend_parse_parameters_none() == FAILURE) {
1784                 return;
1785         }
1786         GET_REFLECTION_OBJECT_PTR(fptr);
1787         RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
1788 }
1789 /* }}} */
1790 
1791 /* {{{ proto public bool ReflectionFunction::isDisabled()
1792    Returns whether this function has been disabled or not */
1793 ZEND_METHOD(reflection_function, isDisabled)
1794 {
1795         reflection_object *intern;
1796         zend_function *fptr;
1797 
1798         METHOD_NOTSTATIC(reflection_function_ptr);
1799         GET_REFLECTION_OBJECT_PTR(fptr);
1800         RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
1801 }
1802 /* }}} */
1803 
1804 /* {{{ proto public string ReflectionFunction::getFileName()
1805    Returns the filename of the file this function was declared in */
1806 ZEND_METHOD(reflection_function, getFileName)
1807 {
1808         reflection_object *intern;
1809         zend_function *fptr;
1810 
1811         if (zend_parse_parameters_none() == FAILURE) {
1812                 return;
1813         }
1814         GET_REFLECTION_OBJECT_PTR(fptr);
1815         if (fptr->type == ZEND_USER_FUNCTION) {
1816                 RETURN_STR_COPY(fptr->op_array.filename);
1817         }
1818         RETURN_FALSE;
1819 }
1820 /* }}} */
1821 
1822 /* {{{ proto public int ReflectionFunction::getStartLine()
1823    Returns the line this function's declaration starts at */
1824 ZEND_METHOD(reflection_function, getStartLine)
1825 {
1826         reflection_object *intern;
1827         zend_function *fptr;
1828 
1829         if (zend_parse_parameters_none() == FAILURE) {
1830                 return;
1831         }
1832         GET_REFLECTION_OBJECT_PTR(fptr);
1833         if (fptr->type == ZEND_USER_FUNCTION) {
1834                 RETURN_LONG(fptr->op_array.line_start);
1835         }
1836         RETURN_FALSE;
1837 }
1838 /* }}} */
1839 
1840 /* {{{ proto public int ReflectionFunction::getEndLine()
1841    Returns the line this function's declaration ends at */
1842 ZEND_METHOD(reflection_function, getEndLine)
1843 {
1844         reflection_object *intern;
1845         zend_function *fptr;
1846 
1847         if (zend_parse_parameters_none() == FAILURE) {
1848                 return;
1849         }
1850         GET_REFLECTION_OBJECT_PTR(fptr);
1851         if (fptr->type == ZEND_USER_FUNCTION) {
1852                 RETURN_LONG(fptr->op_array.line_end);
1853         }
1854         RETURN_FALSE;
1855 }
1856 /* }}} */
1857 
1858 /* {{{ proto public string ReflectionFunction::getDocComment()
1859    Returns the doc comment for this function */
1860 ZEND_METHOD(reflection_function, getDocComment)
1861 {
1862         reflection_object *intern;
1863         zend_function *fptr;
1864 
1865         if (zend_parse_parameters_none() == FAILURE) {
1866                 return;
1867         }
1868         GET_REFLECTION_OBJECT_PTR(fptr);
1869         if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
1870                 RETURN_STR_COPY(fptr->op_array.doc_comment);
1871         }
1872         RETURN_FALSE;
1873 }
1874 /* }}} */
1875 
1876 /* {{{ proto public array ReflectionFunction::getStaticVariables()
1877    Returns an associative array containing this function's static variables and their values */
1878 ZEND_METHOD(reflection_function, getStaticVariables)
1879 {
1880         reflection_object *intern;
1881         zend_function *fptr;
1882         zval *val;
1883 
1884         if (zend_parse_parameters_none() == FAILURE) {
1885                 return;
1886         }
1887         GET_REFLECTION_OBJECT_PTR(fptr);
1888 
1889         /* Return an empty array in case no static variables exist */
1890         array_init(return_value);
1891         if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
1892                 if (GC_REFCOUNT(fptr->op_array.static_variables) > 1) {
1893                         if (!(GC_FLAGS(fptr->op_array.static_variables) & IS_ARRAY_IMMUTABLE)) {
1894                                 GC_REFCOUNT(fptr->op_array.static_variables)--;
1895                         }
1896                         fptr->op_array.static_variables = zend_array_dup(fptr->op_array.static_variables);
1897                 }
1898                 ZEND_HASH_FOREACH_VAL(fptr->op_array.static_variables, val) {
1899                         if (UNEXPECTED(zval_update_constant_ex(val, 1, fptr->common.scope) != SUCCESS)) {
1900                                 return;
1901                         }
1902                 } ZEND_HASH_FOREACH_END();
1903                 zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, zval_add_ref);
1904         }
1905 }
1906 /* }}} */
1907 
1908 /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
1909    Invokes the function */
1910 ZEND_METHOD(reflection_function, invoke)
1911 {
1912         zval retval;
1913         zval *params = NULL;
1914         int result, num_args = 0;
1915         zend_fcall_info fci;
1916         zend_fcall_info_cache fcc;
1917         reflection_object *intern;
1918         zend_function *fptr;
1919 
1920         METHOD_NOTSTATIC(reflection_function_ptr);
1921         GET_REFLECTION_OBJECT_PTR(fptr);
1922 
1923         if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &params, &num_args) == FAILURE) {
1924                 return;
1925         }
1926 
1927         fci.size = sizeof(fci);
1928         fci.function_table = NULL;
1929         ZVAL_UNDEF(&fci.function_name);
1930         fci.symbol_table = NULL;
1931         fci.object = NULL;
1932         fci.retval = &retval;
1933         fci.param_count = num_args;
1934         fci.params = params;
1935         fci.no_separation = 1;
1936 
1937         fcc.initialized = 1;
1938         fcc.function_handler = fptr;
1939         fcc.calling_scope = EG(scope);
1940         fcc.called_scope = NULL;
1941         fcc.object = NULL;
1942 
1943         result = zend_call_function(&fci, &fcc);
1944 
1945         if (result == FAILURE) {
1946                 zend_throw_exception_ex(reflection_exception_ptr, 0,
1947                         "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
1948                 return;
1949         }
1950 
1951         if (Z_TYPE(retval) != IS_UNDEF) {
1952                 ZVAL_COPY_VALUE(return_value, &retval);
1953         }
1954 }
1955 /* }}} */
1956 
1957 /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
1958    Invokes the function and pass its arguments as array. */
1959 ZEND_METHOD(reflection_function, invokeArgs)
1960 {
1961         zval retval;
1962         zval *params, *val;
1963         int result;
1964         int i, argc;
1965         zend_fcall_info fci;
1966         zend_fcall_info_cache fcc;
1967         reflection_object *intern;
1968         zend_function *fptr;
1969         zval *param_array;
1970 
1971         METHOD_NOTSTATIC(reflection_function_ptr);
1972         GET_REFLECTION_OBJECT_PTR(fptr);
1973 
1974         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &param_array) == FAILURE) {
1975                 return;
1976         }
1977 
1978         argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
1979 
1980         params = safe_emalloc(sizeof(zval), argc, 0);
1981         argc = 0;
1982         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
1983                 ZVAL_COPY(&params[argc], val);
1984                 argc++;
1985         } ZEND_HASH_FOREACH_END();
1986 
1987         fci.size = sizeof(fci);
1988         fci.function_table = NULL;
1989         ZVAL_UNDEF(&fci.function_name);
1990         fci.symbol_table = NULL;
1991         fci.object = NULL;
1992         fci.retval = &retval;
1993         fci.param_count = argc;
1994         fci.params = params;
1995         fci.no_separation = 1;
1996 
1997         fcc.initialized = 1;
1998         fcc.function_handler = fptr;
1999         fcc.calling_scope = EG(scope);
2000         fcc.called_scope = NULL;
2001         fcc.object = NULL;
2002 
2003         result = zend_call_function(&fci, &fcc);
2004 
2005         for (i = 0; i < argc; i++) {
2006                 zval_ptr_dtor(&params[i]);
2007         }
2008         efree(params);
2009 
2010         if (result == FAILURE) {
2011                 zend_throw_exception_ex(reflection_exception_ptr, 0,
2012                         "Invocation of function %s() failed", ZSTR_VAL(fptr->common.function_name));
2013                 return;
2014         }
2015 
2016         if (Z_TYPE(retval) != IS_UNDEF) {
2017                 ZVAL_COPY_VALUE(return_value, &retval);
2018         }
2019 }
2020 /* }}} */
2021 
2022 /* {{{ proto public bool ReflectionFunction::returnsReference()
2023    Gets whether this function returns a reference */
2024 ZEND_METHOD(reflection_function, returnsReference)
2025 {
2026         reflection_object *intern;
2027         zend_function *fptr;
2028 
2029         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
2030         GET_REFLECTION_OBJECT_PTR(fptr);
2031 
2032         RETURN_BOOL((fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0);
2033 }
2034 /* }}} */
2035 
2036 /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
2037    Gets the number of required parameters */
2038 ZEND_METHOD(reflection_function, getNumberOfParameters)
2039 {
2040         reflection_object *intern;
2041         zend_function *fptr;
2042         uint32_t num_args;
2043 
2044         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
2045         GET_REFLECTION_OBJECT_PTR(fptr);
2046 
2047         num_args = fptr->common.num_args;
2048         if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2049                 num_args++;
2050         }
2051 
2052         RETURN_LONG(num_args);
2053 }
2054 /* }}} */
2055 
2056 /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
2057    Gets the number of required parameters */
2058 ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
2059 {
2060         reflection_object *intern;
2061         zend_function *fptr;
2062 
2063         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
2064         GET_REFLECTION_OBJECT_PTR(fptr);
2065 
2066         RETURN_LONG(fptr->common.required_num_args);
2067 }
2068 /* }}} */
2069 
2070 /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
2071    Returns an array of parameter objects for this function */
2072 ZEND_METHOD(reflection_function, getParameters)
2073 {
2074         reflection_object *intern;
2075         zend_function *fptr;
2076         uint32_t i, num_args;
2077         struct _zend_arg_info *arg_info;
2078 
2079         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
2080         GET_REFLECTION_OBJECT_PTR(fptr);
2081 
2082         arg_info= fptr->common.arg_info;
2083         num_args = fptr->common.num_args;
2084         if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2085                 num_args++;
2086         }
2087 
2088         array_init(return_value);
2089         for (i = 0; i < num_args; i++) {
2090                 zval parameter;
2091 
2092                 reflection_parameter_factory(_copy_function(fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, arg_info, i, fptr->common.required_num_args, &parameter);
2093                 add_next_index_zval(return_value, &parameter);
2094 
2095                 arg_info++;
2096         }
2097 }
2098 /* }}} */
2099 
2100 /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
2101    Returns NULL or the extension the function belongs to */
2102 ZEND_METHOD(reflection_function, getExtension)
2103 {
2104         reflection_object *intern;
2105         zend_function *fptr;
2106         zend_internal_function *internal;
2107 
2108         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
2109         GET_REFLECTION_OBJECT_PTR(fptr);
2110 
2111         if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2112                 RETURN_NULL();
2113         }
2114 
2115         internal = (zend_internal_function *)fptr;
2116         if (internal->module) {
2117                 reflection_extension_factory(return_value, internal->module->name);
2118         } else {
2119                 RETURN_NULL();
2120         }
2121 }
2122 /* }}} */
2123 
2124 /* {{{ proto public string|false ReflectionFunction::getExtensionName()
2125    Returns false or the name of the extension the function belongs to */
2126 ZEND_METHOD(reflection_function, getExtensionName)
2127 {
2128         reflection_object *intern;
2129         zend_function *fptr;
2130         zend_internal_function *internal;
2131 
2132         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
2133         GET_REFLECTION_OBJECT_PTR(fptr);
2134 
2135         if (fptr->type != ZEND_INTERNAL_FUNCTION) {
2136                 RETURN_FALSE;
2137         }
2138 
2139         internal = (zend_internal_function *)fptr;
2140         if (internal->module) {
2141                 RETURN_STRING(internal->module->name);
2142         } else {
2143                 RETURN_FALSE;
2144         }
2145 }
2146 /* }}} */
2147 
2148 /* {{{ proto public void ReflectionGenerator::__construct(object Generator) */
2149 ZEND_METHOD(reflection_generator, __construct)
2150 {
2151         zval *generator, *object;
2152         reflection_object *intern;
2153         zend_execute_data *ex;
2154 
2155         object = getThis();
2156         intern = Z_REFLECTION_P(object);
2157 
2158         if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "O", &generator, zend_ce_generator) == FAILURE) {
2159                 return;
2160         }
2161 
2162         ex = ((zend_generator *) Z_OBJ_P(generator))->execute_data;
2163         if (!ex) {
2164                 zend_throw_exception(NULL, "Cannot create ReflectionGenerator based on a terminated Generator", 0);
2165                 return;
2166         }
2167 
2168         intern->ref_type = REF_TYPE_GENERATOR;
2169         ZVAL_COPY(&intern->obj, generator);
2170         intern->ce = zend_ce_generator;
2171 }
2172 /* }}} */
2173 
2174 #define REFLECTION_CHECK_VALID_GENERATOR(ex) \
2175         if (!ex) { \
2176                 zend_throw_exception(NULL, "Cannot fetch information from a terminated Generator", 0); \
2177                 return; \
2178         }
2179 
2180 /* {{{ proto public array ReflectionGenerator::getTrace($options = DEBUG_BACKTRACE_PROVIDE_OBJECT) */
2181 ZEND_METHOD(reflection_generator, getTrace)
2182 {
2183         zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT;
2184         zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2185         zend_generator *root_generator;
2186         zend_execute_data *ex_backup = EG(current_execute_data);
2187         zend_execute_data *ex = generator->execute_data;
2188         zend_execute_data *root_prev = NULL, *cur_prev;
2189 
2190         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &options) == FAILURE) {
2191                 return;
2192         }
2193 
2194         REFLECTION_CHECK_VALID_GENERATOR(ex)
2195 
2196         root_generator = zend_generator_get_current(generator);
2197 
2198         cur_prev = generator->execute_data->prev_execute_data;
2199         if (generator == root_generator) {
2200                 generator->execute_data->prev_execute_data = NULL;
2201         } else {
2202                 root_prev = root_generator->execute_data->prev_execute_data;
2203                 generator->execute_fake.prev_execute_data = NULL;
2204                 root_generator->execute_data->prev_execute_data = &generator->execute_fake;
2205         }
2206 
2207         EG(current_execute_data) = root_generator->execute_data;
2208         zend_fetch_debug_backtrace(return_value, 0, options, 0);
2209         EG(current_execute_data) = ex_backup;
2210 
2211         root_generator->execute_data->prev_execute_data = root_prev;
2212         generator->execute_data->prev_execute_data = cur_prev;
2213 }
2214 /* }}} */
2215 
2216 /* {{{ proto public int ReflectionGenerator::getExecutingLine() */
2217 ZEND_METHOD(reflection_generator, getExecutingLine)
2218 {
2219         zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2220         zend_execute_data *ex = generator->execute_data;
2221 
2222         if (zend_parse_parameters_none() == FAILURE) {
2223                 return;
2224         }
2225 
2226         REFLECTION_CHECK_VALID_GENERATOR(ex)
2227 
2228         ZVAL_LONG(return_value, ex->opline->lineno);
2229 }
2230 /* }}} */
2231 
2232 /* {{{ proto public string ReflectionGenerator::getExecutingFile() */
2233 ZEND_METHOD(reflection_generator, getExecutingFile)
2234 {
2235         zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2236         zend_execute_data *ex = generator->execute_data;
2237 
2238         if (zend_parse_parameters_none() == FAILURE) {
2239                 return;
2240         }
2241 
2242         REFLECTION_CHECK_VALID_GENERATOR(ex)
2243 
2244         ZVAL_STR_COPY(return_value, ex->func->op_array.filename);
2245 }
2246 /* }}} */
2247 
2248 /* {{{ proto public ReflectionFunctionAbstract ReflectionGenerator::getFunction() */
2249 ZEND_METHOD(reflection_generator, getFunction)
2250 {
2251         zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2252         zend_execute_data *ex = generator->execute_data;
2253 
2254         if (zend_parse_parameters_none() == FAILURE) {
2255                 return;
2256         }
2257 
2258         REFLECTION_CHECK_VALID_GENERATOR(ex)
2259 
2260         if (ex->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2261                 zval closure;
2262                 ZVAL_OBJ(&closure, (zend_object *) ex->func->common.prototype);
2263                 reflection_function_factory(ex->func, &closure, return_value);
2264         } else if (ex->func->op_array.scope) {
2265                 reflection_method_factory(ex->func->op_array.scope, ex->func, NULL, return_value);
2266         } else {
2267                 reflection_function_factory(ex->func, NULL, return_value);
2268         }
2269 }
2270 /* }}} */
2271 
2272 /* {{{ proto public object ReflectionGenerator::getThis() */
2273 ZEND_METHOD(reflection_generator, getThis)
2274 {
2275         zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2276         zend_execute_data *ex = generator->execute_data;
2277 
2278         if (zend_parse_parameters_none() == FAILURE) {
2279                 return;
2280         }
2281 
2282         REFLECTION_CHECK_VALID_GENERATOR(ex)
2283 
2284         if (Z_OBJ(ex->This)) {
2285                 ZVAL_COPY(return_value, &ex->This);
2286         } else {
2287                 ZVAL_NULL(return_value);
2288         }
2289 }
2290 /* }}} */
2291 
2292 /* {{{ proto public Generator ReflectionGenerator::getExecutingGenerator() */
2293 ZEND_METHOD(reflection_generator, getExecutingGenerator)
2294 {
2295         zend_generator *generator = (zend_generator *) Z_OBJ(Z_REFLECTION_P(getThis())->obj);
2296         zend_execute_data *ex = generator->execute_data;
2297         zend_generator *current;
2298 
2299         if (zend_parse_parameters_none() == FAILURE) {
2300                 return;
2301         }
2302 
2303         REFLECTION_CHECK_VALID_GENERATOR(ex)
2304 
2305         current = zend_generator_get_current(generator);
2306         ++GC_REFCOUNT(&current->std);
2307 
2308         ZVAL_OBJ(return_value, (zend_object *) current);
2309 }
2310 /* }}} */
2311 
2312 
2313 /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
2314    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
2315 ZEND_METHOD(reflection_parameter, export)
2316 {
2317         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
2318 }
2319 /* }}} */
2320 
2321 /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
2322    Constructor. Throws an Exception in case the given method does not exist */
2323 ZEND_METHOD(reflection_parameter, __construct)
2324 {
2325         parameter_reference *ref;
2326         zval *reference, *parameter;
2327         zval *object;
2328         zval name;
2329         reflection_object *intern;
2330         zend_function *fptr;
2331         struct _zend_arg_info *arg_info;
2332         int position;
2333         uint32_t num_args;
2334         zend_class_entry *ce = NULL;
2335         zend_bool is_closure = 0;
2336 
2337         if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zz", &reference, &parameter) == FAILURE) {
2338                 return;
2339         }
2340 
2341         object = getThis();
2342         intern = Z_REFLECTION_P(object);
2343 
2344         /* First, find the function */
2345         switch (Z_TYPE_P(reference)) {
2346                 case IS_STRING: {
2347                                 size_t lcname_len;
2348                                 char *lcname;
2349 
2350                                 lcname_len = Z_STRLEN_P(reference);
2351                                 lcname = zend_str_tolower_dup(Z_STRVAL_P(reference), lcname_len);
2352                                 if ((fptr = zend_hash_str_find_ptr(EG(function_table), lcname, lcname_len)) == NULL) {
2353                                         efree(lcname);
2354                                         zend_throw_exception_ex(reflection_exception_ptr, 0,
2355                                                 "Function %s() does not exist", Z_STRVAL_P(reference));
2356                                         return;
2357                                 }
2358                                 efree(lcname);
2359                         }
2360                         ce = fptr->common.scope;
2361                         break;
2362 
2363                 case IS_ARRAY: {
2364                                 zval *classref;
2365                                 zval *method;
2366                                 size_t lcname_len;
2367                                 char *lcname;
2368 
2369                                 if (((classref =zend_hash_index_find(Z_ARRVAL_P(reference), 0)) == NULL)
2370                                         || ((method = zend_hash_index_find(Z_ARRVAL_P(reference), 1)) == NULL))
2371                                 {
2372                                         _DO_THROW("Expected array($object, $method) or array($classname, $method)");
2373                                         /* returns out of this function */
2374                                 }
2375 
2376                                 if (Z_TYPE_P(classref) == IS_OBJECT) {
2377                                         ce = Z_OBJCE_P(classref);
2378                                 } else {
2379                                         convert_to_string_ex(classref);
2380                                         if ((ce = zend_lookup_class(Z_STR_P(classref))) == NULL) {
2381                                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
2382                                                                 "Class %s does not exist", Z_STRVAL_P(classref));
2383                                                 return;
2384                                         }
2385                                 }
2386 
2387                                 convert_to_string_ex(method);
2388                                 lcname_len = Z_STRLEN_P(method);
2389                                 lcname = zend_str_tolower_dup(Z_STRVAL_P(method), lcname_len);
2390                                 if (ce == zend_ce_closure && Z_TYPE_P(classref) == IS_OBJECT
2391                                         && (lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
2392                                         && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
2393                                         && (fptr = zend_get_closure_invoke_method(Z_OBJ_P(classref))) != NULL)
2394                                 {
2395                                         /* nothing to do. don't set is_closure since is the invoke handler,
2396                                            not the closure itself */
2397                                 } else if ((fptr = zend_hash_str_find_ptr(&ce->function_table, lcname, lcname_len)) == NULL) {
2398                                         efree(lcname);
2399                                         zend_throw_exception_ex(reflection_exception_ptr, 0,
2400                                                 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), Z_STRVAL_P(method));
2401                                         return;
2402                                 }
2403                                 efree(lcname);
2404                         }
2405                         break;
2406 
2407                 case IS_OBJECT: {
2408                                 ce = Z_OBJCE_P(reference);
2409 
2410                                 if (instanceof_function(ce, zend_ce_closure)) {
2411                                         fptr = (zend_function *)zend_get_closure_method_def(reference);
2412                                         Z_ADDREF_P(reference);
2413                                         is_closure = 1;
2414                                 } else if ((fptr = zend_hash_str_find_ptr(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME))) == NULL) {
2415                                         zend_throw_exception_ex(reflection_exception_ptr, 0,
2416                                                 "Method %s::%s() does not exist", ZSTR_VAL(ce->name), ZEND_INVOKE_FUNC_NAME);
2417                                         return;
2418                                 }
2419                         }
2420                         break;
2421 
2422                 default:
2423                         _DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
2424                         /* returns out of this function */
2425         }
2426 
2427         /* Now, search for the parameter */
2428         arg_info = fptr->common.arg_info;
2429         num_args = fptr->common.num_args;
2430         if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) {
2431                 num_args++;
2432         }
2433         if (Z_TYPE_P(parameter) == IS_LONG) {
2434                 position= (int)Z_LVAL_P(parameter);
2435                 if (position < 0 || (uint32_t)position >= num_args) {
2436                         if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2437                                 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
2438                                         zend_string_release(fptr->common.function_name);
2439                                 }
2440                                 zend_free_trampoline(fptr);
2441                         }
2442                         if (is_closure) {
2443                                 zval_ptr_dtor(reference);
2444                         }
2445                         _DO_THROW("The parameter specified by its offset could not be found");
2446                         /* returns out of this function */
2447                 }
2448         } else {
2449                 uint32_t i;
2450 
2451                 position= -1;
2452                 convert_to_string_ex(parameter);
2453                 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2454                     !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2455                         for (i = 0; i < num_args; i++) {
2456                                 if (arg_info[i].name) {
2457                                         if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) {
2458                                                 position= i;
2459                                                 break;
2460                                         }
2461 
2462                                 }
2463                         }
2464                 } else {
2465                         for (i = 0; i < num_args; i++) {
2466                                 if (arg_info[i].name) {
2467                                         if (strcmp(ZSTR_VAL(arg_info[i].name), Z_STRVAL_P(parameter)) == 0) {
2468                                                 position= i;
2469                                                 break;
2470                                         }
2471                                 }
2472                         }
2473                 }
2474                 if (position == -1) {
2475                         if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2476                                 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
2477                                         zend_string_release(fptr->common.function_name);
2478                                 }
2479                                 zend_free_trampoline(fptr);
2480                         }
2481                         if (is_closure) {
2482                                 zval_ptr_dtor(reference);
2483                         }
2484                         _DO_THROW("The parameter specified by its name could not be found");
2485                         /* returns out of this function */
2486                 }
2487         }
2488 
2489         if (arg_info[position].name) {
2490                 if (fptr->type == ZEND_INTERNAL_FUNCTION &&
2491                     !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2492                         ZVAL_STRING(&name, ((zend_internal_arg_info*)arg_info)[position].name);
2493                 } else {
2494                         ZVAL_STR_COPY(&name, arg_info[position].name);
2495                 }
2496         } else {
2497                 ZVAL_NULL(&name);
2498         }
2499         reflection_update_property(object, "name", &name);
2500 
2501         ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
2502         ref->arg_info = &arg_info[position];
2503         ref->offset = (uint32_t)position;
2504         ref->required = fptr->common.required_num_args;
2505         ref->fptr = fptr;
2506         /* TODO: copy fptr */
2507         intern->ptr = ref;
2508         intern->ref_type = REF_TYPE_PARAMETER;
2509         intern->ce = ce;
2510         if (reference && is_closure) {
2511                 ZVAL_COPY_VALUE(&intern->obj, reference);
2512         }
2513 }
2514 /* }}} */
2515 
2516 /* {{{ proto public string ReflectionParameter::__toString()
2517    Returns a string representation */
2518 ZEND_METHOD(reflection_parameter, __toString)
2519 {
2520         reflection_object *intern;
2521         parameter_reference *param;
2522         string str;
2523 
2524         if (zend_parse_parameters_none() == FAILURE) {
2525                 return;
2526         }
2527         GET_REFLECTION_OBJECT_PTR(param);
2528         string_init(&str);
2529         _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
2530         RETURN_NEW_STR(str.buf);
2531 }
2532 
2533 /* }}} */
2534 
2535 /* {{{ proto public string ReflectionParameter::getName()
2536    Returns this parameters's name */
2537 ZEND_METHOD(reflection_parameter, getName)
2538 {
2539         if (zend_parse_parameters_none() == FAILURE) {
2540                 return;
2541         }
2542         _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
2543 }
2544 /* }}} */
2545 
2546 /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
2547    Returns the ReflectionFunction for the function of this parameter */
2548 ZEND_METHOD(reflection_parameter, getDeclaringFunction)
2549 {
2550         reflection_object *intern;
2551         parameter_reference *param;
2552 
2553         if (zend_parse_parameters_none() == FAILURE) {
2554                 return;
2555         }
2556         GET_REFLECTION_OBJECT_PTR(param);
2557 
2558         if (!param->fptr->common.scope) {
2559                 reflection_function_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2560         } else {
2561                 reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, return_value);
2562         }
2563 }
2564 /* }}} */
2565 
2566 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
2567    Returns in which class this parameter is defined (not the type of the parameter) */
2568 ZEND_METHOD(reflection_parameter, getDeclaringClass)
2569 {
2570         reflection_object *intern;
2571         parameter_reference *param;
2572 
2573         if (zend_parse_parameters_none() == FAILURE) {
2574                 return;
2575         }
2576         GET_REFLECTION_OBJECT_PTR(param);
2577 
2578         if (param->fptr->common.scope) {
2579                 zend_reflection_class_factory(param->fptr->common.scope, return_value);
2580         }
2581 }
2582 /* }}} */
2583 
2584 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
2585    Returns this parameters's class hint or NULL if there is none */
2586 ZEND_METHOD(reflection_parameter, getClass)
2587 {
2588         reflection_object *intern;
2589         parameter_reference *param;
2590         zend_class_entry *ce;
2591 
2592         if (zend_parse_parameters_none() == FAILURE) {
2593                 return;
2594         }
2595         GET_REFLECTION_OBJECT_PTR(param);
2596 
2597         if (param->arg_info->class_name) {
2598                 /* Class name is stored as a string, we might also get "self" or "parent"
2599                  * - For "self", simply use the function scope. If scope is NULL then
2600                  *   the function is global and thus self does not make any sense
2601                  *
2602                  * - For "parent", use the function scope's parent. If scope is NULL then
2603                  *   the function is global and thus parent does not make any sense.
2604                  *   If the parent is NULL then the class does not extend anything and
2605                  *   thus parent does not make any sense, either.
2606                  *
2607                  * TODO: Think about moving these checks to the compiler or some sort of
2608                  * lint-mode.
2609                  */
2610                 const char *class_name;
2611                 size_t class_name_len;
2612 
2613                 if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
2614                     !(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2615                         class_name = ((zend_internal_arg_info*)param->arg_info)->class_name;
2616                         class_name_len = strlen(class_name);
2617                 } else {
2618                         class_name = ZSTR_VAL(param->arg_info->class_name);
2619                         class_name_len = ZSTR_LEN(param->arg_info->class_name);
2620                 }
2621                 if (0 == zend_binary_strcasecmp(class_name, class_name_len, "self", sizeof("self")- 1)) {
2622                         ce = param->fptr->common.scope;
2623                         if (!ce) {
2624                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
2625                                         "Parameter uses 'self' as type hint but function is not a class member!");
2626                                 return;
2627                         }
2628                 } else if (0 == zend_binary_strcasecmp(class_name, class_name_len, "parent", sizeof("parent")- 1)) {
2629                         ce = param->fptr->common.scope;
2630                         if (!ce) {
2631                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
2632                                         "Parameter uses 'parent' as type hint but function is not a class member!");
2633                                 return;
2634                         }
2635                         if (!ce->parent) {
2636                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
2637                                         "Parameter uses 'parent' as type hint although class does not have a parent!");
2638                                 return;
2639                         }
2640                         ce = ce->parent;
2641                 } else {
2642                         if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
2643                             !(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2644                                 zend_string *name = zend_string_init(class_name, class_name_len, 0);
2645                                 ce = zend_lookup_class(name);
2646                                 zend_string_release(name);
2647                         } else {
2648                                 ce = zend_lookup_class(param->arg_info->class_name);
2649                         }
2650                         if (!ce) {
2651                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
2652                                         "Class %s does not exist", class_name);
2653                                 return;
2654                         }
2655                 }
2656                 zend_reflection_class_factory(ce, return_value);
2657         }
2658 }
2659 /* }}} */
2660 
2661 /* {{{ proto public bool ReflectionParameter::hasType()
2662    Returns whether parameter has a type */
2663 ZEND_METHOD(reflection_parameter, hasType)
2664 {
2665         reflection_object *intern;
2666         parameter_reference *param;
2667 
2668         if (zend_parse_parameters_none() == FAILURE) {
2669                 return;
2670         }
2671         GET_REFLECTION_OBJECT_PTR(param);
2672 
2673         RETVAL_BOOL(param->arg_info->type_hint != 0);
2674 }
2675 /* }}} */
2676 
2677 /* {{{ proto public ReflectionType ReflectionParameter::getType()
2678    Returns the type associated with the parameter */
2679 ZEND_METHOD(reflection_parameter, getType)
2680 {
2681         reflection_object *intern;
2682         parameter_reference *param;
2683 
2684         if (zend_parse_parameters_none() == FAILURE) {
2685                 return;
2686         }
2687         GET_REFLECTION_OBJECT_PTR(param);
2688 
2689         if (((param->fptr->type == ZEND_INTERNAL_FUNCTION &&
2690               !(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) ?
2691                 ((zend_internal_arg_info*)param->arg_info)->type_hint :
2692                 param->arg_info->type_hint) == 0)
2693         {
2694                 RETURN_NULL();
2695         }
2696         reflection_type_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, param->arg_info, return_value);
2697 }
2698 /* }}} */
2699 
2700 /* {{{ proto public bool ReflectionParameter::isArray()
2701    Returns whether parameter MUST be an array */
2702 ZEND_METHOD(reflection_parameter, isArray)
2703 {
2704         reflection_object *intern;
2705         parameter_reference *param;
2706 
2707         if (zend_parse_parameters_none() == FAILURE) {
2708                 return;
2709         }
2710         GET_REFLECTION_OBJECT_PTR(param);
2711 
2712         RETVAL_BOOL(param->arg_info->type_hint == IS_ARRAY);
2713 }
2714 /* }}} */
2715 
2716 /* {{{ proto public bool ReflectionParameter::isCallable()
2717    Returns whether parameter MUST be callable */
2718 ZEND_METHOD(reflection_parameter, isCallable)
2719 {
2720         reflection_object *intern;
2721         parameter_reference *param;
2722 
2723         if (zend_parse_parameters_none() == FAILURE) {
2724                 return;
2725         }
2726         GET_REFLECTION_OBJECT_PTR(param);
2727 
2728         RETVAL_BOOL(param->arg_info->type_hint == IS_CALLABLE);
2729 }
2730 /* }}} */
2731 
2732 /* {{{ proto public bool ReflectionParameter::allowsNull()
2733    Returns whether NULL is allowed as this parameters's value */
2734 ZEND_METHOD(reflection_parameter, allowsNull)
2735 {
2736         reflection_object *intern;
2737         parameter_reference *param;
2738 
2739         if (zend_parse_parameters_none() == FAILURE) {
2740                 return;
2741         }
2742         GET_REFLECTION_OBJECT_PTR(param);
2743 
2744         RETVAL_BOOL(param->arg_info->allow_null);
2745 }
2746 /* }}} */
2747 
2748 /* {{{ proto public bool ReflectionParameter::isPassedByReference()
2749    Returns whether this parameters is passed to by reference */
2750 ZEND_METHOD(reflection_parameter, isPassedByReference)
2751 {
2752         reflection_object *intern;
2753         parameter_reference *param;
2754 
2755         if (zend_parse_parameters_none() == FAILURE) {
2756                 return;
2757         }
2758         GET_REFLECTION_OBJECT_PTR(param);
2759 
2760         RETVAL_BOOL(param->arg_info->pass_by_reference);
2761 }
2762 /* }}} */
2763 
2764 /* {{{ proto public bool ReflectionParameter::canBePassedByValue()
2765    Returns whether this parameter can be passed by value */
2766 ZEND_METHOD(reflection_parameter, canBePassedByValue)
2767 {
2768         reflection_object *intern;
2769         parameter_reference *param;
2770 
2771         if (zend_parse_parameters_none() == FAILURE) {
2772                 return;
2773         }
2774         GET_REFLECTION_OBJECT_PTR(param);
2775 
2776         /* true if it's ZEND_SEND_BY_VAL or ZEND_SEND_PREFER_REF */
2777         RETVAL_BOOL(param->arg_info->pass_by_reference != ZEND_SEND_BY_REF);
2778 }
2779 /* }}} */
2780 
2781 /* {{{ proto public bool ReflectionParameter::getPosition()
2782    Returns whether this parameter is an optional parameter */
2783 ZEND_METHOD(reflection_parameter, getPosition)
2784 {
2785         reflection_object *intern;
2786         parameter_reference *param;
2787 
2788         if (zend_parse_parameters_none() == FAILURE) {
2789                 return;
2790         }
2791         GET_REFLECTION_OBJECT_PTR(param);
2792 
2793         RETVAL_LONG(param->offset);
2794 }
2795 /* }}} */
2796 
2797 /* {{{ proto public bool ReflectionParameter::isOptional()
2798    Returns whether this parameter is an optional parameter */
2799 ZEND_METHOD(reflection_parameter, isOptional)
2800 {
2801         reflection_object *intern;
2802         parameter_reference *param;
2803 
2804         if (zend_parse_parameters_none() == FAILURE) {
2805                 return;
2806         }
2807         GET_REFLECTION_OBJECT_PTR(param);
2808 
2809         RETVAL_BOOL(param->offset >= param->required);
2810 }
2811 /* }}} */
2812 
2813 /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
2814    Returns whether the default value of this parameter is available */
2815 ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
2816 {
2817         reflection_object *intern;
2818         parameter_reference *param;
2819         zend_op *precv;
2820 
2821         if (zend_parse_parameters_none() == FAILURE) {
2822                 return;
2823         }
2824         GET_REFLECTION_OBJECT_PTR(param);
2825 
2826         if (param->fptr->type != ZEND_USER_FUNCTION)
2827         {
2828                 RETURN_FALSE;
2829         }
2830 
2831         precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
2832         if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2_type == IS_UNUSED) {
2833                 RETURN_FALSE;
2834         }
2835         RETURN_TRUE;
2836 }
2837 /* }}} */
2838 
2839 /* {{{ proto public bool ReflectionParameter::getDefaultValue()
2840    Returns the default value of this parameter or throws an exception */
2841 ZEND_METHOD(reflection_parameter, getDefaultValue)
2842 {
2843         parameter_reference *param;
2844         zend_op *precv;
2845 
2846         if (zend_parse_parameters_none() == FAILURE) {
2847                 return;
2848         }
2849 
2850         param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2851         if (!param) {
2852                 return;
2853         }
2854 
2855         precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2856         if (!precv) {
2857                 return;
2858         }
2859 
2860         ZVAL_COPY_VALUE(return_value, RT_CONSTANT(&param->fptr->op_array, precv->op2));
2861         if (Z_CONSTANT_P(return_value)) {
2862                 zend_class_entry *old_scope = EG(scope);
2863 
2864                 EG(scope) = param->fptr->common.scope;
2865                 zval_update_constant_ex(return_value, 0, NULL);
2866                 EG(scope) = old_scope;
2867         } else {
2868                 zval_copy_ctor(return_value);
2869         }
2870 }
2871 /* }}} */
2872 
2873 /* {{{ proto public bool ReflectionParameter::isDefaultValueConstant()
2874    Returns whether the default value of this parameter is constant */
2875 ZEND_METHOD(reflection_parameter, isDefaultValueConstant)
2876 {
2877         zend_op *precv;
2878         parameter_reference *param;
2879 
2880         if (zend_parse_parameters_none() == FAILURE) {
2881                 return;
2882         }
2883 
2884         param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2885         if (!param) {
2886                 RETURN_FALSE;
2887         }
2888 
2889         precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2890         if (precv && Z_TYPE_P(RT_CONSTANT(&param->fptr->op_array, precv->op2)) == IS_CONSTANT) {
2891                 RETURN_TRUE;
2892         }
2893 
2894         RETURN_FALSE;
2895 }
2896 /* }}} */
2897 
2898 /* {{{ proto public mixed ReflectionParameter::getDefaultValueConstantName()
2899    Returns the default value's constant name if default value is constant or null */
2900 ZEND_METHOD(reflection_parameter, getDefaultValueConstantName)
2901 {
2902         zend_op *precv;
2903         parameter_reference *param;
2904 
2905         if (zend_parse_parameters_none() == FAILURE) {
2906                 return;
2907         }
2908 
2909         param = _reflection_param_get_default_param(INTERNAL_FUNCTION_PARAM_PASSTHRU);
2910         if (!param) {
2911                 return;
2912         }
2913 
2914         precv = _reflection_param_get_default_precv(INTERNAL_FUNCTION_PARAM_PASSTHRU, param);
2915         if (precv && Z_TYPE_P(RT_CONSTANT(&param->fptr->op_array, precv->op2)) == IS_CONSTANT) {
2916                 RETURN_STR_COPY(Z_STR_P(RT_CONSTANT(&param->fptr->op_array, precv->op2)));
2917         }
2918 }
2919 /* }}} */
2920 
2921 /* {{{ proto public bool ReflectionParameter::isVariadic()
2922    Returns whether this parameter is a variadic parameter */
2923 ZEND_METHOD(reflection_parameter, isVariadic)
2924 {
2925         reflection_object *intern;
2926         parameter_reference *param;
2927 
2928         if (zend_parse_parameters_none() == FAILURE) {
2929                 return;
2930         }
2931         GET_REFLECTION_OBJECT_PTR(param);
2932 
2933         RETVAL_BOOL(param->arg_info->is_variadic);
2934 }
2935 /* }}} */
2936 
2937 /* {{{ proto public bool ReflectionType::allowsNull()
2938   Returns whether parameter MAY be null */
2939 ZEND_METHOD(reflection_type, allowsNull)
2940 {
2941         reflection_object *intern;
2942         type_reference *param;
2943 
2944         if (zend_parse_parameters_none() == FAILURE) {
2945                 return;
2946         }
2947         GET_REFLECTION_OBJECT_PTR(param);
2948 
2949         RETVAL_BOOL(param->arg_info->allow_null);
2950 }
2951 /* }}} */
2952 
2953 /* {{{ proto public bool ReflectionType::isBuiltin()
2954   Returns whether parameter is a builtin type */
2955 ZEND_METHOD(reflection_type, isBuiltin)
2956 {
2957         reflection_object *intern;
2958         type_reference *param;
2959 
2960         if (zend_parse_parameters_none() == FAILURE) {
2961                 return;
2962         }
2963         GET_REFLECTION_OBJECT_PTR(param);
2964 
2965         RETVAL_BOOL(param->arg_info->type_hint != IS_OBJECT);
2966 }
2967 /* }}} */
2968 
2969 /* {{{ proto public string ReflectionType::__toString()
2970    Return the text of the type hint */
2971 ZEND_METHOD(reflection_type, __toString)
2972 {
2973         reflection_object *intern;
2974         type_reference *param;
2975 
2976         if (zend_parse_parameters_none() == FAILURE) {
2977                 return;
2978         }
2979         GET_REFLECTION_OBJECT_PTR(param);
2980 
2981         switch (param->arg_info->type_hint) {
2982                 case IS_ARRAY:    RETURN_STRINGL("array", sizeof("array") - 1);
2983                 case IS_CALLABLE: RETURN_STRINGL("callable", sizeof("callable") - 1);
2984                 case IS_OBJECT:
2985                         if (param->fptr->type == ZEND_INTERNAL_FUNCTION &&
2986                             !(param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
2987                                 RETURN_STRING(((zend_internal_arg_info*)param->arg_info)->class_name);
2988                         }
2989                         RETURN_STR_COPY(param->arg_info->class_name);
2990                 case IS_STRING:   RETURN_STRINGL("string", sizeof("string") - 1);
2991                 case _IS_BOOL:    RETURN_STRINGL("bool", sizeof("bool") - 1);
2992                 case IS_LONG:     RETURN_STRINGL("int", sizeof("int") - 1);
2993                 case IS_DOUBLE:   RETURN_STRINGL("float", sizeof("float") - 1);
2994                 EMPTY_SWITCH_DEFAULT_CASE()
2995         }
2996 }
2997 /* }}} */
2998 
2999 /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
3000    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
3001 ZEND_METHOD(reflection_method, export)
3002 {
3003         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
3004 }
3005 /* }}} */
3006 
3007 /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
3008    Constructor. Throws an Exception in case the given method does not exist */
3009 ZEND_METHOD(reflection_method, __construct)
3010 {
3011         zval name, *classname;
3012         zval *object, *orig_obj;
3013         reflection_object *intern;
3014         char *lcname;
3015         zend_class_entry *ce;
3016         zend_function *mptr;
3017         char *name_str, *tmp;
3018         size_t name_len, tmp_len;
3019         zval ztmp;
3020 
3021         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
3022                 if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
3023                         return;
3024                 }
3025 
3026                 if ((tmp = strstr(name_str, "::")) == NULL) {
3027                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3028                                 "Invalid method name %s", name_str);
3029                         return;
3030                 }
3031                 classname = &ztmp;
3032                 tmp_len = tmp - name_str;
3033                 ZVAL_STRINGL(classname, name_str, tmp_len);
3034                 name_len = name_len - (tmp_len + 2);
3035                 name_str = tmp + 2;
3036                 orig_obj = NULL;
3037         } else if (Z_TYPE_P(classname) == IS_OBJECT) {
3038                 orig_obj = classname;
3039         } else {
3040                 orig_obj = NULL;
3041         }
3042 
3043         object = getThis();
3044         intern = Z_REFLECTION_P(object);
3045 
3046         /* Find the class entry */
3047         switch (Z_TYPE_P(classname)) {
3048                 case IS_STRING:
3049                         if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
3050                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
3051                                                 "Class %s does not exist", Z_STRVAL_P(classname));
3052                                 if (classname == &ztmp) {
3053                                         zval_dtor(&ztmp);
3054                                 }
3055                                 return;
3056                         }
3057                         break;
3058 
3059                 case IS_OBJECT:
3060                         ce = Z_OBJCE_P(classname);
3061                         break;
3062 
3063                 default:
3064                         if (classname == &ztmp) {
3065                                 zval_dtor(&ztmp);
3066                         }
3067                         _DO_THROW("The parameter class is expected to be either a string or an object");
3068                         /* returns out of this function */
3069         }
3070 
3071         if (classname == &ztmp) {
3072                 zval_dtor(&ztmp);
3073         }
3074 
3075         lcname = zend_str_tolower_dup(name_str, name_len);
3076 
3077         if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
3078                 && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
3079                 && (mptr = zend_get_closure_invoke_method(Z_OBJ_P(orig_obj))) != NULL)
3080         {
3081                 /* do nothing, mptr already set */
3082         } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lcname, name_len)) == NULL) {
3083                 efree(lcname);
3084                 zend_throw_exception_ex(reflection_exception_ptr, 0,
3085                         "Method %s::%s() does not exist", ZSTR_VAL(ce->name), name_str);
3086                 return;
3087         }
3088         efree(lcname);
3089 
3090         ZVAL_STR_COPY(&name, mptr->common.scope->name);
3091         reflection_update_property(object, "class", &name);
3092         ZVAL_STR_COPY(&name, mptr->common.function_name);
3093         reflection_update_property(object, "name", &name);
3094         intern->ptr = mptr;
3095         intern->ref_type = REF_TYPE_FUNCTION;
3096         intern->ce = ce;
3097 }
3098 /* }}} */
3099 
3100 /* {{{ proto public string ReflectionMethod::__toString()
3101    Returns a string representation */
3102 ZEND_METHOD(reflection_method, __toString)
3103 {
3104         reflection_object *intern;
3105         zend_function *mptr;
3106         string str;
3107 
3108         if (zend_parse_parameters_none() == FAILURE) {
3109                 return;
3110         }
3111         GET_REFLECTION_OBJECT_PTR(mptr);
3112         string_init(&str);
3113         _function_string(&str, mptr, intern->ce, "");
3114         RETURN_NEW_STR(str.buf);
3115 }
3116 /* }}} */
3117 
3118 /* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
3119    Invokes the function */
3120 ZEND_METHOD(reflection_method, getClosure)
3121 {
3122         reflection_object *intern;
3123         zval *obj;
3124         zend_function *mptr;
3125 
3126         METHOD_NOTSTATIC(reflection_method_ptr);
3127         GET_REFLECTION_OBJECT_PTR(mptr);
3128 
3129         if (mptr->common.fn_flags & ZEND_ACC_STATIC)  {
3130                 zend_create_fake_closure(return_value, mptr, mptr->common.scope, mptr->common.scope, NULL);
3131         } else {
3132                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) {
3133                         return;
3134                 }
3135 
3136                 if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope)) {
3137                         _DO_THROW("Given object is not an instance of the class this method was declared in");
3138                         /* Returns from this function */
3139                 }
3140 
3141                 /* This is an original closure object and __invoke is to be called. */
3142                 if (Z_OBJCE_P(obj) == zend_ce_closure &&
3143                         (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
3144                 {
3145                         ZVAL_COPY(return_value, obj);
3146                 } else {
3147                         zend_create_fake_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
3148                 }
3149         }
3150 }
3151 /* }}} */
3152 
3153 /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
3154    Invokes the method. */
3155 ZEND_METHOD(reflection_method, invoke)
3156 {
3157         zval retval;
3158         zval *params = NULL;
3159         zend_object *object;
3160         reflection_object *intern;
3161         zend_function *mptr;
3162         int result, num_args = 0;
3163         zend_fcall_info fci;
3164         zend_fcall_info_cache fcc;
3165         zend_class_entry *obj_ce;
3166 
3167         METHOD_NOTSTATIC(reflection_method_ptr);
3168 
3169         GET_REFLECTION_OBJECT_PTR(mptr);
3170 
3171         if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
3172                  || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
3173                  && intern->ignore_visibility == 0)
3174         {
3175                 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
3176                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3177                                 "Trying to invoke abstract method %s::%s()",
3178                                 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3179                 } else {
3180                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3181                                 "Trying to invoke %s method %s::%s() from scope %s",
3182                                 mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
3183                                 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
3184                                 ZSTR_VAL(Z_OBJCE_P(getThis())->name));
3185                 }
3186                 return;
3187         }
3188 
3189         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &params, &num_args) == FAILURE) {
3190                 return;
3191         }
3192 
3193         /* In case this is a static method, we should'nt pass an object_ptr
3194          * (which is used as calling context aka $this). We can thus ignore the
3195          * first parameter.
3196          *
3197          * Else, we verify that the given object is an instance of the class.
3198          */
3199         if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3200                 object = NULL;
3201                 obj_ce = mptr->common.scope;
3202         } else {
3203                 if (Z_TYPE(params[0]) != IS_OBJECT) {
3204                         _DO_THROW("Non-object passed to Invoke()");
3205                         /* Returns from this function */
3206                 }
3207 
3208                 obj_ce = Z_OBJCE(params[0]);
3209 
3210                 if (!instanceof_function(obj_ce, mptr->common.scope)) {
3211                         _DO_THROW("Given object is not an instance of the class this method was declared in");
3212                         /* Returns from this function */
3213                 }
3214 
3215                 object = Z_OBJ(params[0]);
3216         }
3217 
3218         fci.size = sizeof(fci);
3219         fci.function_table = NULL;
3220         ZVAL_UNDEF(&fci.function_name);
3221         fci.symbol_table = NULL;
3222         fci.object = object;
3223         fci.retval = &retval;
3224         fci.param_count = num_args - 1;
3225         fci.params = params + 1;
3226         fci.no_separation = 1;
3227 
3228         fcc.initialized = 1;
3229         fcc.function_handler = mptr;
3230         fcc.calling_scope = obj_ce;
3231         fcc.called_scope = intern->ce;
3232         fcc.object = object;
3233 
3234         result = zend_call_function(&fci, &fcc);
3235 
3236         if (result == FAILURE) {
3237                 zend_throw_exception_ex(reflection_exception_ptr, 0,
3238                         "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3239                 return;
3240         }
3241 
3242         if (Z_TYPE(retval) != IS_UNDEF) {
3243                 ZVAL_COPY_VALUE(return_value, &retval);
3244         }
3245 }
3246 /* }}} */
3247 
3248 /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
3249    Invokes the function and pass its arguments as array. */
3250 ZEND_METHOD(reflection_method, invokeArgs)
3251 {
3252         zval retval;
3253         zval *params, *val, *object;
3254         reflection_object *intern;
3255         zend_function *mptr;
3256         int i, argc;
3257         int result;
3258         zend_fcall_info fci;
3259         zend_fcall_info_cache fcc;
3260         zend_class_entry *obj_ce;
3261         zval *param_array;
3262 
3263         METHOD_NOTSTATIC(reflection_method_ptr);
3264 
3265         GET_REFLECTION_OBJECT_PTR(mptr);
3266 
3267         if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a", &object, &param_array) == FAILURE) {
3268                 return;
3269         }
3270 
3271         if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
3272                  || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
3273                  && intern->ignore_visibility == 0)
3274         {
3275                 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
3276                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3277                                 "Trying to invoke abstract method %s::%s()",
3278                                 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3279                 } else {
3280                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3281                                 "Trying to invoke %s method %s::%s() from scope %s",
3282                                 mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
3283                                 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name),
3284                                 ZSTR_VAL(Z_OBJCE_P(getThis())->name));
3285                 }
3286                 return;
3287         }
3288 
3289         argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
3290 
3291         params = safe_emalloc(sizeof(zval), argc, 0);
3292         argc = 0;
3293         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(param_array), val) {
3294                 ZVAL_COPY(&params[argc], val);
3295                 argc++;
3296         } ZEND_HASH_FOREACH_END();
3297 
3298         /* In case this is a static method, we should'nt pass an object_ptr
3299          * (which is used as calling context aka $this). We can thus ignore the
3300          * first parameter.
3301          *
3302          * Else, we verify that the given object is an instance of the class.
3303          */
3304         if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
3305                 object = NULL;
3306                 obj_ce = mptr->common.scope;
3307         } else {
3308                 if (!object) {
3309                         efree(params);
3310                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3311                                 "Trying to invoke non static method %s::%s() without an object",
3312                                 ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3313                         return;
3314                 }
3315 
3316                 obj_ce = Z_OBJCE_P(object);
3317 
3318                 if (!instanceof_function(obj_ce, mptr->common.scope)) {
3319                         efree(params);
3320                         _DO_THROW("Given object is not an instance of the class this method was declared in");
3321                         /* Returns from this function */
3322                 }
3323         }
3324 
3325         fci.size = sizeof(fci);
3326         fci.function_table = NULL;
3327         ZVAL_UNDEF(&fci.function_name);
3328         fci.symbol_table = NULL;
3329         fci.object = object ? Z_OBJ_P(object) : NULL;
3330         fci.retval = &retval;
3331         fci.param_count = argc;
3332         fci.params = params;
3333         fci.no_separation = 1;
3334 
3335         fcc.initialized = 1;
3336         fcc.function_handler = mptr;
3337         fcc.calling_scope = obj_ce;
3338         fcc.called_scope = intern->ce;
3339         fcc.object = (object) ? Z_OBJ_P(object) : NULL;
3340 
3341         /*
3342          * Copy the zend_function when calling via handler (e.g. Closure::__invoke())
3343          */
3344         if ((mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
3345                 fcc.function_handler = _copy_function(mptr);
3346         }
3347 
3348         result = zend_call_function(&fci, &fcc);
3349 
3350         for (i = 0; i < argc; i++) {
3351                 zval_ptr_dtor(&params[i]);
3352         }
3353         efree(params);
3354 
3355         if (result == FAILURE) {
3356                 zend_throw_exception_ex(reflection_exception_ptr, 0,
3357                         "Invocation of method %s::%s() failed", ZSTR_VAL(mptr->common.scope->name), ZSTR_VAL(mptr->common.function_name));
3358                 return;
3359         }
3360 
3361         if (Z_TYPE(retval) != IS_UNDEF) {
3362                 ZVAL_COPY_VALUE(return_value, &retval);
3363         }
3364 }
3365 /* }}} */
3366 
3367 /* {{{ proto public bool ReflectionMethod::isFinal()
3368    Returns whether this method is final */
3369 ZEND_METHOD(reflection_method, isFinal)
3370 {
3371         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
3372 }
3373 /* }}} */
3374 
3375 /* {{{ proto public bool ReflectionMethod::isAbstract()
3376    Returns whether this method is abstract */
3377 ZEND_METHOD(reflection_method, isAbstract)
3378 {
3379         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
3380 }
3381 /* }}} */
3382 
3383 /* {{{ proto public bool ReflectionMethod::isPublic()
3384    Returns whether this method is public */
3385 ZEND_METHOD(reflection_method, isPublic)
3386 {
3387         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
3388 }
3389 /* }}} */
3390 
3391 /* {{{ proto public bool ReflectionMethod::isPrivate()
3392    Returns whether this method is private */
3393 ZEND_METHOD(reflection_method, isPrivate)
3394 {
3395         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
3396 }
3397 /* }}} */
3398 
3399 /* {{{ proto public bool ReflectionMethod::isProtected()
3400    Returns whether this method is protected */
3401 ZEND_METHOD(reflection_method, isProtected)
3402 {
3403         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
3404 }
3405 /* }}} */
3406 
3407 /* {{{ proto public bool ReflectionMethod::isStatic()
3408    Returns whether this method is static */
3409 ZEND_METHOD(reflection_method, isStatic)
3410 {
3411         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
3412 }
3413 /* }}} */
3414 
3415 /* {{{ proto public bool ReflectionFunction::isDeprecated()
3416    Returns whether this function is deprecated */
3417 ZEND_METHOD(reflection_function, isDeprecated)
3418 {
3419         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
3420 }
3421 /* }}} */
3422 
3423 /* {{{ proto public bool ReflectionFunction::isGenerator()
3424    Returns whether this function is a generator */
3425 ZEND_METHOD(reflection_function, isGenerator)
3426 {
3427         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_GENERATOR);
3428 }
3429 /* }}} */
3430 
3431 /* {{{ proto public bool ReflectionFunction::isVariadic()
3432    Returns whether this function is variadic */
3433 ZEND_METHOD(reflection_function, isVariadic)
3434 {
3435         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_VARIADIC);
3436 }
3437 /* }}} */
3438 
3439 /* {{{ proto public bool ReflectionFunction::inNamespace()
3440    Returns whether this function is defined in namespace */
3441 ZEND_METHOD(reflection_function, inNamespace)
3442 {
3443         zval *name;
3444         const char *backslash;
3445 
3446         if (zend_parse_parameters_none() == FAILURE) {
3447                 return;
3448         }
3449         if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1)) == NULL) {
3450                 RETURN_FALSE;
3451         }
3452         if (Z_TYPE_P(name) == IS_STRING
3453                 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3454                 && backslash > Z_STRVAL_P(name))
3455         {
3456                 RETURN_TRUE;
3457         }
3458         RETURN_FALSE;
3459 }
3460 /* }}} */
3461 
3462 /* {{{ proto public string ReflectionFunction::getNamespaceName()
3463    Returns the name of namespace where this function is defined */
3464 ZEND_METHOD(reflection_function, getNamespaceName)
3465 {
3466         zval *name;
3467         const char *backslash;
3468 
3469         if (zend_parse_parameters_none() == FAILURE) {
3470                 return;
3471         }
3472         if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1)) == NULL) {
3473                 RETURN_FALSE;
3474         }
3475         if (Z_TYPE_P(name) == IS_STRING
3476                 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3477                 && backslash > Z_STRVAL_P(name))
3478         {
3479                 RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
3480         }
3481         RETURN_EMPTY_STRING();
3482 }
3483 /* }}} */
3484 
3485 /* {{{ proto public string ReflectionFunction::getShortName()
3486    Returns the short name of the function (without namespace part) */
3487 ZEND_METHOD(reflection_function, getShortName)
3488 {
3489         zval *name;
3490         const char *backslash;
3491 
3492         if (zend_parse_parameters_none() == FAILURE) {
3493                 return;
3494         }
3495         if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1)) == NULL) {
3496                 RETURN_FALSE;
3497         }
3498         if (Z_TYPE_P(name) == IS_STRING
3499                 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
3500                 && backslash > Z_STRVAL_P(name))
3501         {
3502                 RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
3503         }
3504         ZVAL_DEREF(name);
3505         ZVAL_COPY(return_value, name);
3506 }
3507 /* }}} */
3508 
3509 /* {{{ proto public bool ReflectionFunctionAbstract:hasReturnType()
3510    Return whether the function has a return type */
3511 ZEND_METHOD(reflection_function, hasReturnType)
3512 {
3513         reflection_object *intern;
3514         zend_function *fptr;
3515 
3516         if (zend_parse_parameters_none() == FAILURE) {
3517                 return;
3518         }
3519 
3520         GET_REFLECTION_OBJECT_PTR(fptr);
3521 
3522         RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
3523 }
3524 /* }}} */
3525 
3526 /* {{{ proto public string ReflectionFunctionAbstract::getReturnType()
3527    Returns the return type associated with the function */
3528 ZEND_METHOD(reflection_function, getReturnType)
3529 {
3530         reflection_object *intern;
3531         zend_function *fptr;
3532 
3533         if (zend_parse_parameters_none() == FAILURE) {
3534                 return;
3535         }
3536 
3537         GET_REFLECTION_OBJECT_PTR(fptr);
3538 
3539         if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
3540                 RETURN_NULL();
3541         }
3542 
3543         reflection_type_factory(_copy_function(fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, &fptr->common.arg_info[-1], return_value);
3544 }
3545 /* }}} */
3546 
3547 /* {{{ proto public bool ReflectionMethod::isConstructor()
3548    Returns whether this method is the constructor */
3549 ZEND_METHOD(reflection_method, isConstructor)
3550 {
3551         reflection_object *intern;
3552         zend_function *mptr;
3553 
3554         if (zend_parse_parameters_none() == FAILURE) {
3555                 return;
3556         }
3557         GET_REFLECTION_OBJECT_PTR(mptr);
3558         /* we need to check if the ctor is the ctor of the class level we we
3559          * looking at since we might be looking at an inherited old style ctor
3560          * defined in base class. */
3561         RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
3562 }
3563 /* }}} */
3564 
3565 /* {{{ proto public bool ReflectionMethod::isDestructor()
3566    Returns whether this method is static */
3567 ZEND_METHOD(reflection_method, isDestructor)
3568 {
3569         reflection_object *intern;
3570         zend_function *mptr;
3571 
3572         if (zend_parse_parameters_none() == FAILURE) {
3573                 return;
3574         }
3575         GET_REFLECTION_OBJECT_PTR(mptr);
3576         RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
3577 }
3578 /* }}} */
3579 
3580 /* {{{ proto public int ReflectionMethod::getModifiers()
3581    Returns a bitfield of the access modifiers for this method */
3582 ZEND_METHOD(reflection_method, getModifiers)
3583 {
3584         reflection_object *intern;
3585         zend_function *mptr;
3586 
3587         if (zend_parse_parameters_none() == FAILURE) {
3588                 return;
3589         }
3590         GET_REFLECTION_OBJECT_PTR(mptr);
3591 
3592         RETURN_LONG(mptr->common.fn_flags);
3593 }
3594 /* }}} */
3595 
3596 /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
3597    Get the declaring class */
3598 ZEND_METHOD(reflection_method, getDeclaringClass)
3599 {
3600         reflection_object *intern;
3601         zend_function *mptr;
3602 
3603         METHOD_NOTSTATIC(reflection_method_ptr);
3604         GET_REFLECTION_OBJECT_PTR(mptr);
3605 
3606         if (zend_parse_parameters_none() == FAILURE) {
3607                 return;
3608         }
3609 
3610         zend_reflection_class_factory(mptr->common.scope, return_value);
3611 }
3612 /* }}} */
3613 
3614 /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
3615    Get the prototype */
3616 ZEND_METHOD(reflection_method, getPrototype)
3617 {
3618         reflection_object *intern;
3619         zend_function *mptr;
3620 
3621         METHOD_NOTSTATIC(reflection_method_ptr);
3622         GET_REFLECTION_OBJECT_PTR(mptr);
3623 
3624         if (zend_parse_parameters_none() == FAILURE) {
3625                 return;
3626         }
3627 
3628         if (!mptr->common.prototype) {
3629                 zend_throw_exception_ex(reflection_exception_ptr, 0,
3630                         "Method %s::%s does not have a prototype", ZSTR_VAL(intern->ce->name), ZSTR_VAL(mptr->common.function_name));
3631                 return;
3632         }
3633 
3634         reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value);
3635 }
3636 /* }}} */
3637 
3638 /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
3639    Sets whether non-public methods can be invoked */
3640 ZEND_METHOD(reflection_method, setAccessible)
3641 {
3642         reflection_object *intern;
3643         zend_bool visible;
3644 
3645         if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
3646                 return;
3647         }
3648 
3649         intern = Z_REFLECTION_P(getThis());
3650 
3651         intern->ignore_visibility = visible;
3652 }
3653 /* }}} */
3654 
3655 /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
3656    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
3657 ZEND_METHOD(reflection_class, export)
3658 {
3659         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
3660 }
3661 /* }}} */
3662 
3663 /* {{{ reflection_class_object_ctor */
3664 static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
3665 {
3666         zval *argument;
3667         zval *object;
3668         zval classname;
3669         reflection_object *intern;
3670         zend_class_entry *ce;
3671 
3672         if (is_object) {
3673                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &argument) == FAILURE) {
3674                         return;
3675                 }
3676         } else {
3677                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/", &argument) == FAILURE) {
3678                         return;
3679                 }
3680         }
3681 
3682         object = getThis();
3683         intern = Z_REFLECTION_P(object);
3684 
3685         if (Z_TYPE_P(argument) == IS_OBJECT) {
3686                 ZVAL_STR_COPY(&classname, Z_OBJCE_P(argument)->name);
3687                 reflection_update_property(object, "name", &classname);
3688                 intern->ptr = Z_OBJCE_P(argument);
3689                 if (is_object) {
3690                         ZVAL_COPY_VALUE(&intern->obj, argument);
3691                         zval_add_ref(argument);
3692                 }
3693         } else {
3694                 convert_to_string_ex(argument);
3695                 if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
3696                         if (!EG(exception)) {
3697                                 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", Z_STRVAL_P(argument));
3698                         }
3699                         return;
3700                 }
3701 
3702                 ZVAL_STR_COPY(&classname, ce->name);
3703                 reflection_update_property(object, "name", &classname);
3704 
3705                 intern->ptr = ce;
3706         }
3707         intern->ref_type = REF_TYPE_OTHER;
3708 }
3709 /* }}} */
3710 
3711 /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
3712    Constructor. Takes a string or an instance as an argument */
3713 ZEND_METHOD(reflection_class, __construct)
3714 {
3715         reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3716 }
3717 /* }}} */
3718 
3719 /* {{{ add_class_vars */
3720 static void add_class_vars(zend_class_entry *ce, int statics, zval *return_value)
3721 {
3722         zend_property_info *prop_info;
3723         zval *prop, prop_copy;
3724         zend_string *key;
3725 
3726         ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->properties_info, key, prop_info) {
3727                 if (((prop_info->flags & ZEND_ACC_SHADOW) &&
3728                      prop_info->ce != ce) ||
3729                     ((prop_info->flags & ZEND_ACC_PROTECTED) &&
3730                      !zend_check_protected(prop_info->ce, ce)) ||
3731                     ((prop_info->flags & ZEND_ACC_PRIVATE) &&
3732                      prop_info->ce != ce)) {
3733                         continue;
3734                 }
3735                 prop = NULL;
3736                 if (statics && (prop_info->flags & ZEND_ACC_STATIC) != 0) {
3737                         prop = &ce->default_static_members_table[prop_info->offset];
3738                 } else if (!statics && (prop_info->flags & ZEND_ACC_STATIC) == 0) {
3739                         prop = &ce->default_properties_table[OBJ_PROP_TO_NUM(prop_info->offset)];
3740                 }
3741                 if (!prop) {
3742                         continue;
3743                 }
3744 
3745                 /* copy: enforce read only access */
3746                 ZVAL_DEREF(prop);
3747                 ZVAL_DUP(&prop_copy, prop);
3748 
3749                 /* this is necessary to make it able to work with default array
3750                 * properties, returned to user */
3751                 if (Z_CONSTANT(prop_copy)) {
3752                         if (UNEXPECTED(zval_update_constant_ex(&prop_copy, 1, NULL) != SUCCESS)) {
3753                                 return;
3754                         }
3755                 }
3756 
3757                 zend_hash_update(Z_ARRVAL_P(return_value), key, &prop_copy);
3758         } ZEND_HASH_FOREACH_END();
3759 }
3760 /* }}} */
3761 
3762 /* {{{ proto public array ReflectionClass::getStaticProperties()
3763    Returns an associative array containing all static property values of the class */
3764 ZEND_METHOD(reflection_class, getStaticProperties)
3765 {
3766         reflection_object *intern;
3767         zend_class_entry *ce;
3768 
3769         if (zend_parse_parameters_none() == FAILURE) {
3770                 return;
3771         }
3772 
3773         GET_REFLECTION_OBJECT_PTR(ce);
3774 
3775         if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3776                 return;
3777         }
3778 
3779         array_init(return_value);
3780         add_class_vars(ce, 1, return_value);
3781 }
3782 /* }}} */
3783 
3784 /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
3785    Returns the value of a static property */
3786 ZEND_METHOD(reflection_class, getStaticPropertyValue)
3787 {
3788         reflection_object *intern;
3789         zend_class_entry *ce;
3790         zend_string *name;
3791         zval *prop, *def_value = NULL;
3792 
3793         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|z", &name, &def_value) == FAILURE) {
3794                 return;
3795         }
3796 
3797         GET_REFLECTION_OBJECT_PTR(ce);
3798 
3799         if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3800                 return;
3801         }
3802         prop = zend_std_get_static_property(ce, name, 1);
3803         if (!prop) {
3804                 if (def_value) {
3805                         ZVAL_COPY(return_value, def_value);
3806                 } else {
3807                         zend_throw_exception_ex(reflection_exception_ptr, 0,
3808                                 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3809                 }
3810                 return;
3811         } else {
3812                 ZVAL_DEREF(prop);
3813                 ZVAL_COPY(return_value, prop);
3814         }
3815 }
3816 /* }}} */
3817 
3818 /* {{{ proto public void ReflectionClass::setStaticPropertyValue(string $name, mixed $value)
3819    Sets the value of a static property */
3820 ZEND_METHOD(reflection_class, setStaticPropertyValue)
3821 {
3822         reflection_object *intern;
3823         zend_class_entry *ce;
3824         zend_string *name;
3825         zval *variable_ptr, *value;
3826 
3827         if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sz", &name, &value) == FAILURE) {
3828                 return;
3829         }
3830 
3831         GET_REFLECTION_OBJECT_PTR(ce);
3832 
3833         if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3834                 return;
3835         }
3836         variable_ptr = zend_std_get_static_property(ce, name, 1);
3837         if (!variable_ptr) {
3838                 zend_throw_exception_ex(reflection_exception_ptr, 0,
3839                                 "Class %s does not have a property named %s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
3840                 return;
3841         }
3842         ZVAL_DEREF(variable_ptr);
3843         zval_ptr_dtor(variable_ptr);
3844         ZVAL_COPY(variable_ptr, value);
3845 }
3846 /* }}} */
3847 
3848 /* {{{ proto public array ReflectionClass::getDefaultProperties()
3849    Returns an associative array containing copies of all default property values of the class */
3850 ZEND_METHOD(reflection_class, getDefaultProperties)
3851 {
3852         reflection_object *intern;
3853         zend_class_entry *ce;
3854 
3855         if (zend_parse_parameters_none() == FAILURE) {
3856                 return;
3857         }
3858         GET_REFLECTION_OBJECT_PTR(ce);
3859         array_init(return_value);
3860         if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
3861                 return;
3862         }
3863         add_class_vars(ce, 1, return_value);
3864         add_class_vars(ce, 0, return_value);
3865 }
3866 /* }}} */
3867 
3868 /* {{{ proto public string ReflectionClass::__toString()
3869    Returns a string representation */
3870 ZEND_METHOD(reflection_class, __toString)
3871 {
3872         reflection_object *intern;
3873         zend_class_entry *ce;
3874         string str;
3875 
3876         if (zend_parse_parameters_none() == FAILURE) {
3877                 return;
3878         }
3879         GET_REFLECTION_OBJECT_PTR(ce);
3880         string_init(&str);
3881         _class_string(&str, ce, &intern->obj, "");
3882         RETURN_NEW_STR(str.buf);
3883 }
3884 /* }}} */
3885 
3886 /* {{{ proto public string ReflectionClass::getName()
3887    Returns the class' name */
3888 ZEND_METHOD(reflection_class, getName)
3889 {
3890         if (zend_parse_parameters_none() == FAILURE) {
3891                 return;
3892         }
3893         _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
3894 }
3895 /* }}} */
3896 
3897 /* {{{ proto public bool ReflectionClass::isInternal()
3898    Returns whether this class is an internal class */
3899 ZEND_METHOD(reflection_class, isInternal)
3900 {
3901         reflection_object *intern;
3902         zend_class_entry *ce;
3903 
3904         if (zend_parse_parameters_none() == FAILURE) {
3905                 return;
3906         }
3907         GET_REFLECTION_OBJECT_PTR(ce);
3908         RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
3909 }
3910 /* }}} */
3911 
3912 /* {{{ proto public bool ReflectionClass::isUserDefined()
3913    Returns whether this class is user-defined */
3914 ZEND_METHOD(reflection_class, isUserDefined)
3915 {
3916         reflection_object *intern;
3917         zend_class_entry *ce;
3918 
3919         if (zend_parse_parameters_none() == FAILURE) {
3920                 return;
3921         }
3922         GET_REFLECTION_OBJECT_PTR(ce);
3923         RETURN_BOOL(ce->type == ZEND_USER_CLASS);
3924 }
3925 /* }}} */
3926 
3927 /* {{{ proto public bool ReflectionClass::isAnonymous()
3928    Returns whether this class is anonymous */
3929 ZEND_METHOD(reflection_class, isAnonymous)
3930 {
3931         reflection_object *intern;
3932         zend_class_entry *ce;
3933 
3934         if (zend_parse_parameters_none() == FAILURE) {
3935                 return;
3936         }
3937         GET_REFLECTION_OBJECT_PTR(ce);
3938         RETURN_BOOL(ce->ce_flags & ZEND_ACC_ANON_CLASS);
3939 }
3940 /* }}} */
3941 
3942 /* {{{ proto public string ReflectionClass::getFileName()
3943    Returns the filename of the file this class was declared in */
3944 ZEND_METHOD(reflection_class, getFileName)
3945 {
3946         reflection_object *intern;
3947         zend_class_entry *ce;
3948 
3949         if (zend_parse_parameters_none() == FAILURE) {
3950                 return;
3951         }
3952         GET_REFLECTION_OBJECT_PTR(ce);
3953         if (ce->type == ZEND_USER_CLASS) {
3954                 RETURN_STR_COPY(ce->info.user.filename);
3955         }
3956         RETURN_FALSE;
3957 }
3958 /* }}} */
3959 
3960 /* {{{ proto public int ReflectionClass::getStartLine()
3961    Returns the line this class' declaration starts at */
3962 ZEND_METHOD(reflection_class, getStartLine)
3963 {
3964         reflection_object *intern;
3965         zend_class_entry *ce;
3966 
3967         if (zend_parse_parameters_none() == FAILURE) {
3968                 return;
3969         }
3970         GET_REFLECTION_OBJECT_PTR(ce);
3971         if (ce->type == ZEND_USER_FUNCTION) {
3972                 RETURN_LONG(ce->info.user.line_start);
3973         }
3974         RETURN_FALSE;
3975 }
3976 /* }}} */
3977 
3978 /* {{{ proto public int ReflectionClass::getEndLine()
3979    Returns the line this class' declaration ends at */
3980 ZEND_METHOD(reflection_class, getEndLine)
3981 {
3982         reflection_object *intern;
3983         zend_class_entry *ce;
3984 
3985         if (zend_parse_parameters_none() == FAILURE) {
3986                 return;
3987         }
3988         GET_REFLECTION_OBJECT_PTR(ce);
3989         if (ce->type == ZEND_USER_CLASS) {
3990                 RETURN_LONG(ce->info.user.line_end);
3991         }
3992         RETURN_FALSE;
3993 }
3994 /* }}} */
3995 
3996 /* {{{ proto public string ReflectionClass::getDocComment()
3997    Returns the doc comment for this class */
3998 ZEND_METHOD(reflection_class, getDocComment)
3999 {
4000         reflection_object *intern;
4001         zend_class_entry *ce;
4002 
4003         if (zend_parse_parameters_none() == FAILURE) {
4004                 return;
4005         }
4006         GET_REFLECTION_OBJECT_PTR(ce);
4007         if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) {
4008                 RETURN_STR_COPY(ce->info.user.doc_comment);
4009         }
4010         RETURN_FALSE;
4011 }
4012 /* }}} */
4013 
4014 /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
4015    Returns the class' constructor if there is one, NULL otherwise */
4016 ZEND_METHOD(reflection_class, getConstructor)
4017 {
4018         reflection_object *intern;
4019         zend_class_entry *ce;
4020 
4021         if (zend_parse_parameters_none() == FAILURE) {
4022                 return;
4023         }
4024         GET_REFLECTION_OBJECT_PTR(ce);
4025 
4026         if (ce->constructor) {
4027                 reflection_method_factory(ce, ce->constructor, NULL, return_value);
4028         } else {
4029                 RETURN_NULL();
4030         }
4031 }
4032 /* }}} */
4033 
4034 /* {{{ proto public bool ReflectionClass::hasMethod(string name)
4035    Returns whether a method exists or not */
4036 ZEND_METHOD(reflection_class, hasMethod)
4037 {
4038         reflection_object *intern;
4039         zend_class_entry *ce;
4040         char *name, *lc_name;
4041         size_t name_len;
4042 
4043         METHOD_NOTSTATIC(reflection_class_ptr);
4044         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
4045                 return;
4046         }
4047 
4048         GET_REFLECTION_OBJECT_PTR(ce);
4049         lc_name = zend_str_tolower_dup(name, name_len);
4050         if ((ce == zend_ce_closure && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4051                 && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0)
4052                 || zend_hash_str_exists(&ce->function_table, lc_name, name_len)) {
4053                 efree(lc_name);
4054                 RETURN_TRUE;
4055         } else {
4056                 efree(lc_name);
4057                 RETURN_FALSE;
4058         }
4059 }
4060 /* }}} */
4061 
4062 /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
4063    Returns the class' method specified by its name */
4064 ZEND_METHOD(reflection_class, getMethod)
4065 {
4066         reflection_object *intern;
4067         zend_class_entry *ce;
4068         zend_function *mptr;
4069         zval obj_tmp;
4070         char *name, *lc_name;
4071         size_t name_len;
4072 
4073         METHOD_NOTSTATIC(reflection_class_ptr);
4074         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
4075                 return;
4076         }
4077 
4078         GET_REFLECTION_OBJECT_PTR(ce);
4079         lc_name = zend_str_tolower_dup(name, name_len);
4080         if (ce == zend_ce_closure && !Z_ISUNDEF(intern->obj) && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4081                 && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
4082                 && (mptr = zend_get_closure_invoke_method(Z_OBJ(intern->obj))) != NULL)
4083         {
4084                 /* don't assign closure_object since we only reflect the invoke handler
4085                    method and not the closure definition itself */
4086                 reflection_method_factory(ce, mptr, NULL, return_value);
4087                 efree(lc_name);
4088         } else if (ce == zend_ce_closure && Z_ISUNDEF(intern->obj) && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4089                 && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
4090                 && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(Z_OBJ(obj_tmp))) != NULL) {
4091                 /* don't assign closure_object since we only reflect the invoke handler
4092                    method and not the closure definition itself */
4093                 reflection_method_factory(ce, mptr, NULL, return_value);
4094                 zval_dtor(&obj_tmp);
4095                 efree(lc_name);
4096         } else if ((mptr = zend_hash_str_find_ptr(&ce->function_table, lc_name, name_len)) != NULL) {
4097                 reflection_method_factory(ce, mptr, NULL, return_value);
4098                 efree(lc_name);
4099         } else {
4100                 efree(lc_name);
4101                 zend_throw_exception_ex(reflection_exception_ptr, 0,
4102                                 "Method %s does not exist", name);
4103                 return;
4104         }
4105 }
4106 /* }}} */
4107 
4108 /* {{{ _addmethod */
4109 static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, zend_long filter, zval *obj)
4110 {
4111         zval method;
4112         size_t len = ZSTR_LEN(mptr->common.function_name);
4113         zend_function *closure;
4114         if (mptr->common.fn_flags & filter) {
4115                 if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
4116                         && memcmp(ZSTR_VAL(mptr->common.function_name), ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
4117                         && (closure = zend_get_closure_invoke_method(Z_OBJ_P(obj))) != NULL)
4118                 {
4119                         mptr = closure;
4120                 }
4121                 /* don't assign closure_object since we only reflect the invoke handler
4122                    method and not the closure definition itself, even if we have a
4123                    closure */
4124                 reflection_method_factory(ce, mptr, NULL, &method);
4125                 add_next_index_zval(retval, &method);
4126         }
4127 }
4128 /* }}} */
4129 
4130 /* {{{ _addmethod */
4131 static int _addmethod_va(zval *el, int num_args, va_list args, zend_hash_key *hash_key)
4132 {
4133         zend_function *mptr = (zend_function*)Z_PTR_P(el);
4134         zend_class_entry *ce = *va_arg(args, zend_class_entry**);
4135         zval *retval = va_arg(args, zval*);
4136         long filter = va_arg(args, long);
4137         zval *obj = va_arg(args, zval *);
4138 
4139         _addmethod(mptr, ce, retval, filter, obj);
4140         return ZEND_HASH_APPLY_KEEP;
4141 }
4142 /* }}} */
4143 
4144 /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
4145    Returns an array of this class' methods */
4146 ZEND_METHOD(reflection_class, getMethods)
4147 {
4148         reflection_object *intern;
4149         zend_class_entry *ce;
4150         zend_long filter = 0;
4151         int argc = ZEND_NUM_ARGS();
4152 
4153         METHOD_NOTSTATIC(reflection_class_ptr);
4154         if (argc) {
4155                 if (zend_parse_parameters(argc, "|l", &filter) == FAILURE) {
4156                         return;
4157                 }
4158         } else {
4159                 /* No parameters given, default to "return all" */
4160                 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
4161         }
4162 
4163         GET_REFLECTION_OBJECT_PTR(ce);
4164 
4165         array_init(return_value);
4166         zend_hash_apply_with_arguments(&ce->function_table, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter, intern->obj);
4167         if (Z_TYPE(intern->obj) != IS_UNDEF && instanceof_function(ce, zend_ce_closure)) {
4168                 zend_function *closure = zend_get_closure_invoke_method(Z_OBJ(intern->obj));
4169                 if (closure) {
4170                         _addmethod(closure, ce, return_value, filter, &intern->obj);
4171                         _free_function(closure);
4172                 }
4173         }
4174 }
4175 /* }}} */
4176 
4177 /* {{{ proto public bool ReflectionClass::hasProperty(string name)
4178    Returns whether a property exists or not */
4179 ZEND_METHOD(reflection_class, hasProperty)
4180 {
4181         reflection_object *intern;
4182         zend_property_info *property_info;
4183         zend_class_entry *ce;
4184         zend_string *name;
4185         zval property;
4186 
4187         METHOD_NOTSTATIC(reflection_class_ptr);
4188         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4189                 return;
4190         }
4191 
4192         GET_REFLECTION_OBJECT_PTR(ce);
4193         if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4194                 if (property_info->flags & ZEND_ACC_SHADOW) {
4195                         RETURN_FALSE;
4196                 }
4197                 RETURN_TRUE;
4198         } else {
4199                 if (Z_TYPE(intern->obj) != IS_UNDEF && Z_OBJ_HANDLER(intern->obj, has_property)) {
4200                         ZVAL_STR_COPY(&property, name);
4201                         if (Z_OBJ_HANDLER(intern->obj, has_property)(&intern->obj, &property, 2, NULL)) {
4202                                 zval_ptr_dtor(&property);
4203                                 RETURN_TRUE;
4204                         }
4205                         zval_ptr_dtor(&property);
4206                 }
4207                 RETURN_FALSE;
4208         }
4209 }
4210 /* }}} */
4211 
4212 /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
4213    Returns the class' property specified by its name */
4214 ZEND_METHOD(reflection_class, getProperty)
4215 {
4216         reflection_object *intern;
4217         zend_class_entry *ce, *ce2;
4218         zend_property_info *property_info;
4219         zend_string *name, *classname;
4220         char *tmp, *str_name;
4221         size_t classname_len, str_name_len;
4222 
4223         METHOD_NOTSTATIC(reflection_class_ptr);
4224         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4225                 return;
4226         }
4227 
4228         GET_REFLECTION_OBJECT_PTR(ce);
4229         if ((property_info = zend_hash_find_ptr(&ce->properties_info, name)) != NULL) {
4230                 if ((property_info->flags & ZEND_ACC_SHADOW) == 0) {
4231                         reflection_property_factory(ce, property_info, return_value);
4232                         return;
4233                 }
4234         } else if (Z_TYPE(intern->obj) != IS_UNDEF) {
4235                 /* Check for dynamic properties */
4236                 if (zend_hash_exists(Z_OBJ_HT(intern->obj)->get_properties(&intern->obj), name)) {
4237                         zend_property_info property_info_tmp;
4238                         property_info_tmp.flags = ZEND_ACC_IMPLICIT_PUBLIC;
4239                         property_info_tmp.name = zend_string_copy(name);
4240                         property_info_tmp.doc_comment = NULL;
4241                         property_info_tmp.ce = ce;
4242 
4243                         reflection_property_factory(ce, &property_info_tmp, return_value);
4244                         intern = Z_REFLECTION_P(return_value);
4245                         intern->ref_type = REF_TYPE_DYNAMIC_PROPERTY;
4246                         return;
4247                 }
4248         }
4249         str_name = ZSTR_VAL(name);
4250         str_name_len = ZSTR_LEN(name);
4251         if ((tmp = strstr(ZSTR_VAL(name), "::")) != NULL) {
4252                 classname_len = tmp - ZSTR_VAL(name);
4253                 classname = zend_string_alloc(classname_len, 0);
4254                 zend_str_tolower_copy(ZSTR_VAL(classname), ZSTR_VAL(name), classname_len);
4255                 ZSTR_VAL(classname)[classname_len] = '\0';
4256                 str_name_len = ZSTR_LEN(name) - (classname_len + 2);
4257                 str_name = tmp + 2;
4258 
4259                 ce2 = zend_lookup_class(classname);
4260                 if (!ce2) {
4261                         if (!EG(exception)) {
4262                                 zend_throw_exception_ex(reflection_exception_ptr, -1, "Class %s does not exist", ZSTR_VAL(classname));
4263                         }
4264                         zend_string_release(classname);
4265                         return;
4266                 }
4267                 zend_string_release(classname);
4268 
4269                 if (!instanceof_function(ce, ce2)) {
4270                         zend_throw_exception_ex(reflection_exception_ptr, -1, "Fully qualified property name %s::%s does not specify a base class of %s", ZSTR_VAL(ce2->name), str_name, ZSTR_VAL(ce->name));
4271                         return;
4272                 }
4273                 ce = ce2;
4274 
4275                 if ((property_info = zend_hash_str_find_ptr(&ce->properties_info, str_name, str_name_len)) != NULL && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
4276                         reflection_property_factory(ce, property_info, return_value);
4277                         return;
4278                 }
4279         }
4280         zend_throw_exception_ex(reflection_exception_ptr, 0,
4281                         "Property %s does not exist", str_name);
4282 }
4283 /* }}} */
4284 
4285 /* {{{ _addproperty */
4286 static int _addproperty(zval *el, int num_args, va_list args, zend_hash_key *hash_key)
4287 {
4288         zval property;
4289         zend_property_info *pptr = (zend_property_info*)Z_PTR_P(el);
4290         zend_class_entry *ce = *va_arg(args, zend_class_entry**);
4291         zval *retval = va_arg(args, zval*);
4292         long filter = va_arg(args, long);
4293 
4294         if (pptr->flags & ZEND_ACC_SHADOW) {
4295                 return 0;
4296         }
4297 
4298         if (pptr->flags & filter) {
4299                 reflection_property_factory(ce, pptr, &property);
4300                 add_next_index_zval(retval, &property);
4301         }
4302         return 0;
4303 }
4304 /* }}} */
4305 
4306 /* {{{ _adddynproperty */
4307 static int _adddynproperty(zval *ptr, int num_args, va_list args, zend_hash_key *hash_key)
4308 {
4309         zval property;
4310         zend_class_entry *ce = *va_arg(args, zend_class_entry**);
4311         zval *retval = va_arg(args, zval*);
4312 
4313         /* under some circumstances, the properties hash table may contain numeric
4314          * properties (e.g. when casting from array). This is a WONT FIX bug, at
4315          * least for the moment. Ignore these */
4316         if (hash_key->key == NULL) {
4317                 return 0;
4318         }
4319 
4320         if (ZSTR_VAL(hash_key->key)[0] == '\0') {
4321                 return 0; /* non public cannot be dynamic */
4322         }
4323 
4324         if (zend_get_property_info(ce, hash_key->key, 1) == NULL) {
4325                 zend_property_info property_info;
4326 
4327                 property_info.doc_comment = NULL;
4328                 property_info.flags = ZEND_ACC_IMPLICIT_PUBLIC;
4329                 property_info.name = hash_key->key;
4330                 property_info.ce = ce;
4331                 property_info.offset = -1;
4332                 reflection_property_factory(ce, &property_info, &property);
4333                 add_next_index_zval(retval, &property);
4334         }
4335         return 0;
4336 }
4337 /* }}} */
4338 
4339 /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
4340    Returns an array of this class' properties */
4341 ZEND_METHOD(reflection_class, getProperties)
4342 {
4343         reflection_object *intern;
4344         zend_class_entry *ce;
4345         zend_long filter = 0;
4346         int argc = ZEND_NUM_ARGS();
4347 
4348         METHOD_NOTSTATIC(reflection_class_ptr);
4349         if (argc) {
4350                 if (zend_parse_parameters(argc, "|l", &filter) == FAILURE) {
4351                         return;
4352                 }
4353         } else {
4354                 /* No parameters given, default to "return all" */
4355                 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
4356         }
4357 
4358         GET_REFLECTION_OBJECT_PTR(ce);
4359 
4360         array_init(return_value);
4361         zend_hash_apply_with_arguments(&ce->properties_info, (apply_func_args_t) _addproperty, 3, &ce, return_value, filter);
4362 
4363         if (Z_TYPE(intern->obj) != IS_UNDEF && (filter & ZEND_ACC_PUBLIC) != 0 && Z_OBJ_HT(intern->obj)->get_properties) {
4364                 HashTable *properties = Z_OBJ_HT(intern->obj)->get_properties(&intern->obj);
4365                 zend_hash_apply_with_arguments(properties, (apply_func_args_t) _adddynproperty, 2, &ce, return_value);
4366         }
4367 }
4368 /* }}} */
4369 
4370 /* {{{ proto public bool ReflectionClass::hasConstant(string name)
4371    Returns whether a constant exists or not */
4372 ZEND_METHOD(reflection_class, hasConstant)
4373 {
4374         reflection_object *intern;
4375         zend_class_entry *ce;
4376         zend_string *name;
4377 
4378         METHOD_NOTSTATIC(reflection_class_ptr);
4379         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4380                 return;
4381         }
4382 
4383         GET_REFLECTION_OBJECT_PTR(ce);
4384         if (zend_hash_exists(&ce->constants_table, name)) {
4385                 RETURN_TRUE;
4386         } else {
4387                 RETURN_FALSE;
4388         }
4389 }
4390 /* }}} */
4391 
4392 /* {{{ proto public array ReflectionClass::getConstants()
4393    Returns an associative array containing this class' constants and their values */
4394 ZEND_METHOD(reflection_class, getConstants)
4395 {
4396         reflection_object *intern;
4397         zend_class_entry *ce;
4398         zval *val;
4399 
4400         if (zend_parse_parameters_none() == FAILURE) {
4401                 return;
4402         }
4403         GET_REFLECTION_OBJECT_PTR(ce);
4404         array_init(return_value);
4405         ZEND_HASH_FOREACH_VAL(&ce->constants_table, val) {
4406                 if (UNEXPECTED(zval_update_constant_ex(val, 1, ce) != SUCCESS)) {
4407                         return;
4408                 }
4409         } ZEND_HASH_FOREACH_END();
4410         zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref_unref);
4411 }
4412 /* }}} */
4413 
4414 /* {{{ proto public mixed ReflectionClass::getConstant(string name)
4415    Returns the class' constant specified by its name */
4416 ZEND_METHOD(reflection_class, getConstant)
4417 {
4418         reflection_object *intern;
4419         zend_class_entry *ce;
4420         zval *value;
4421         zend_string *name;
4422 
4423         METHOD_NOTSTATIC(reflection_class_ptr);
4424         if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
4425                 return;
4426         }
4427 
4428         GET_REFLECTION_OBJECT_PTR(ce);
4429         ZEND_HASH_FOREACH_VAL(&ce->constants_table, value) {
4430                 if (UNEXPECTED(zval_update_constant_ex(value, 1, ce) != SUCCESS)) {
4431                         return;
4432                 }
4433         } ZEND_HASH_FOREACH_END();
4434         if ((value = zend_hash_find(&ce->constants_table, name)) == NULL) {
4435                 RETURN_FALSE;
4436         }
4437         ZVAL_DUP(return_value, value);
4438 }
4439 /* }}} */
4440 
4441 /* {{{ _class_check_flag */
4442 static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
4443 {
4444         reflection_object *intern;
4445         zend_class_entry *ce;
4446 
4447         if (zend_parse_parameters_none() == FAILURE) {
4448                 return;
4449         }
4450         GET_REFLECTION_OBJECT_PTR(ce);
4451         RETVAL_BOOL(ce->ce_flags & mask);
4452 }
4453 /* }}} */
4454 
4455 /* {{{ proto public bool ReflectionClass::isInstantiable()
4456    Returns whether this class is instantiable */
4457 ZEND_METHOD(reflection_class, isInstantiable)
4458 {
4459         reflection_object *intern;
4460         zend_class_entry *ce;
4461 
4462         if (zend_parse_parameters_none() == FAILURE) {
4463                 return;
4464         }
4465         GET_REFLECTION_OBJECT_PTR(ce);
4466         if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4467                 RETURN_FALSE;
4468         }
4469 
4470         /* Basically, the class is instantiable. Though, if there is a constructor
4471          * and it is not publicly accessible, it isn't! */
4472         if (!ce->constructor) {
4473                 RETURN_TRUE;
4474         }
4475 
4476         RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
4477 }
4478 /* }}} */
4479 
4480 /* {{{ proto public bool ReflectionClass::isCloneable()
4481    Returns whether this class is cloneable */
4482 ZEND_METHOD(reflection_class, isCloneable)
4483 {
4484         reflection_object *intern;
4485         zend_class_entry *ce;
4486         zval obj;
4487 
4488         if (zend_parse_parameters_none() == FAILURE) {
4489                 return;
4490         }
4491         GET_REFLECTION_OBJECT_PTR(ce);
4492         if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
4493                 RETURN_FALSE;
4494         }
4495         if (!Z_ISUNDEF(intern->obj)) {
4496                 if (ce->clone) {
4497                         RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4498                 } else {
4499                         RETURN_BOOL(Z_OBJ_HANDLER(intern->obj, clone_obj) != NULL);
4500                 }
4501         } else {
4502                 if (ce->clone) {
4503                         RETURN_BOOL(ce->clone->common.fn_flags & ZEND_ACC_PUBLIC);
4504                 } else {
4505                         if (UNEXPECTED(object_init_ex(&obj, ce) != SUCCESS)) {
4506                                 return;
4507                         }
4508                         RETVAL_BOOL(Z_OBJ_HANDLER(obj, clone_obj) != NULL);
4509                         zval_dtor(&obj);
4510                 }
4511         }
4512 }
4513 /* }}} */
4514 
4515 /* {{{ proto public bool ReflectionClass::isInterface()
4516    Returns whether this is an interface or a class */
4517 ZEND_METHOD(reflection_class, isInterface)
4518 {
4519         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
4520 }
4521 /* }}} */
4522 
4523 /* {{{ proto public bool ReflectionClass::isTrait()
4524    Returns whether this is a trait */
4525 ZEND_METHOD(reflection_class, isTrait)
4526 {
4527         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_TRAIT);
4528 }
4529 /* }}} */
4530 
4531 /* {{{ proto public bool ReflectionClass::isFinal()
4532    Returns whether this class is final */
4533 ZEND_METHOD(reflection_class, isFinal)
4534 {
4535         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
4536 }
4537 /* }}} */
4538 
4539 /* {{{ proto public bool ReflectionClass::isAbstract()
4540    Returns whether this class is abstract */
4541 ZEND_METHOD(reflection_class, isAbstract)
4542 {
4543         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
4544 }
4545 /* }}} */
4546 
4547 /* {{{ proto public int ReflectionClass::getModifiers()
4548    Returns a bitfield of the access modifiers for this class */
4549 ZEND_METHOD(reflection_class, getModifiers)
4550 {
4551         reflection_object *intern;
4552         zend_class_entry *ce;
4553 
4554         if (zend_parse_parameters_none() == FAILURE) {
4555                 return;
4556         }
4557         GET_REFLECTION_OBJECT_PTR(ce);
4558 
4559         RETURN_LONG(ce->ce_flags & ~(ZEND_ACC_CONSTANTS_UPDATED|ZEND_ACC_USE_GUARDS));
4560 }
4561 /* }}} */
4562 
4563 /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
4564    Returns whether the given object is an instance of this class */
4565 ZEND_METHOD(reflection_class, isInstance)
4566 {
4567         reflection_object *intern;
4568         zend_class_entry *ce;
4569         zval *object;
4570 
4571         METHOD_NOTSTATIC(reflection_class_ptr);
4572         if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
4573                 return;
4574         }
4575         GET_REFLECTION_OBJECT_PTR(ce);
4576         RETURN_BOOL(instanceof_function(Z_OBJCE_P(object), ce));
4577 }
4578 /* }}} */
4579 
4580 /* {{{ proto public stdclass ReflectionClass::newInstance(mixed* args, ...)
4581    Returns an instance of this class */
4582 ZEND_METHOD(reflection_class, newInstance)
4583 {
4584         zval retval;
4585         reflection_object *intern;
4586         zend_class_entry *ce, *old_scope;
4587         zend_function *constructor;
4588 
4589         METHOD_NOTSTATIC(reflection_class_ptr);
4590         GET_REFLECTION_OBJECT_PTR(ce);
4591 
4592         if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4593                 return;
4594         }
4595 
4596         old_scope = EG(scope);
4597         EG(scope) = ce;
4598         constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4599         EG(scope) = old_scope;
4600 
4601         /* Run the constructor if there is one */
4602         if (constructor) {
4603                 zval *params = NULL;
4604                 int ret, i, num_args = 0;
4605                 zend_fcall_info fci;
4606                 zend_fcall_info_cache fcc;
4607 
4608                 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4609                         zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4610                         zval_dtor(return_value);
4611                         RETURN_NULL();
4612                 }
4613 
4614                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &params, &num_args) == FAILURE) {
4615                         zval_dtor(return_value);
4616                         RETURN_FALSE;
4617                 }
4618 
4619                 for (i = 0; i < num_args; i++) {
4620                         if (Z_REFCOUNTED(params[i])) Z_ADDREF(params[i]);
4621                 }
4622 
4623                 fci.size = sizeof(fci);
4624                 fci.function_table = EG(function_table);
4625                 ZVAL_UNDEF(&fci.function_name);
4626                 fci.symbol_table = NULL;
4627                 fci.object = Z_OBJ_P(return_value);
4628                 fci.retval = &retval;
4629                 fci.param_count = num_args;
4630                 fci.params = params;
4631                 fci.no_separation = 1;
4632 
4633                 fcc.initialized = 1;
4634                 fcc.function_handler = constructor;
4635                 fcc.calling_scope = EG(scope);
4636                 fcc.called_scope = Z_OBJCE_P(return_value);
4637                 fcc.object = Z_OBJ_P(return_value);
4638 
4639                 ret = zend_call_function(&fci, &fcc);
4640                 zval_ptr_dtor(&retval);
4641                 for (i = 0; i < num_args; i++) {
4642                         zval_ptr_dtor(&params[i]);
4643                 }
4644                 if (ret == FAILURE) {
4645                         php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4646                         zval_dtor(return_value);
4647                         RETURN_NULL();
4648                 }
4649         } else if (ZEND_NUM_ARGS()) {
4650                 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
4651         }
4652 }
4653 /* }}} */
4654 
4655 /* {{{ proto public stdclass ReflectionClass::newInstanceWithoutConstructor()
4656    Returns an instance of this class without invoking its constructor */
4657 ZEND_METHOD(reflection_class, newInstanceWithoutConstructor)
4658 {
4659         reflection_object *intern;
4660         zend_class_entry *ce;
4661 
4662         METHOD_NOTSTATIC(reflection_class_ptr);
4663         GET_REFLECTION_OBJECT_PTR(ce);
4664 
4665         if (ce->create_object != NULL && ce->ce_flags & ZEND_ACC_FINAL) {
4666                 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s is an internal class marked as final that cannot be instantiated without invoking its constructor", ZSTR_VAL(ce->name));
4667                 return;
4668         }
4669 
4670         object_init_ex(return_value, ce);
4671 }
4672 /* }}} */
4673 
4674 /* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args])
4675    Returns an instance of this class */
4676 ZEND_METHOD(reflection_class, newInstanceArgs)
4677 {
4678         zval retval, *val;
4679         reflection_object *intern;
4680         zend_class_entry *ce, *old_scope;
4681         int ret, i, argc = 0;
4682         HashTable *args;
4683         zend_function *constructor;
4684 
4685 
4686         METHOD_NOTSTATIC(reflection_class_ptr);
4687         GET_REFLECTION_OBJECT_PTR(ce);
4688 
4689         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|h", &args) == FAILURE) {
4690                 return;
4691         }
4692 
4693         if (ZEND_NUM_ARGS() > 0) {
4694                 argc = args->nNumOfElements;
4695         }
4696 
4697         if (UNEXPECTED(object_init_ex(return_value, ce) != SUCCESS)) {
4698                 return;
4699         }
4700 
4701         old_scope = EG(scope);
4702         EG(scope) = ce;
4703         constructor = Z_OBJ_HT_P(return_value)->get_constructor(Z_OBJ_P(return_value));
4704         EG(scope) = old_scope;
4705 
4706         /* Run the constructor if there is one */
4707         if (constructor) {
4708                 zval *params = NULL;
4709                 zend_fcall_info fci;
4710                 zend_fcall_info_cache fcc;
4711 
4712                 if (!(constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
4713                         zend_throw_exception_ex(reflection_exception_ptr, 0, "Access to non-public constructor of class %s", ZSTR_VAL(ce->name));
4714                         zval_dtor(return_value);
4715                         RETURN_NULL();
4716                 }
4717 
4718                 if (argc) {
4719                         params = safe_emalloc(sizeof(zval), argc, 0);
4720                         argc = 0;
4721                         ZEND_HASH_FOREACH_VAL(args, val) {
4722                                 ZVAL_COPY(&params[argc], val);
4723                                 argc++;
4724                         } ZEND_HASH_FOREACH_END();
4725                 }
4726 
4727                 fci.size = sizeof(fci);
4728                 fci.function_table = EG(function_table);
4729                 ZVAL_UNDEF(&fci.function_name);
4730                 fci.symbol_table = NULL;
4731                 fci.object = Z_OBJ_P(return_value);
4732                 fci.retval = &retval;
4733                 fci.param_count = argc;
4734                 fci.params = params;
4735                 fci.no_separation = 1;
4736 
4737                 fcc.initialized = 1;
4738                 fcc.function_handler = constructor;
4739                 fcc.calling_scope = EG(scope);
4740                 fcc.called_scope = Z_OBJCE_P(return_value);
4741                 fcc.object = Z_OBJ_P(return_value);
4742 
4743                 ret = zend_call_function(&fci, &fcc);
4744                 zval_ptr_dtor(&retval);
4745                 if (params) {
4746                         for (i = 0; i < argc; i++) {
4747                                 zval_ptr_dtor(&params[i]);
4748                         }
4749                         efree(params);
4750                 }
4751                 if (ret == FAILURE) {
4752                         zval_ptr_dtor(&retval);
4753                         php_error_docref(NULL, E_WARNING, "Invocation of %s's constructor failed", ZSTR_VAL(ce->name));
4754                         zval_dtor(return_value);
4755                         RETURN_NULL();
4756                 }
4757         } else if (argc) {
4758                 zend_throw_exception_ex(reflection_exception_ptr, 0, "Class %s does not have a constructor, so you cannot pass any constructor arguments", ZSTR_VAL(ce->name));
4759         }
4760 }
4761 /* }}} */
4762 
4763 /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
4764    Returns an array of interfaces this class implements */
4765 ZEND_METHOD(reflection_class, getInterfaces)
4766 {
4767         reflection_object *intern;
4768         zend_class_entry *ce;
4769 
4770         if (zend_parse_parameters_none() == FAILURE) {
4771                 return;
4772         }
4773         GET_REFLECTION_OBJECT_PTR(ce);
4774 
4775         /* Return an empty array if this class implements no interfaces */
4776         array_init(return_value);
4777 
4778         if (ce->num_interfaces) {
4779                 uint32_t i;
4780 
4781                 for (i=0; i < ce->num_interfaces; i++) {
4782                         zval interface;
4783                         zend_reflection_class_factory(ce->interfaces[i], &interface);
4784                         zend_hash_update(Z_ARRVAL_P(return_value), ce->interfaces[i]->name, &interface);
4785                 }
4786         }
4787 }
4788 /* }}} */
4789 
4790 /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
4791    Returns an array of names of interfaces this class implements */
4792 ZEND_METHOD(reflection_class, getInterfaceNames)
4793 {
4794         reflection_object *intern;
4795         zend_class_entry *ce;
4796         uint32_t i;
4797 
4798         if (zend_parse_parameters_none() == FAILURE) {
4799                 return;
4800         }
4801         GET_REFLECTION_OBJECT_PTR(ce);
4802 
4803         /* Return an empty array if this class implements no interfaces */
4804         array_init(return_value);
4805 
4806         for (i=0; i < ce->num_interfaces; i++) {
4807                 add_next_index_str(return_value, zend_string_copy(ce->interfaces[i]->name));
4808         }
4809 }
4810 /* }}} */
4811 
4812 /* {{{ proto public ReflectionClass[] ReflectionClass::getTraits()
4813    Returns an array of traits used by this class */
4814 ZEND_METHOD(reflection_class, getTraits)
4815 {
4816         reflection_object *intern;
4817         zend_class_entry *ce;
4818         uint32_t i;
4819 
4820         if (zend_parse_parameters_none() == FAILURE) {
4821                 return;
4822         }
4823         GET_REFLECTION_OBJECT_PTR(ce);
4824 
4825         array_init(return_value);
4826 
4827         for (i=0; i < ce->num_traits; i++) {
4828                 zval trait;
4829                 zend_reflection_class_factory(ce->traits[i], &trait);
4830                 zend_hash_update(Z_ARRVAL_P(return_value), ce->traits[i]->name, &trait);
4831         }
4832 }
4833 /* }}} */
4834 
4835 /* {{{ proto public String[] ReflectionClass::getTraitNames()
4836    Returns an array of names of traits used by this class */
4837 ZEND_METHOD(reflection_class, getTraitNames)
4838 {
4839         reflection_object *intern;
4840         zend_class_entry *ce;
4841         uint32_t i;
4842 
4843         if (zend_parse_parameters_none() == FAILURE) {
4844                 return;
4845         }
4846         GET_REFLECTION_OBJECT_PTR(ce);
4847 
4848         array_init(return_value);
4849 
4850         for (i=0; i < ce->num_traits; i++) {
4851                 add_next_index_str(return_value, zend_string_copy(ce->traits[i]->name));
4852         }
4853 }
4854 /* }}} */
4855 
4856 /* {{{ proto public arra ReflectionClass::getTraitaliases()
4857    Returns an array of trait aliases */
4858 ZEND_METHOD(reflection_class, getTraitAliases)
4859 {
4860         reflection_object *intern;
4861         zend_class_entry *ce;
4862 
4863         if (zend_parse_parameters_none() == FAILURE) {
4864                 return;
4865         }
4866         GET_REFLECTION_OBJECT_PTR(ce);
4867 
4868         array_init(return_value);
4869 
4870         if (ce->trait_aliases) {
4871                 uint32_t i = 0;
4872                 while (ce->trait_aliases[i]) {
4873                         zend_string *mname;
4874                         zend_trait_method_reference *cur_ref = ce->trait_aliases[i]->trait_method;
4875 
4876                         if (ce->trait_aliases[i]->alias) {
4877 
4878                                 mname = zend_string_alloc(ZSTR_LEN(cur_ref->ce->name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
4879                                 snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->ce->name), ZSTR_VAL(cur_ref->method_name));
4880                                 add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname);
4881                         }
4882                         i++;
4883                 }
4884         }
4885 }
4886 /* }}} */
4887 
4888 /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
4889    Returns the class' parent class, or, if none exists, FALSE */
4890 ZEND_METHOD(reflection_class, getParentClass)
4891 {
4892         reflection_object *intern;
4893         zend_class_entry *ce;
4894 
4895         if (zend_parse_parameters_none() == FAILURE) {
4896                 return;
4897         }
4898         GET_REFLECTION_OBJECT_PTR(ce);
4899 
4900         if (ce->parent) {
4901                 zend_reflection_class_factory(ce->parent, return_value);
4902         } else {
4903                 RETURN_FALSE;
4904         }
4905 }
4906 /* }}} */
4907 
4908 /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
4909    Returns whether this class is a subclass of another class */
4910 ZEND_METHOD(reflection_class, isSubclassOf)
4911 {
4912         reflection_object *intern, *argument;
4913         zend_class_entry *ce, *class_ce;
4914         zval *class_name;
4915 
4916         METHOD_NOTSTATIC(reflection_class_ptr);
4917         GET_REFLECTION_OBJECT_PTR(ce);
4918 
4919         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &class_name) == FAILURE) {
4920                 return;
4921         }
4922 
4923         switch (Z_TYPE_P(class_name)) {
4924                 case IS_STRING:
4925                         if ((class_ce = zend_lookup_class(Z_STR_P(class_name))) == NULL) {
4926                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
4927                                                 "Class %s does not exist", Z_STRVAL_P(class_name));
4928                                 return;
4929                         }
4930                         break;
4931                 case IS_OBJECT:
4932                         if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr)) {
4933                                 argument = Z_REFLECTION_P(class_name);
4934                                 if (argument == NULL || argument->ptr == NULL) {
4935                                         php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
4936                                         /* Bails out */
4937                                 }
4938                                 class_ce = argument->ptr;
4939                                 break;
4940                         }
4941                         /* no break */
4942                 default:
4943                         zend_throw_exception_ex(reflection_exception_ptr, 0,
4944                                         "Parameter one must either be a string or a ReflectionClass object");
4945                         return;
4946         }
4947 
4948         RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce)));
4949 }
4950 /* }}} */
4951 
4952 /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
4953    Returns whether this class is a subclass of another class */
4954 ZEND_METHOD(reflection_class, implementsInterface)
4955 {
4956         reflection_object *intern, *argument;
4957         zend_class_entry *ce, *interface_ce;
4958         zval *interface;
4959 
4960         METHOD_NOTSTATIC(reflection_class_ptr);
4961         GET_REFLECTION_OBJECT_PTR(ce);
4962 
4963         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &interface) == FAILURE) {
4964                 return;
4965         }
4966 
4967         switch (Z_TYPE_P(interface)) {
4968                 case IS_STRING:
4969                         if ((interface_ce = zend_lookup_class(Z_STR_P(interface))) == NULL) {
4970                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
4971                                                 "Interface %s does not exist", Z_STRVAL_P(interface));
4972                                 return;
4973                         }
4974                         break;
4975                 case IS_OBJECT:
4976                         if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr)) {
4977                                 argument = Z_REFLECTION_P(interface);
4978                                 if (argument == NULL || argument->ptr == NULL) {
4979                                         php_error_docref(NULL, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
4980                                         /* Bails out */
4981                                 }
4982                                 interface_ce = argument->ptr;
4983                                 break;
4984                         }
4985                         /* no break */
4986                 default:
4987                         zend_throw_exception_ex(reflection_exception_ptr, 0,
4988                                         "Parameter one must either be a string or a ReflectionClass object");
4989                         return;
4990         }
4991 
4992         if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
4993                 zend_throw_exception_ex(reflection_exception_ptr, 0,
4994                                 "Interface %s is a Class", ZSTR_VAL(interface_ce->name));
4995                 return;
4996         }
4997         RETURN_BOOL(instanceof_function(ce, interface_ce));
4998 }
4999 /* }}} */
5000 
5001 /* {{{ proto public bool ReflectionClass::isIterateable()
5002    Returns whether this class is iterateable (can be used inside foreach) */
5003 ZEND_METHOD(reflection_class, isIterateable)
5004 {
5005         reflection_object *intern;
5006         zend_class_entry *ce;
5007 
5008         if (zend_parse_parameters_none() == FAILURE) {
5009                 return;
5010         }
5011 
5012         METHOD_NOTSTATIC(reflection_class_ptr);
5013         GET_REFLECTION_OBJECT_PTR(ce);
5014 
5015         RETURN_BOOL(ce->get_iterator != NULL);
5016 }
5017 /* }}} */
5018 
5019 /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
5020    Returns NULL or the extension the class belongs to */
5021 ZEND_METHOD(reflection_class, getExtension)
5022 {
5023         reflection_object *intern;
5024         zend_class_entry *ce;
5025 
5026         if (zend_parse_parameters_none() == FAILURE) {
5027                 return;
5028         }
5029 
5030         METHOD_NOTSTATIC(reflection_class_ptr);
5031         GET_REFLECTION_OBJECT_PTR(ce);
5032 
5033         if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5034                 reflection_extension_factory(return_value, ce->info.internal.module->name);
5035         }
5036 }
5037 /* }}} */
5038 
5039 /* {{{ proto public string|false ReflectionClass::getExtensionName()
5040    Returns false or the name of the extension the class belongs to */
5041 ZEND_METHOD(reflection_class, getExtensionName)
5042 {
5043         reflection_object *intern;
5044         zend_class_entry *ce;
5045 
5046         if (zend_parse_parameters_none() == FAILURE) {
5047                 return;
5048         }
5049 
5050         METHOD_NOTSTATIC(reflection_class_ptr);
5051         GET_REFLECTION_OBJECT_PTR(ce);
5052 
5053         if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module) {
5054                 RETURN_STRING(ce->info.internal.module->name);
5055         } else {
5056                 RETURN_FALSE;
5057         }
5058 }
5059 /* }}} */
5060 
5061 /* {{{ proto public bool ReflectionClass::inNamespace()
5062    Returns whether this class is defined in namespace */
5063 ZEND_METHOD(reflection_class, inNamespace)
5064 {
5065         zval *name;
5066         const char *backslash;
5067 
5068         if (zend_parse_parameters_none() == FAILURE) {
5069                 return;
5070         }
5071         if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1)) == NULL) {
5072                 RETURN_FALSE;
5073         }
5074         if (Z_TYPE_P(name) == IS_STRING
5075                 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5076                 && backslash > Z_STRVAL_P(name))
5077         {
5078                 RETURN_TRUE;
5079         }
5080         RETURN_FALSE;
5081 }
5082 /* }}} */
5083 
5084 /* {{{ proto public string ReflectionClass::getNamespaceName()
5085    Returns the name of namespace where this class is defined */
5086 ZEND_METHOD(reflection_class, getNamespaceName)
5087 {
5088         zval *name;
5089         const char *backslash;
5090 
5091         if (zend_parse_parameters_none() == FAILURE) {
5092                 return;
5093         }
5094         if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1)) == NULL) {
5095                 RETURN_FALSE;
5096         }
5097         if (Z_TYPE_P(name) == IS_STRING
5098                 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5099                 && backslash > Z_STRVAL_P(name))
5100         {
5101                 RETURN_STRINGL(Z_STRVAL_P(name), backslash - Z_STRVAL_P(name));
5102         }
5103         RETURN_EMPTY_STRING();
5104 }
5105 /* }}} */
5106 
5107 /* {{{ proto public string ReflectionClass::getShortName()
5108    Returns the short name of the class (without namespace part) */
5109 ZEND_METHOD(reflection_class, getShortName)
5110 {
5111         zval *name;
5112         const char *backslash;
5113 
5114         if (zend_parse_parameters_none() == FAILURE) {
5115                 return;
5116         }
5117         if ((name = _default_load_entry(getThis(), "name", sizeof("name")-1)) == NULL) {
5118                 RETURN_FALSE;
5119         }
5120         if (Z_TYPE_P(name) == IS_STRING
5121                 && (backslash = zend_memrchr(Z_STRVAL_P(name), '\\', Z_STRLEN_P(name)))
5122                 && backslash > Z_STRVAL_P(name))
5123         {
5124                 RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
5125         }
5126         ZVAL_DEREF(name);
5127         ZVAL_COPY(return_value, name);
5128 }
5129 /* }}} */
5130 
5131 /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException
5132    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
5133 ZEND_METHOD(reflection_object, export)
5134 {
5135         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
5136 }
5137 /* }}} */
5138 
5139 /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
5140    Constructor. Takes an instance as an argument */
5141 ZEND_METHOD(reflection_object, __construct)
5142 {
5143         reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
5144 }
5145 /* }}} */
5146 
5147 /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException
5148    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
5149 ZEND_METHOD(reflection_property, export)
5150 {
5151         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
5152 }
5153 /* }}} */
5154 
5155 /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
5156    Constructor. Throws an Exception in case the given property does not exist */
5157 ZEND_METHOD(reflection_property, __construct)
5158 {
5159         zval propname, cname, *classname;
5160         char *name_str;
5161         size_t name_len;
5162         int dynam_prop = 0;
5163         zval *object;
5164         reflection_object *intern;
5165         zend_class_entry *ce;
5166         zend_property_info *property_info = NULL;
5167         property_reference *reference;
5168 
5169         if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zs", &classname, &name_str, &name_len) == FAILURE) {
5170                 return;
5171         }
5172 
5173         object = getThis();
5174         intern = Z_REFLECTION_P(object);
5175 
5176         /* Find the class entry */
5177         switch (Z_TYPE_P(classname)) {
5178                 case IS_STRING:
5179                         if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
5180                                 zend_throw_exception_ex(reflection_exception_ptr, 0,
5181                                                 "Class %s does not exist", Z_STRVAL_P(classname));
5182                                 return;
5183                         }
5184                         break;
5185 
5186                 case IS_OBJECT:
5187                         ce = Z_OBJCE_P(classname);
5188                         break;
5189 
5190                 default:
5191                         _DO_THROW("The parameter class is expected to be either a string or an object");
5192                         /* returns out of this function */
5193         }
5194 
5195         if ((property_info = zend_hash_str_find_ptr(&ce->properties_info, name_str, name_len)) == NULL || (property_info->flags & ZEND_ACC_SHADOW)) {
5196                 /* Check for dynamic properties */
5197                 if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT && Z_OBJ_HT_P(classname)->get_properties) {
5198                         if (zend_hash_str_exists(Z_OBJ_HT_P(classname)->get_properties(classname), name_str, name_len)) {
5199                                 dynam_prop = 1;
5200                         }
5201                 }
5202                 if (dynam_prop == 0) {
5203                         zend_throw_exception_ex(reflection_exception_ptr, 0, "Property %s::$%s does not exist", ZSTR_VAL(ce->name), name_str);
5204                         return;
5205                 }
5206         }
5207 
5208         if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
5209                 /* we have to search the class hierarchy for this (implicit) public or protected property */
5210                 zend_class_entry *tmp_ce = ce;
5211                 zend_property_info *tmp_info;
5212 
5213                 while (tmp_ce && (tmp_info = zend_hash_str_find_ptr(&tmp_ce->properties_info, name_str, name_len)) == NULL) {
5214                         ce = tmp_ce;
5215                         property_info = tmp_info;
5216                         tmp_ce = tmp_ce->parent;
5217                 }
5218         }
5219 
5220         if (dynam_prop == 0) {
5221                 const char *class_name, *prop_name;
5222                 size_t prop_name_len;
5223                 zend_unmangle_property_name_ex(property_info->name, &class_name, &prop_name, &prop_name_len);
5224                 ZVAL_STR_COPY(&cname, property_info->ce->name);
5225                 ZVAL_STRINGL(&propname, prop_name, prop_name_len);
5226         } else {
5227                 ZVAL_STR_COPY(&cname, ce->name);
5228                 ZVAL_STRINGL(&propname, name_str, name_len);
5229         }
5230         reflection_update_property(object, "class", &cname);
5231         reflection_update_property(object, "name", &propname);
5232 
5233         reference = (property_reference*) emalloc(sizeof(property_reference));
5234         if (dynam_prop) {
5235                 reference->prop.flags = ZEND_ACC_IMPLICIT_PUBLIC;
5236                 reference->prop.name = Z_STR(propname);
5237                 reference->prop.doc_comment = NULL;
5238                 reference->prop.ce = ce;
5239         } else {
5240                 reference->prop = *property_info;
5241         }
5242         reference->ce = ce;
5243         intern->ptr = reference;
5244         intern->ref_type = REF_TYPE_PROPERTY;
5245         intern->ce = ce;
5246         intern->ignore_visibility = 0;
5247 }
5248 /* }}} */
5249 
5250 /* {{{ proto public string ReflectionProperty::__toString()
5251    Returns a string representation */
5252 ZEND_METHOD(reflection_property, __toString)
5253 {
5254         reflection_object *intern;
5255         property_reference *ref;
5256         string str;
5257 
5258         if (zend_parse_parameters_none() == FAILURE) {
5259                 return;
5260         }
5261         GET_REFLECTION_OBJECT_PTR(ref);
5262         string_init(&str);
5263         _property_string(&str, &ref->prop, NULL, "");
5264         RETURN_NEW_STR(str.buf);
5265 }
5266 /* }}} */
5267 
5268 /* {{{ proto public string ReflectionProperty::getName()
5269    Returns the class' name */
5270 ZEND_METHOD(reflection_property, getName)
5271 {
5272         if (zend_parse_parameters_none() == FAILURE) {
5273                 return;
5274         }
5275         _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
5276 }
5277 /* }}} */
5278 
5279 static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
5280 {
5281         reflection_object *intern;
5282         property_reference *ref;
5283 
5284         if (zend_parse_parameters_none() == FAILURE) {
5285                 return;
5286         }
5287         GET_REFLECTION_OBJECT_PTR(ref);
5288         RETURN_BOOL(ref->prop.flags & mask);
5289 }
5290 /* }}} */
5291 
5292 /* {{{ proto public bool ReflectionProperty::isPublic()
5293    Returns whether this property is public */
5294 ZEND_METHOD(reflection_property, isPublic)
5295 {
5296         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
5297 }
5298 /* }}} */
5299 
5300 /* {{{ proto public bool ReflectionProperty::isPrivate()
5301    Returns whether this property is private */
5302 ZEND_METHOD(reflection_property, isPrivate)
5303 {
5304         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
5305 }
5306 /* }}} */
5307 
5308 /* {{{ proto public bool ReflectionProperty::isProtected()
5309    Returns whether this property is protected */
5310 ZEND_METHOD(reflection_property, isProtected)
5311 {
5312         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
5313 }
5314 /* }}} */
5315 
5316 /* {{{ proto public bool ReflectionProperty::isStatic()
5317    Returns whether this property is static */
5318 ZEND_METHOD(reflection_property, isStatic)
5319 {
5320         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
5321 }
5322 /* }}} */
5323 
5324 /* {{{ proto public bool ReflectionProperty::isDefault()
5325    Returns whether this property is default (declared at compilation time). */
5326 ZEND_METHOD(reflection_property, isDefault)
5327 {
5328         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ~ZEND_ACC_IMPLICIT_PUBLIC);
5329 }
5330 /* }}} */
5331 
5332 /* {{{ proto public int ReflectionProperty::getModifiers()
5333    Returns a bitfield of the access modifiers for this property */
5334 ZEND_METHOD(reflection_property, getModifiers)
5335 {
5336         reflection_object *intern;
5337         property_reference *ref;
5338 
5339         if (zend_parse_parameters_none() == FAILURE) {
5340                 return;
5341         }
5342         GET_REFLECTION_OBJECT_PTR(ref);
5343 
5344         RETURN_LONG(ref->prop.flags);
5345 }
5346 /* }}} */
5347 
5348 /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
5349    Returns this property's value */
5350 ZEND_METHOD(reflection_property, getValue)
5351 {
5352         reflection_object *intern;
5353         property_reference *ref;
5354         zval *object, *name;
5355         zval *member_p = NULL;
5356 
5357         METHOD_NOTSTATIC(reflection_property_ptr);
5358         GET_REFLECTION_OBJECT_PTR(ref);
5359 
5360         if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) {
5361                 name = _default_load_entry(getThis(), "name", sizeof("name")-1);
5362                 zend_throw_exception_ex(reflection_exception_ptr, 0,
5363                         "Cannot access non-public member %s::%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5364                 return;
5365         }
5366 
5367         if ((ref->prop.flags & ZEND_ACC_STATIC)) {
5368                 if (UNEXPECTED(zend_update_class_constants(intern->ce) != SUCCESS)) {
5369                         return;
5370                 }
5371                 if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) {
5372                         php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
5373                         /* Bails out */
5374                 }
5375                 ZVAL_DUP(return_value, &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]);
5376         } else {
5377                 const char *class_name, *prop_name;
5378                 size_t prop_name_len;
5379                 zval rv;
5380 
5381                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &object) == FAILURE) {
5382                         return;
5383                 }
5384 
5385                 zend_unmangle_property_name_ex(ref->prop.name, &class_name, &prop_name, &prop_name_len);
5386                 member_p = zend_read_property(ref->ce, object, prop_name, prop_name_len, 1, &rv);
5387                 ZVAL_DUP(return_value, member_p);
5388         }
5389 }
5390 /* }}} */
5391 
5392 /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
5393    Sets this property's value */
5394 ZEND_METHOD(reflection_property, setValue)
5395 {
5396         reflection_object *intern;
5397         property_reference *ref;
5398         zval *variable_ptr;
5399         zval *object, *name;
5400         zval *value;
5401         zval *tmp;
5402 
5403         METHOD_NOTSTATIC(reflection_property_ptr);
5404         GET_REFLECTION_OBJECT_PTR(ref);
5405 
5406         if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
5407                 name = _default_load_entry(getThis(), "name", sizeof("name")-1);
5408                 zend_throw_exception_ex(reflection_exception_ptr, 0,
5409                         "Cannot access non-public member %s::%s", ZSTR_VAL(intern->ce->name), Z_STRVAL_P(name));
5410                 return;
5411         }
5412 
5413         if ((ref->prop.flags & ZEND_ACC_STATIC)) {
5414                 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
5415                         if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &tmp, &value) == FAILURE) {
5416                                 return;
5417                         }
5418                 }
5419                 if (UNEXPECTED(zend_update_class_constants(intern->ce) != SUCCESS)) {
5420                         return;
5421                 }
5422 
5423                 if (Z_TYPE(CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]) == IS_UNDEF) {
5424                         php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name));
5425                         /* Bails out */
5426                 }
5427                 variable_ptr = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset];
5428                 if (variable_ptr != value) {
5429                         zval garbage;
5430 
5431                         ZVAL_DEREF(variable_ptr);
5432                         ZVAL_DEREF(value);
5433 
5434                         ZVAL_COPY_VALUE(&garbage, variable_ptr);
5435 
5436                         ZVAL_COPY(variable_ptr, value);
5437 
5438                         zval_ptr_dtor(&garbage);
5439                 }
5440         } else {
5441                 const char *class_name, *prop_name;
5442                 size_t prop_name_len;
5443 
5444                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "oz", &object, &value) == FAILURE) {
5445                         return;
5446                 }
5447 
5448                 zend_unmangle_property_name_ex(ref->prop.name, &class_name, &prop_name, &prop_name_len);
5449                 zend_update_property(ref->ce, object, prop_name, prop_name_len, value);
5450         }
5451 }
5452 /* }}} */
5453 
5454 /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
5455    Get the declaring class */
5456 ZEND_METHOD(reflection_property, getDeclaringClass)
5457 {
5458         reflection_object *intern;
5459         property_reference *ref;
5460         zend_class_entry *tmp_ce, *ce;
5461         zend_property_info *tmp_info;
5462         const char *prop_name, *class_name;
5463         size_t prop_name_len;
5464 
5465         if (zend_parse_parameters_none() == FAILURE) {
5466                 return;
5467         }
5468         GET_REFLECTION_OBJECT_PTR(ref);
5469 
5470         if (zend_unmangle_property_name_ex(ref->prop.name, &class_name, &prop_name, &prop_name_len) != SUCCESS) {
5471                 RETURN_FALSE;
5472         }
5473 
5474         ce = tmp_ce = ref->ce;
5475         while (tmp_ce && (tmp_info = zend_hash_str_find_ptr(&tmp_ce->properties_info, prop_name, prop_name_len)) != NULL) {
5476                 if (tmp_info->flags & ZEND_ACC_PRIVATE || tmp_info->flags & ZEND_ACC_SHADOW) {
5477                         /* it's a private property, so it can't be inherited */
5478                         break;
5479                 }
5480                 ce = tmp_ce;
5481                 if (tmp_ce == tmp_info->ce) {
5482                         /* declared in this class, done */
5483                         break;
5484                 }
5485                 tmp_ce = tmp_ce->parent;
5486         }
5487 
5488         zend_reflection_class_factory(ce, return_value);
5489 }
5490 /* }}} */
5491 
5492 /* {{{ proto public string ReflectionProperty::getDocComment()
5493    Returns the doc comment for this property */
5494 ZEND_METHOD(reflection_property, getDocComment)
5495 {
5496         reflection_object *intern;
5497         property_reference *ref;
5498 
5499         if (zend_parse_parameters_none() == FAILURE) {
5500                 return;
5501         }
5502         GET_REFLECTION_OBJECT_PTR(ref);
5503         if (ref->prop.doc_comment) {
5504                 RETURN_STR_COPY(ref->prop.doc_comment);
5505         }
5506         RETURN_FALSE;
5507 }
5508 /* }}} */
5509 
5510 /* {{{ proto public int ReflectionProperty::setAccessible(bool visible)
5511    Sets whether non-public properties can be requested */
5512 ZEND_METHOD(reflection_property, setAccessible)
5513 {
5514         reflection_object *intern;
5515         zend_bool visible;
5516 
5517         if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
5518                 return;
5519         }
5520 
5521         intern = Z_REFLECTION_P(getThis());
5522 
5523         intern->ignore_visibility = visible;
5524 }
5525 /* }}} */
5526 
5527 /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
5528    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
5529 ZEND_METHOD(reflection_extension, export)
5530 {
5531         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_extension_ptr, 1);
5532 }
5533 /* }}} */
5534 
5535 /* {{{ proto public void ReflectionExtension::__construct(string name)
5536    Constructor. Throws an Exception in case the given extension does not exist */
5537 ZEND_METHOD(reflection_extension, __construct)
5538 {
5539         zval name;
5540         zval *object;
5541         char *lcname;
5542         reflection_object *intern;
5543         zend_module_entry *module;
5544         char *name_str;
5545         size_t name_len;
5546         ALLOCA_FLAG(use_heap)
5547 
5548         if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
5549                 return;
5550         }
5551 
5552         object = getThis();
5553         intern = Z_REFLECTION_P(object);
5554 
5555         lcname = do_alloca(name_len + 1, use_heap);
5556         zend_str_tolower_copy(lcname, name_str, name_len);
5557         if ((module = zend_hash_str_find_ptr(&module_registry, lcname, name_len)) == NULL) {
5558                 free_alloca(lcname, use_heap);
5559                 zend_throw_exception_ex(reflection_exception_ptr, 0,
5560                         "Extension %s does not exist", name_str);
5561                 return;
5562         }
5563         free_alloca(lcname, use_heap);
5564         ZVAL_STRING(&name, module->name);
5565         reflection_update_property(object, "name", &name);
5566         intern->ptr = module;
5567         intern->ref_type = REF_TYPE_OTHER;
5568         intern->ce = NULL;
5569 }
5570 /* }}} */
5571 
5572 /* {{{ proto public string ReflectionExtension::__toString()
5573    Returns a string representation */
5574 ZEND_METHOD(reflection_extension, __toString)
5575 {
5576         reflection_object *intern;
5577         zend_module_entry *module;
5578         string str;
5579 
5580         if (zend_parse_parameters_none() == FAILURE) {
5581                 return;
5582         }
5583         GET_REFLECTION_OBJECT_PTR(module);
5584         string_init(&str);
5585         _extension_string(&str, module, "");
5586         RETURN_NEW_STR(str.buf);
5587 }
5588 /* }}} */
5589 
5590 /* {{{ proto public string ReflectionExtension::getName()
5591    Returns this extension's name */
5592 ZEND_METHOD(reflection_extension, getName)
5593 {
5594         if (zend_parse_parameters_none() == FAILURE) {
5595                 return;
5596         }
5597         _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
5598 }
5599 /* }}} */
5600 
5601 /* {{{ proto public string ReflectionExtension::getVersion()
5602    Returns this extension's version */
5603 ZEND_METHOD(reflection_extension, getVersion)
5604 {
5605         reflection_object *intern;
5606         zend_module_entry *module;
5607 
5608         if (zend_parse_parameters_none() == FAILURE) {
5609                 return;
5610         }
5611         GET_REFLECTION_OBJECT_PTR(module);
5612 
5613         /* An extension does not necessarily have a version number */
5614         if (module->version == NO_VERSION_YET) {
5615                 RETURN_NULL();
5616         } else {
5617                 RETURN_STRING(module->version);
5618         }
5619 }
5620 /* }}} */
5621 
5622 /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
5623    Returns an array of this extension's functions */
5624 ZEND_METHOD(reflection_extension, getFunctions)
5625 {
5626         reflection_object *intern;
5627         zend_module_entry *module;
5628         zval function;
5629         zend_function *fptr;
5630 
5631         if (zend_parse_parameters_none() == FAILURE) {
5632                 return;
5633         }
5634         GET_REFLECTION_OBJECT_PTR(module);
5635 
5636         array_init(return_value);
5637         ZEND_HASH_FOREACH_PTR(CG(function_table), fptr) {
5638                 if (fptr->common.type==ZEND_INTERNAL_FUNCTION
5639                         && fptr->internal_function.module == module) {
5640                         reflection_function_factory(fptr, NULL, &function);
5641                         zend_hash_update(Z_ARRVAL_P(return_value), fptr->common.function_name, &function);
5642                 }
5643         } ZEND_HASH_FOREACH_END();
5644 }
5645 /* }}} */
5646 
5647 static int _addconstant(zval *el, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
5648 {
5649         zval const_val;
5650         zend_constant *constant = (zend_constant*)Z_PTR_P(el);
5651         zval *retval = va_arg(args, zval*);
5652         int number = va_arg(args, int);
5653 
5654         if (number == constant->module_number) {
5655                 ZVAL_DUP(&const_val, &constant->value);
5656                 zend_hash_update(Z_ARRVAL_P(retval), constant->name, &const_val);
5657         }
5658         return 0;
5659 }
5660 /* }}} */
5661 
5662 /* {{{ proto public array ReflectionExtension::getConstants()
5663    Returns an associative array containing this extension's constants and their values */
5664 ZEND_METHOD(reflection_extension, getConstants)
5665 {
5666         reflection_object *intern;
5667         zend_module_entry *module;
5668 
5669         if (zend_parse_parameters_none() == FAILURE) {
5670                 return;
5671         }
5672         GET_REFLECTION_OBJECT_PTR(module);
5673 
5674         array_init(return_value);
5675         zend_hash_apply_with_arguments(EG(zend_constants), (apply_func_args_t) _addconstant, 2, return_value, module->module_number);
5676 }
5677 /* }}} */
5678 
5679 /* {{{ _addinientry */
5680 static int _addinientry(zval *el, int num_args, va_list args, zend_hash_key *hash_key)
5681 {
5682         zend_ini_entry *ini_entry = (zend_ini_entry*)Z_PTR_P(el);
5683         zval *retval = va_arg(args, zval*);
5684         int number = va_arg(args, int);
5685 
5686         if (number == ini_entry->module_number) {
5687                 if (ini_entry->value) {
5688                         zval zv;
5689 
5690                         ZVAL_STR_COPY(&zv, ini_entry->value);
5691                         zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &zv);
5692                 } else {
5693                         zend_symtable_update(Z_ARRVAL_P(retval), ini_entry->name, &EG(uninitialized_zval));
5694                 }
5695         }
5696         return ZEND_HASH_APPLY_KEEP;
5697 }
5698 /* }}} */
5699 
5700 /* {{{ proto public array ReflectionExtension::getINIEntries()
5701    Returns an associative array containing this extension's INI entries and their values */
5702 ZEND_METHOD(reflection_extension, getINIEntries)
5703 {
5704         reflection_object *intern;
5705         zend_module_entry *module;
5706 
5707         if (zend_parse_parameters_none() == FAILURE) {
5708                 return;
5709         }
5710         GET_REFLECTION_OBJECT_PTR(module);
5711 
5712         array_init(return_value);
5713         zend_hash_apply_with_arguments(EG(ini_directives), (apply_func_args_t) _addinientry, 2, return_value, module->module_number);
5714 }
5715 /* }}} */
5716 
5717 /* {{{ add_extension_class */
5718 static int add_extension_class(zval *zv, int num_args, va_list args, zend_hash_key *hash_key)
5719 {
5720         zend_class_entry *ce = Z_PTR_P(zv);
5721         zval *class_array = va_arg(args, zval*), zclass;
5722         struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
5723         int add_reflection_class = va_arg(args, int);
5724 
5725         if ((ce->type == ZEND_INTERNAL_CLASS) && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
5726                 zend_string *name;
5727 
5728                 if (zend_binary_strcasecmp(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), ZSTR_VAL(hash_key->key), ZSTR_LEN(hash_key->key))) {
5729                         /* This is an class alias, use alias name */
5730                         name = hash_key->key;
5731                 } else {
5732                         /* Use class name */
5733                         name = ce->name;
5734                 }
5735                 if (add_reflection_class) {
5736                         zend_reflection_class_factory(ce, &zclass);
5737                         zend_hash_update(Z_ARRVAL_P(class_array), name, &zclass);
5738                 } else {
5739                         add_next_index_str(class_array, zend_string_copy(name));
5740                 }
5741         }
5742         return ZEND_HASH_APPLY_KEEP;
5743 }
5744 /* }}} */
5745 
5746 /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
5747    Returns an array containing ReflectionClass objects for all classes of this extension */
5748 ZEND_METHOD(reflection_extension, getClasses)
5749 {
5750         reflection_object *intern;
5751         zend_module_entry *module;
5752 
5753         if (zend_parse_parameters_none() == FAILURE) {
5754                 return;
5755         }
5756         GET_REFLECTION_OBJECT_PTR(module);
5757 
5758         array_init(return_value);
5759         zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) add_extension_class, 3, return_value, module, 1);
5760 }
5761 /* }}} */
5762 
5763 /* {{{ proto public array ReflectionExtension::getClassNames()
5764    Returns an array containing all names of all classes of this extension */
5765 ZEND_METHOD(reflection_extension, getClassNames)
5766 {
5767         reflection_object *intern;
5768         zend_module_entry *module;
5769 
5770         if (zend_parse_parameters_none() == FAILURE) {
5771                 return;
5772         }
5773         GET_REFLECTION_OBJECT_PTR(module);
5774 
5775         array_init(return_value);
5776         zend_hash_apply_with_arguments(EG(class_table), (apply_func_args_t) add_extension_class, 3, return_value, module, 0);
5777 }
5778 /* }}} */
5779 
5780 /* {{{ proto public array ReflectionExtension::getDependencies()
5781    Returns an array containing all names of all extensions this extension depends on */
5782 ZEND_METHOD(reflection_extension, getDependencies)
5783 {
5784         reflection_object *intern;
5785         zend_module_entry *module;
5786         const zend_module_dep *dep;
5787 
5788         if (zend_parse_parameters_none() == FAILURE) {
5789                 return;
5790         }
5791         GET_REFLECTION_OBJECT_PTR(module);
5792 
5793         array_init(return_value);
5794 
5795         dep = module->deps;
5796 
5797         if (!dep)
5798         {
5799                 return;
5800         }
5801 
5802         while(dep->name) {
5803                 zend_string *relation;
5804                 char *rel_type;
5805                 size_t len = 0;
5806 
5807                 switch(dep->type) {
5808                         case MODULE_DEP_REQUIRED:
5809                                 rel_type = "Required";
5810                                 len += sizeof("Required") - 1;
5811                                 break;
5812                         case MODULE_DEP_CONFLICTS:
5813                                 rel_type = "Conflicts";
5814                                 len += sizeof("Conflicts") - 1;
5815                                 break;
5816                         case MODULE_DEP_OPTIONAL:
5817                                 rel_type = "Optional";
5818                                 len += sizeof("Optional") - 1;
5819                                 break;
5820                         default:
5821                                 rel_type = "Error"; /* shouldn't happen */
5822                                 len += sizeof("Error") - 1;
5823                                 break;
5824                 }
5825 
5826                 if (dep->rel) {
5827                         len += strlen(dep->rel) + 1;
5828                 }
5829 
5830                 if (dep->version) {
5831                         len += strlen(dep->version) + 1;
5832                 }
5833 
5834                 relation = zend_string_alloc(len, 0);
5835                 snprintf(ZSTR_VAL(relation), ZSTR_LEN(relation) + 1, "%s%s%s%s%s",
5836                                                 rel_type,
5837                                                 dep->rel ? " " : "",
5838                                                 dep->rel ? dep->rel : "",
5839                                                 dep->version ? " " : "",
5840                                                 dep->version ? dep->version : "");
5841                 add_assoc_str(return_value, dep->name, relation);
5842                 dep++;
5843         }
5844 }
5845 /* }}} */
5846 
5847 /* {{{ proto public void ReflectionExtension::info()
5848        Prints phpinfo block for the extension */
5849 ZEND_METHOD(reflection_extension, info)
5850 {
5851         reflection_object *intern;
5852         zend_module_entry *module;
5853 
5854         if (zend_parse_parameters_none() == FAILURE) {
5855                 return;
5856         }
5857         GET_REFLECTION_OBJECT_PTR(module);
5858 
5859         php_info_print_module(module);
5860 }
5861 /* }}} */
5862 
5863 /* {{{ proto public bool ReflectionExtension::isPersistent()
5864        Returns whether this extension is persistent */
5865 ZEND_METHOD(reflection_extension, isPersistent)
5866 {
5867         reflection_object *intern;
5868     zend_module_entry *module;
5869 
5870     if (zend_parse_parameters_none() == FAILURE) {
5871                 return;
5872         }
5873         GET_REFLECTION_OBJECT_PTR(module);
5874 
5875         RETURN_BOOL(module->type == MODULE_PERSISTENT);
5876 }
5877 /* }}} */
5878 
5879 /* {{{ proto public bool ReflectionExtension::isTemporary()
5880        Returns whether this extension is temporary */
5881 ZEND_METHOD(reflection_extension, isTemporary)
5882 {
5883         reflection_object *intern;
5884         zend_module_entry *module;
5885 
5886         if (zend_parse_parameters_none() == FAILURE) {
5887                 return;
5888         }
5889         GET_REFLECTION_OBJECT_PTR(module);
5890 
5891         RETURN_BOOL(module->type == MODULE_TEMPORARY);
5892 }
5893 /* }}} */
5894 
5895 /* {{{ proto public static mixed ReflectionZendExtension::export(string name [, bool return]) throws ReflectionException
5896  *    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
5897 ZEND_METHOD(reflection_zend_extension, export)
5898 {
5899         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_zend_extension_ptr, 1);
5900 }
5901 /* }}} */
5902 
5903 /* {{{ proto public void ReflectionZendExtension::__construct(string name)
5904        Constructor. Throws an Exception in case the given Zend extension does not exist */
5905 ZEND_METHOD(reflection_zend_extension, __construct)
5906 {
5907         zval name;
5908         zval *object;
5909         reflection_object *intern;
5910         zend_extension *extension;
5911         char *name_str;
5912         size_t name_len;
5913 
5914         if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s", &name_str, &name_len) == FAILURE) {
5915                 return;
5916         }
5917 
5918         object = getThis();
5919         intern = Z_REFLECTION_P(object);
5920 
5921         extension = zend_get_extension(name_str);
5922         if (!extension) {
5923                 zend_throw_exception_ex(reflection_exception_ptr, 0,
5924                                 "Zend Extension %s does not exist", name_str);
5925                 return;
5926         }
5927         ZVAL_STRING(&name, extension->name);
5928         reflection_update_property(object, "name", &name);
5929         intern->ptr = extension;
5930         intern->ref_type = REF_TYPE_OTHER;
5931         intern->ce = NULL;
5932 }
5933 /* }}} */
5934 
5935 /* {{{ proto public string ReflectionZendExtension::__toString()
5936        Returns a string representation */
5937 ZEND_METHOD(reflection_zend_extension, __toString)
5938 {
5939         reflection_object *intern;
5940         zend_extension *extension;
5941         string str;
5942 
5943         if (zend_parse_parameters_none() == FAILURE) {
5944                 return;
5945         }
5946         GET_REFLECTION_OBJECT_PTR(extension);
5947         string_init(&str);
5948         _zend_extension_string(&str, extension, "");
5949         RETURN_NEW_STR(str.buf);
5950 }
5951 /* }}} */
5952 
5953 /* {{{ proto public string ReflectionZendExtension::getName()
5954        Returns the name of this Zend extension */
5955 ZEND_METHOD(reflection_zend_extension, getName)
5956 {
5957         reflection_object *intern;
5958         zend_extension *extension;
5959 
5960         if (zend_parse_parameters_none() == FAILURE) {
5961                 return;
5962         }
5963         GET_REFLECTION_OBJECT_PTR(extension);
5964 
5965         RETURN_STRING(extension->name);
5966 }
5967 /* }}} */
5968 
5969 /* {{{ proto public string ReflectionZendExtension::getVersion()
5970        Returns the version information of this Zend extension */
5971 ZEND_METHOD(reflection_zend_extension, getVersion)
5972 {
5973         reflection_object *intern;
5974         zend_extension *extension;
5975 
5976         if (zend_parse_parameters_none() == FAILURE) {
5977                 return;
5978         }
5979         GET_REFLECTION_OBJECT_PTR(extension);
5980 
5981         if (extension->version) {
5982                 RETURN_STRING(extension->version);
5983         } else {
5984                 RETURN_EMPTY_STRING();
5985         }
5986 }
5987 /* }}} */
5988 
5989 /* {{{ proto public void ReflectionZendExtension::getAuthor()
5990  * Returns the name of this Zend extension's author */
5991 ZEND_METHOD(reflection_zend_extension, getAuthor)
5992 {
5993         reflection_object *intern;
5994         zend_extension *extension;
5995 
5996         if (zend_parse_parameters_none() == FAILURE) {
5997                 return;
5998         }
5999         GET_REFLECTION_OBJECT_PTR(extension);
6000 
6001         if (extension->author) {
6002                 RETURN_STRING(extension->author);
6003         } else {
6004                 RETURN_EMPTY_STRING();
6005         }
6006 }
6007 /* }}} */
6008 
6009 /* {{{ proto public void ReflectionZendExtension::getURL()
6010        Returns this Zend extension's URL*/
6011 ZEND_METHOD(reflection_zend_extension, getURL)
6012 {
6013         reflection_object *intern;
6014         zend_extension *extension;
6015 
6016         if (zend_parse_parameters_none() == FAILURE) {
6017                 return;
6018         }
6019         GET_REFLECTION_OBJECT_PTR(extension);
6020 
6021         if (extension->URL) {
6022                 RETURN_STRING(extension->URL);
6023         } else {
6024                 RETURN_EMPTY_STRING();
6025         }
6026 }
6027 /* }}} */
6028 
6029 /* {{{ proto public void ReflectionZendExtension::getCopyright()
6030        Returns this Zend extension's copyright information */
6031 ZEND_METHOD(reflection_zend_extension, getCopyright)
6032 {
6033         reflection_object *intern;
6034         zend_extension *extension;
6035 
6036         if (zend_parse_parameters_none() == FAILURE) {
6037                 return;
6038         }
6039         GET_REFLECTION_OBJECT_PTR(extension);
6040 
6041         if (extension->copyright) {
6042                 RETURN_STRING(extension->copyright);
6043         } else {
6044                 RETURN_EMPTY_STRING();
6045         }
6046 }
6047 /* }}} */
6048 
6049 /* {{{ method tables */
6050 static const zend_function_entry reflection_exception_functions[] = {
6051         PHP_FE_END
6052 };
6053 
6054 ZEND_BEGIN_ARG_INFO(arginfo_reflection__void, 0)
6055 ZEND_END_ARG_INFO()
6056 
6057 
6058 ZEND_BEGIN_ARG_INFO(arginfo_reflection_getModifierNames, 0)
6059         ZEND_ARG_INFO(0, modifiers)
6060 ZEND_END_ARG_INFO()
6061 
6062 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_export, 0, 0, 1)
6063         ZEND_ARG_OBJ_INFO(0, reflector, Reflector, 0)
6064         ZEND_ARG_INFO(0, return)
6065 ZEND_END_ARG_INFO()
6066 
6067 static const zend_function_entry reflection_functions[] = {
6068         ZEND_ME(reflection, getModifierNames, arginfo_reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6069         ZEND_ME(reflection, export, arginfo_reflection_export, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
6070         PHP_FE_END
6071 };
6072 
6073 static const zend_function_entry reflector_functions[] = {
6074         ZEND_FENTRY(export, NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)
6075         ZEND_ABSTRACT_ME(reflector, __toString, arginfo_reflection__void)
6076         PHP_FE_END
6077 };
6078 
6079 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_export, 0, 0, 1)
6080         ZEND_ARG_INFO(0, name)
6081         ZEND_ARG_INFO(0, return)
6082 ZEND_END_ARG_INFO()
6083 
6084 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function___construct, 0)
6085         ZEND_ARG_INFO(0, name)
6086 ZEND_END_ARG_INFO()
6087 
6088 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_invoke, 0, 0, 0)
6089         ZEND_ARG_INFO(0, args)
6090 ZEND_END_ARG_INFO()
6091 
6092 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function_invokeArgs, 0)
6093         ZEND_ARG_ARRAY_INFO(0, args, 0)
6094 ZEND_END_ARG_INFO()
6095 
6096 static const zend_function_entry reflection_function_abstract_functions[] = {
6097         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6098         ZEND_ME(reflection_function, inNamespace, arginfo_reflection__void, 0)
6099         ZEND_ME(reflection_function, isClosure, arginfo_reflection__void, 0)
6100         ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
6101         ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
6102         ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
6103         ZEND_ME(reflection_function, isGenerator, arginfo_reflection__void, 0)
6104         ZEND_ME(reflection_function, isVariadic, arginfo_reflection__void, 0)
6105         ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0)
6106         ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0)
6107         ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
6108         ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
6109         ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
6110         ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0)
6111         ZEND_ME(reflection_function, getFileName, arginfo_reflection__void, 0)
6112         ZEND_ME(reflection_function, getName, arginfo_reflection__void, 0)
6113         ZEND_ME(reflection_function, getNamespaceName, arginfo_reflection__void, 0)
6114         ZEND_ME(reflection_function, getNumberOfParameters, arginfo_reflection__void, 0)
6115         ZEND_ME(reflection_function, getNumberOfRequiredParameters, arginfo_reflection__void, 0)
6116         ZEND_ME(reflection_function, getParameters, arginfo_reflection__void, 0)
6117         ZEND_ME(reflection_function, getShortName, arginfo_reflection__void, 0)
6118         ZEND_ME(reflection_function, getStartLine, arginfo_reflection__void, 0)
6119         ZEND_ME(reflection_function, getStaticVariables, arginfo_reflection__void, 0)
6120         ZEND_ME(reflection_function, returnsReference, arginfo_reflection__void, 0)
6121         ZEND_ME(reflection_function, hasReturnType, arginfo_reflection__void, 0)
6122         ZEND_ME(reflection_function, getReturnType, arginfo_reflection__void, 0)
6123         PHP_FE_END
6124 };
6125 
6126 static const zend_function_entry reflection_function_functions[] = {
6127         ZEND_ME(reflection_function, __construct, arginfo_reflection_function___construct, 0)
6128         ZEND_ME(reflection_function, __toString, arginfo_reflection__void, 0)
6129         ZEND_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6130         ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
6131         ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
6132         ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
6133         ZEND_ME(reflection_function, getClosure, arginfo_reflection__void, 0)
6134         PHP_FE_END
6135 };
6136 
6137 ZEND_BEGIN_ARG_INFO(arginfo_reflection_generator___construct, 0)
6138         ZEND_ARG_INFO(0, generator)
6139 ZEND_END_ARG_INFO()
6140 
6141 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_generator_trace, 0, 0, 0)
6142         ZEND_ARG_INFO(0, options)
6143 ZEND_END_ARG_INFO()
6144 
6145 static const zend_function_entry reflection_generator_functions[] = {
6146         ZEND_ME(reflection_generator, __construct, arginfo_reflection_generator___construct, 0)
6147         ZEND_ME(reflection_generator, getExecutingLine, arginfo_reflection__void, 0)
6148         ZEND_ME(reflection_generator, getExecutingFile, arginfo_reflection__void, 0)
6149         ZEND_ME(reflection_generator, getTrace, arginfo_reflection_generator_trace, 0)
6150         ZEND_ME(reflection_generator, getFunction, arginfo_reflection__void, 0)
6151         ZEND_ME(reflection_generator, getThis, arginfo_reflection__void, 0)
6152         ZEND_ME(reflection_generator, getExecutingGenerator, arginfo_reflection__void, 0)
6153         PHP_FE_END
6154 };
6155 
6156 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_export, 0, 0, 2)
6157         ZEND_ARG_INFO(0, class)
6158         ZEND_ARG_INFO(0, name)
6159         ZEND_ARG_INFO(0, return)
6160 ZEND_END_ARG_INFO()
6161 
6162 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method___construct, 0, 0, 1)
6163         ZEND_ARG_INFO(0, class_or_method)
6164         ZEND_ARG_INFO(0, name)
6165 ZEND_END_ARG_INFO()
6166 
6167 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invoke, 0)
6168         ZEND_ARG_INFO(0, object)
6169         ZEND_ARG_INFO(0, args)
6170 ZEND_END_ARG_INFO()
6171 
6172 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invokeArgs, 0)
6173         ZEND_ARG_INFO(0, object)
6174         ZEND_ARG_ARRAY_INFO(0, args, 0)
6175 ZEND_END_ARG_INFO()
6176 
6177 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
6178         ZEND_ARG_INFO(0, value)
6179 ZEND_END_ARG_INFO()
6180 
6181 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_getClosure, 0)
6182         ZEND_ARG_INFO(0, object)
6183 ZEND_END_ARG_INFO()
6184 
6185 static const zend_function_entry reflection_method_functions[] = {
6186         ZEND_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6187         ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
6188         ZEND_ME(reflection_method, __toString, arginfo_reflection__void, 0)
6189         ZEND_ME(reflection_method, isPublic, arginfo_reflection__void, 0)
6190         ZEND_ME(reflection_method, isPrivate, arginfo_reflection__void, 0)
6191         ZEND_ME(reflection_method, isProtected, arginfo_reflection__void, 0)
6192         ZEND_ME(reflection_method, isAbstract, arginfo_reflection__void, 0)
6193         ZEND_ME(reflection_method, isFinal, arginfo_reflection__void, 0)
6194         ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
6195         ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
6196         ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
6197         ZEND_ME(reflection_method, getClosure, arginfo_reflection_method_getClosure, 0)
6198         ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
6199         ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
6200         ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
6201         ZEND_ME(reflection_method, getDeclaringClass, arginfo_reflection__void, 0)
6202         ZEND_ME(reflection_method, getPrototype, arginfo_reflection__void, 0)
6203         ZEND_ME(reflection_method, setAccessible, arginfo_reflection_method_setAccessible, 0)
6204         PHP_FE_END
6205 };
6206 
6207 
6208 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1)
6209         ZEND_ARG_INFO(0, argument)
6210         ZEND_ARG_INFO(0, return)
6211 ZEND_END_ARG_INFO()
6212 
6213 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class___construct, 0)
6214         ZEND_ARG_INFO(0, argument)
6215 ZEND_END_ARG_INFO()
6216 
6217 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getStaticPropertyValue, 0, 0, 1)
6218         ZEND_ARG_INFO(0, name)
6219         ZEND_ARG_INFO(0, default)
6220 ZEND_END_ARG_INFO()
6221 
6222 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setStaticPropertyValue, 0)
6223         ZEND_ARG_INFO(0, name)
6224         ZEND_ARG_INFO(0, value)
6225 ZEND_END_ARG_INFO()
6226 
6227 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasMethod, 0)
6228         ZEND_ARG_INFO(0, name)
6229 ZEND_END_ARG_INFO()
6230 
6231 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getMethod, 0)
6232         ZEND_ARG_INFO(0, name)
6233 ZEND_END_ARG_INFO()
6234 
6235 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getMethods, 0, 0, 0)
6236         ZEND_ARG_INFO(0, filter)
6237 ZEND_END_ARG_INFO()
6238 
6239 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasProperty, 0)
6240         ZEND_ARG_INFO(0, name)
6241 ZEND_END_ARG_INFO()
6242 
6243 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getProperty, 0)
6244         ZEND_ARG_INFO(0, name)
6245 ZEND_END_ARG_INFO()
6246 
6247 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getProperties, 0, 0, 0)
6248         ZEND_ARG_INFO(0, filter)
6249 ZEND_END_ARG_INFO()
6250 
6251 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasConstant, 0)
6252         ZEND_ARG_INFO(0, name)
6253 ZEND_END_ARG_INFO()
6254 
6255 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getConstant, 0)
6256         ZEND_ARG_INFO(0, name)
6257 ZEND_END_ARG_INFO()
6258 
6259 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0)
6260         ZEND_ARG_INFO(0, object)
6261 ZEND_END_ARG_INFO()
6262 
6263 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
6264         ZEND_ARG_INFO(0, args)
6265 ZEND_END_ARG_INFO()
6266 
6267 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6268 ZEND_END_ARG_INFO()
6269 
6270 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
6271         ZEND_ARG_ARRAY_INFO(0, args, 0)
6272 ZEND_END_ARG_INFO()
6273 
6274 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isSubclassOf, 0)
6275         ZEND_ARG_INFO(0, class)
6276 ZEND_END_ARG_INFO()
6277 
6278 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_implementsInterface, 0)
6279         ZEND_ARG_INFO(0, interface)
6280 ZEND_END_ARG_INFO()
6281 
6282 static const zend_function_entry reflection_class_functions[] = {
6283         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6284         ZEND_ME(reflection_class, export, arginfo_reflection_class_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6285         ZEND_ME(reflection_class, __construct, arginfo_reflection_class___construct, 0)
6286         ZEND_ME(reflection_class, __toString, arginfo_reflection__void, 0)
6287         ZEND_ME(reflection_class, getName, arginfo_reflection__void, 0)
6288         ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
6289         ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
6290         ZEND_ME(reflection_class, isAnonymous, arginfo_reflection__void, 0)
6291         ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
6292         ZEND_ME(reflection_class, isCloneable, arginfo_reflection__void, 0)
6293         ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
6294         ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
6295         ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
6296         ZEND_ME(reflection_class, getDocComment, arginfo_reflection__void, 0)
6297         ZEND_ME(reflection_class, getConstructor, arginfo_reflection__void, 0)
6298         ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0)
6299         ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0)
6300         ZEND_ME(reflection_class, getMethods, arginfo_reflection_class_getMethods, 0)
6301         ZEND_ME(reflection_class, hasProperty, arginfo_reflection_class_hasProperty, 0)
6302         ZEND_ME(reflection_class, getProperty, arginfo_reflection_class_getProperty, 0)
6303         ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
6304         ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
6305         ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
6306         ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
6307         ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
6308         ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
6309         ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
6310         ZEND_ME(reflection_class, getTraits, arginfo_reflection__void, 0)
6311         ZEND_ME(reflection_class, getTraitNames, arginfo_reflection__void, 0)
6312         ZEND_ME(reflection_class, getTraitAliases, arginfo_reflection__void, 0)
6313         ZEND_ME(reflection_class, isTrait, arginfo_reflection__void, 0)
6314         ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
6315         ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
6316         ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
6317         ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
6318         ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
6319         ZEND_ME(reflection_class, newInstanceWithoutConstructor, arginfo_reflection_class_newInstanceWithoutConstructor, 0)
6320         ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
6321         ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
6322         ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
6323         ZEND_ME(reflection_class, getStaticProperties, arginfo_reflection__void, 0)
6324         ZEND_ME(reflection_class, getStaticPropertyValue, arginfo_reflection_class_getStaticPropertyValue, 0)
6325         ZEND_ME(reflection_class, setStaticPropertyValue, arginfo_reflection_class_setStaticPropertyValue, 0)
6326         ZEND_ME(reflection_class, getDefaultProperties, arginfo_reflection__void, 0)
6327         ZEND_ME(reflection_class, isIterateable, arginfo_reflection__void, 0)
6328         ZEND_ME(reflection_class, implementsInterface, arginfo_reflection_class_implementsInterface, 0)
6329         ZEND_ME(reflection_class, getExtension, arginfo_reflection__void, 0)
6330         ZEND_ME(reflection_class, getExtensionName, arginfo_reflection__void, 0)
6331         ZEND_ME(reflection_class, inNamespace, arginfo_reflection__void, 0)
6332         ZEND_ME(reflection_class, getNamespaceName, arginfo_reflection__void, 0)
6333         ZEND_ME(reflection_class, getShortName, arginfo_reflection__void, 0)
6334         PHP_FE_END
6335 };
6336 
6337 
6338 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_object_export, 0, 0, 1)
6339         ZEND_ARG_INFO(0, argument)
6340         ZEND_ARG_INFO(0, return)
6341 ZEND_END_ARG_INFO()
6342 
6343 ZEND_BEGIN_ARG_INFO(arginfo_reflection_object___construct, 0)
6344         ZEND_ARG_INFO(0, argument)
6345 ZEND_END_ARG_INFO()
6346 
6347 static const zend_function_entry reflection_object_functions[] = {
6348         ZEND_ME(reflection_object, export, arginfo_reflection_object_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6349         ZEND_ME(reflection_object, __construct, arginfo_reflection_object___construct, 0)
6350         PHP_FE_END
6351 };
6352 
6353 
6354 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 2)
6355         ZEND_ARG_INFO(0, class)
6356         ZEND_ARG_INFO(0, name)
6357         ZEND_ARG_INFO(0, return)
6358 ZEND_END_ARG_INFO()
6359 
6360 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 2)
6361         ZEND_ARG_INFO(0, class)
6362         ZEND_ARG_INFO(0, name)
6363 ZEND_END_ARG_INFO()
6364 
6365 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_getValue, 0, 0, 0)
6366         ZEND_ARG_INFO(0, object)
6367 ZEND_END_ARG_INFO()
6368 
6369 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_setValue, 0, 0, 1)
6370         ZEND_ARG_INFO(0, object)
6371         ZEND_ARG_INFO(0, value)
6372 ZEND_END_ARG_INFO()
6373 
6374 ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
6375         ZEND_ARG_INFO(0, visible)
6376 ZEND_END_ARG_INFO()
6377 
6378 static const zend_function_entry reflection_property_functions[] = {
6379         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6380         ZEND_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6381         ZEND_ME(reflection_property, __construct, arginfo_reflection_property___construct, 0)
6382         ZEND_ME(reflection_property, __toString, arginfo_reflection__void, 0)
6383         ZEND_ME(reflection_property, getName, arginfo_reflection__void, 0)
6384         ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
6385         ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
6386         ZEND_ME(reflection_property, isPublic, arginfo_reflection__void, 0)
6387         ZEND_ME(reflection_property, isPrivate, arginfo_reflection__void, 0)
6388         ZEND_ME(reflection_property, isProtected, arginfo_reflection__void, 0)
6389         ZEND_ME(reflection_property, isStatic, arginfo_reflection__void, 0)
6390         ZEND_ME(reflection_property, isDefault, arginfo_reflection__void, 0)
6391         ZEND_ME(reflection_property, getModifiers, arginfo_reflection__void, 0)
6392         ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0)
6393         ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0)
6394         ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
6395         PHP_FE_END
6396 };
6397 
6398 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
6399         ZEND_ARG_INFO(0, function)
6400         ZEND_ARG_INFO(0, parameter)
6401         ZEND_ARG_INFO(0, return)
6402 ZEND_END_ARG_INFO()
6403 
6404 ZEND_BEGIN_ARG_INFO(arginfo_reflection_parameter___construct, 0)
6405         ZEND_ARG_INFO(0, function)
6406         ZEND_ARG_INFO(0, parameter)
6407 ZEND_END_ARG_INFO()
6408 
6409 static const zend_function_entry reflection_parameter_functions[] = {
6410         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6411         ZEND_ME(reflection_parameter, export, arginfo_reflection_parameter_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6412         ZEND_ME(reflection_parameter, __construct, arginfo_reflection_parameter___construct, 0)
6413         ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
6414         ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
6415         ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
6416         ZEND_ME(reflection_parameter, canBePassedByValue, arginfo_reflection__void, 0)
6417         ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
6418         ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
6419         ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
6420         ZEND_ME(reflection_parameter, hasType, arginfo_reflection__void, 0)
6421         ZEND_ME(reflection_parameter, getType, arginfo_reflection__void, 0)
6422         ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
6423         ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
6424         ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
6425         ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
6426         ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
6427         ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
6428         ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
6429         ZEND_ME(reflection_parameter, isDefaultValueConstant, arginfo_reflection__void, 0)
6430         ZEND_ME(reflection_parameter, getDefaultValueConstantName, arginfo_reflection__void, 0)
6431         ZEND_ME(reflection_parameter, isVariadic, arginfo_reflection__void, 0)
6432         PHP_FE_END
6433 };
6434 
6435 static const zend_function_entry reflection_type_functions[] = {
6436         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6437         ZEND_ME(reflection_type, allowsNull, arginfo_reflection__void, 0)
6438         ZEND_ME(reflection_type, isBuiltin, arginfo_reflection__void, 0)
6439         ZEND_ME(reflection_type, __toString, arginfo_reflection__void, 0)
6440         PHP_FE_END
6441 };
6442 
6443 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
6444         ZEND_ARG_INFO(0, name)
6445         ZEND_ARG_INFO(0, return)
6446 ZEND_END_ARG_INFO()
6447 
6448 ZEND_BEGIN_ARG_INFO(arginfo_reflection_extension___construct, 0)
6449         ZEND_ARG_INFO(0, name)
6450 ZEND_END_ARG_INFO()
6451 
6452 static const zend_function_entry reflection_extension_functions[] = {
6453         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6454         ZEND_ME(reflection_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6455         ZEND_ME(reflection_extension, __construct, arginfo_reflection_extension___construct, 0)
6456         ZEND_ME(reflection_extension, __toString, arginfo_reflection__void, 0)
6457         ZEND_ME(reflection_extension, getName, arginfo_reflection__void, 0)
6458         ZEND_ME(reflection_extension, getVersion, arginfo_reflection__void, 0)
6459         ZEND_ME(reflection_extension, getFunctions, arginfo_reflection__void, 0)
6460         ZEND_ME(reflection_extension, getConstants, arginfo_reflection__void, 0)
6461         ZEND_ME(reflection_extension, getINIEntries, arginfo_reflection__void, 0)
6462         ZEND_ME(reflection_extension, getClasses, arginfo_reflection__void, 0)
6463         ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
6464         ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
6465         ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
6466         ZEND_ME(reflection_extension, isPersistent, arginfo_reflection__void, 0)
6467         ZEND_ME(reflection_extension, isTemporary, arginfo_reflection__void, 0)
6468         PHP_FE_END
6469 };
6470 
6471 ZEND_BEGIN_ARG_INFO(arginfo_reflection_zend_extension___construct, 0)
6472         ZEND_ARG_INFO(0, name)
6473 ZEND_END_ARG_INFO()
6474 
6475 static const zend_function_entry reflection_zend_extension_functions[] = {
6476         ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
6477         ZEND_ME(reflection_zend_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
6478         ZEND_ME(reflection_zend_extension, __construct, arginfo_reflection_zend_extension___construct, 0)
6479         ZEND_ME(reflection_zend_extension, __toString, arginfo_reflection__void, 0)
6480         ZEND_ME(reflection_zend_extension, getName, arginfo_reflection__void, 0)
6481         ZEND_ME(reflection_zend_extension, getVersion, arginfo_reflection__void, 0)
6482         ZEND_ME(reflection_zend_extension, getAuthor, arginfo_reflection__void, 0)
6483         ZEND_ME(reflection_zend_extension, getURL, arginfo_reflection__void, 0)
6484         ZEND_ME(reflection_zend_extension, getCopyright, arginfo_reflection__void, 0)
6485         PHP_FE_END
6486 };
6487 /* }}} */
6488 
6489 const zend_function_entry reflection_ext_functions[] = { /* {{{ */
6490         PHP_FE_END
6491 }; /* }}} */
6492 
6493 static zend_object_handlers *zend_std_obj_handlers;
6494 
6495 /* {{{ _reflection_write_property */
6496 static void _reflection_write_property(zval *object, zval *member, zval *value, void **cache_slot)
6497 {
6498         if ((Z_TYPE_P(member) == IS_STRING)
6499                 && zend_hash_exists(&Z_OBJCE_P(object)->properties_info, Z_STR_P(member))
6500                 && ((Z_STRLEN_P(member) == sizeof("name") - 1  && !memcmp(Z_STRVAL_P(member), "name",  sizeof("name")))
6501                         || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
6502         {
6503                 zend_throw_exception_ex(reflection_exception_ptr, 0,
6504                         "Cannot set read-only property %s::$%s", ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member));
6505         }
6506         else
6507         {
6508                 zend_std_obj_handlers->write_property(object, member, value, cache_slot);
6509         }
6510 }
6511 /* }}} */
6512 
6513 PHP_MINIT_FUNCTION(reflection) /* {{{ */
6514 {
6515         zend_class_entry _reflection_entry;
6516 
6517         zend_std_obj_handlers = zend_get_std_object_handlers();
6518         memcpy(&reflection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
6519         reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
6520         reflection_object_handlers.free_obj = reflection_free_objects_storage;
6521         reflection_object_handlers.clone_obj = NULL;
6522         reflection_object_handlers.write_property = _reflection_write_property;
6523 
6524         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions);
6525         reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_ce_exception);
6526 
6527         INIT_CLASS_ENTRY(_reflection_entry, "Reflection", reflection_functions);
6528         reflection_ptr = zend_register_internal_class(&_reflection_entry);
6529 
6530         INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions);
6531         reflector_ptr = zend_register_internal_interface(&_reflection_entry);
6532 
6533         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
6534         _reflection_entry.create_object = reflection_objects_new;
6535         reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
6536         zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
6537         zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
6538 
6539         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
6540         _reflection_entry.create_object = reflection_objects_new;
6541         reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6542         zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6543 
6544         REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
6545 
6546         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", reflection_generator_functions);
6547         _reflection_entry.create_object = reflection_objects_new;
6548         reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
6549 
6550         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
6551         _reflection_entry.create_object = reflection_objects_new;
6552         reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
6553         zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
6554         zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6555 
6556         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
6557         _reflection_entry.create_object = reflection_objects_new;
6558         reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
6559 
6560         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
6561         _reflection_entry.create_object = reflection_objects_new;
6562         reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
6563         zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6564         zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6565 
6566         REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
6567         REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6568         REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6569         REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6570         REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
6571         REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
6572 
6573         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
6574         _reflection_entry.create_object = reflection_objects_new;
6575         reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
6576         zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
6577         zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6578 
6579         REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
6580         REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
6581         REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
6582 
6583         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
6584         _reflection_entry.create_object = reflection_objects_new;
6585         reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
6586 
6587         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
6588         _reflection_entry.create_object = reflection_objects_new;
6589         reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
6590         zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
6591         zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6592         zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
6593 
6594         REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
6595         REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
6596         REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
6597         REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
6598 
6599         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
6600         _reflection_entry.create_object = reflection_objects_new;
6601         reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
6602         zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
6603         zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6604 
6605         INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", reflection_zend_extension_functions);
6606         _reflection_entry.create_object = reflection_objects_new;
6607         reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
6608         zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
6609         zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
6610 
6611         return SUCCESS;
6612 } /* }}} */
6613 
6614 PHP_MINFO_FUNCTION(reflection) /* {{{ */
6615 {
6616         php_info_print_table_start();
6617         php_info_print_table_header(2, "Reflection", "enabled");
6618 
6619         php_info_print_table_row(2, "Version", "$Id: 50d0ba002342d41efa753927261e5e09f295ecf9 $");
6620 
6621         php_info_print_table_end();
6622 } /* }}} */
6623 
6624 zend_module_entry reflection_module_entry = { /* {{{ */
6625         STANDARD_MODULE_HEADER,
6626         "Reflection",
6627         reflection_ext_functions,
6628         PHP_MINIT(reflection),
6629         NULL,
6630         NULL,
6631         NULL,
6632         PHP_MINFO(reflection),
6633         PHP_REFLECTION_VERSION,
6634         STANDARD_MODULE_PROPERTIES
6635 }; /* }}} */
6636 
6637 /*
6638  * Local variables:
6639  * tab-width: 4
6640  * c-basic-offset: 4
6641  * indent-tabs-mode: t
6642  * End:
6643  * vim600: noet sw=4 ts=4 fdm=marker
6644  */

/* [<][>][^][v][top][bottom][index][help] */