PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - reflection - php_reflection.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 2406
Code covered: 90.7 % Executed lines: 2183
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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: php_reflection.c 290515 2009-11-11 18:52:12Z felipe $ */
      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                 : 
      43                 : /* Class entry pointers */
      44                 : PHPAPI zend_class_entry *reflector_ptr;
      45                 : PHPAPI zend_class_entry *reflection_exception_ptr;
      46                 : PHPAPI zend_class_entry *reflection_ptr;
      47                 : PHPAPI zend_class_entry *reflection_function_abstract_ptr;
      48                 : PHPAPI zend_class_entry *reflection_function_ptr;
      49                 : PHPAPI zend_class_entry *reflection_parameter_ptr;
      50                 : PHPAPI zend_class_entry *reflection_class_ptr;
      51                 : PHPAPI zend_class_entry *reflection_object_ptr;
      52                 : PHPAPI zend_class_entry *reflection_method_ptr;
      53                 : PHPAPI zend_class_entry *reflection_property_ptr;
      54                 : PHPAPI zend_class_entry *reflection_extension_ptr;
      55                 : 
      56                 : #if MBO_0
      57                 : ZEND_BEGIN_MODULE_GLOBALS(reflection)
      58                 :         int dummy;
      59                 : ZEND_END_MODULE_GLOBALS(reflection)
      60                 : 
      61                 : #ifdef ZTS
      62                 : # define REFLECTION_G(v) \
      63                 :         TSRMG(reflection_globals_id, zend_reflection_globals*, v)
      64                 : extern int reflection_globals_id;
      65                 : #else
      66                 : # define REFLECTION_G(v) (reflection_globals.v)
      67                 : extern zend_reflection_globals reflectionglobals;
      68                 : #endif
      69                 : 
      70                 : ZEND_DECLARE_MODULE_GLOBALS(reflection)
      71                 : #endif /* MBO_0 */
      72                 : 
      73                 : /* Method macros */
      74                 : 
      75                 : #define METHOD_NOTSTATIC(ce)                                                                                \
      76                 :         if (!this_ptr || !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {                             \
      77                 :                 zend_error(E_ERROR, "%v() cannot be called statically", get_active_function_name(TSRMLS_C));        \
      78                 :                 return;                                                                                             \
      79                 :         }                                                                                                       \
      80                 : 
      81                 : /* Exception throwing macro */
      82                 : #define _DO_THROW(msg)                                                                                      \
      83                 :         zend_throw_exception(reflection_exception_ptr, msg, 0 TSRMLS_CC);                                       \
      84                 :         return;                                                                                                 \
      85                 : 
      86                 : #define RETURN_ON_EXCEPTION                                                                                 \
      87                 :         if (EG(exception) && Z_OBJCE_P(EG(exception)) == reflection_exception_ptr) {                            \
      88                 :                 return;                                                                                             \
      89                 :         }
      90                 : 
      91                 : #define GET_REFLECTION_OBJECT_PTR(target)                                                                   \
      92                 :         intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC);                       \
      93                 :         if (intern == NULL || intern->ptr == NULL) {                                                            \
      94                 :                 RETURN_ON_EXCEPTION                                                                                 \
      95                 :                 zend_error(E_ERROR, "Internal error: Failed to retrieve the reflection object");                    \
      96                 :         }                                                                                                       \
      97                 :         target = intern->ptr;                                                                                   \
      98                 : 
      99                 : /* Class constants */
     100                 : #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value)                                        \
     101                 :         zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
     102                 : 
     103                 : /* {{{ Smart string functions */
     104                 : typedef struct _string {
     105                 :         char *string;
     106                 :         int len;
     107                 :         int alloced;
     108                 : } string;
     109                 : 
     110                 : static void string_init(string *str)
     111            1032 : {
     112            1032 :         str->string = (char *) emalloc(1024);
     113            1032 :         str->len = 1;
     114            1032 :         str->alloced = 1024;
     115            1032 :         *str->string = '\0';
     116            1032 : }
     117                 :         
     118                 : static string *string_printf(string *str, const char *format, ...)
     119           12941 : {
     120                 :         int len;
     121                 :         va_list arg;
     122                 :         char *s_tmp;
     123                 : 
     124           12941 :         va_start(arg, format);
     125           12941 :         len = zend_vspprintf(&s_tmp, 0, format, arg);
     126           12941 :         if (len) {
     127           12941 :                 register int nlen = (str->len + len + (1024 - 1)) & ~(1024 - 1);
     128           12941 :                 if (str->alloced < nlen) {
     129              75 :                         str->alloced = nlen;
     130              75 :                         str->string = erealloc(str->string, str->alloced);
     131                 :                 }
     132           12941 :                 memcpy(str->string + str->len - 1, s_tmp, len + 1);
     133           12941 :                 str->len += len;
     134                 :         }
     135           12941 :         efree(s_tmp);
     136           12941 :         va_end(arg);
     137           12941 :         return str;
     138                 : }
     139                 : 
     140                 : static string *string_write(string *str, char *buf, int len)
     141            1957 : {
     142            1957 :         register int nlen = (str->len + len + (1024 - 1)) & ~(1024 - 1);
     143            1957 :         if (str->alloced < nlen) {
     144              33 :                 str->alloced = nlen;
     145              33 :                 str->string = erealloc(str->string, str->alloced);
     146                 :         }
     147            1957 :         memcpy(str->string + str->len - 1, buf, len);
     148            1957 :         str->len += len;
     149            1957 :         str->string[str->len - 1] = '\0';
     150            1957 :         return str;
     151                 : }
     152                 : 
     153                 : static string *string_append(string *str, string *append)
     154              50 : {
     155              50 :         if (append->len > 1) {
     156              45 :                 string_write(str, append->string, append->len - 1);
     157                 :         }
     158              50 :         return str;
     159                 : }
     160                 : 
     161                 : static void string_free(string *str)
     162             838 : {
     163             838 :         efree(str->string);
     164             838 :         str->len = 0;
     165             838 :         str->alloced = 0;
     166             838 :         str->string = NULL;
     167             838 : }
     168                 : /* }}} */
     169                 : 
     170                 : /* Struct for properties */
     171                 : typedef struct _property_reference {
     172                 :         zend_class_entry *ce;
     173                 :         zend_property_info prop;
     174                 : } property_reference;
     175                 : 
     176                 : /* Struct for parameters */
     177                 : typedef struct _parameter_reference {
     178                 :         zend_uint offset;
     179                 :         zend_uint required;
     180                 :         struct _zend_arg_info *arg_info;
     181                 :         zend_function *fptr;
     182                 : } parameter_reference;
     183                 : 
     184                 : typedef enum {
     185                 :         REF_TYPE_OTHER,      /* Must be 0 */
     186                 :         REF_TYPE_FUNCTION,
     187                 :         REF_TYPE_PARAMETER,
     188                 :         REF_TYPE_PROPERTY
     189                 : } reflection_type_t;
     190                 : 
     191                 : /* Struct for reflection objects */
     192                 : typedef struct {
     193                 :         zend_object zo;
     194                 :         void *ptr;
     195                 :         reflection_type_t ref_type;
     196                 :         zval *obj;
     197                 :         zend_class_entry *ce;
     198                 :         unsigned int ignore_visibility:1;
     199                 : } reflection_object;
     200                 : 
     201                 : static zend_object_handlers reflection_object_handlers;
     202                 : 
     203                 : static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC) /* {{{ */
     204             416 : {
     205                 :         zval **value;
     206                 : 
     207             416 :         if (zend_ascii_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
     208               0 :                 RETURN_FALSE;
     209                 :         }
     210                 : 
     211             416 :         *return_value = **value;
     212             416 :         zval_copy_ctor(return_value);
     213             416 :         INIT_PZVAL(return_value);
     214                 : }
     215                 : /* }}} */
     216                 : 
     217                 : static void _default_lookup_entry(zval *object, char *name, int name_len, zval **return_value TSRMLS_DC) /* {{{ */
     218             144 : {
     219                 :         zval **value;
     220                 : 
     221             144 :         if (zend_ascii_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
     222               0 :                 *return_value = NULL;
     223                 :         } else {
     224             144 :                 *return_value = *value;
     225                 :         }
     226             144 : }
     227                 : /* }}} */
     228                 : 
     229                 : static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC) /* {{{ */
     230           85035 : {
     231           85035 :         zend_uint num_interfaces = ++class_entry->num_interfaces;
     232                 : 
     233           85035 :         class_entry->interfaces = (zend_class_entry **) realloc(class_entry->interfaces, sizeof(zend_class_entry *) * num_interfaces);
     234           85035 :         class_entry->interfaces[num_interfaces - 1] = interface_entry;
     235           85035 : }
     236                 : /* }}} */
     237                 : 
     238                 : static zend_function *_copy_function(zend_function *fptr TSRMLS_DC) /* {{{ */
     239              81 : {
     240              81 :         if (fptr
     241                 :                 && fptr->type == ZEND_INTERNAL_FUNCTION
     242                 :                 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
     243                 :         {
     244                 :                 zend_function *copy_fptr;
     245               4 :                 copy_fptr = emalloc(sizeof(zend_function));
     246               4 :                 memcpy(copy_fptr, fptr, sizeof(zend_function));
     247               4 :                 copy_fptr->internal_function.function_name.u = eustrdup(fptr->internal_function.function_name.u);
     248               4 :                 return copy_fptr;
     249                 :         } else {
     250                 :                 /* no copy needed */
     251              77 :                 return fptr;
     252                 :         }
     253                 : }
     254                 : /* }}} */
     255                 : 
     256                 : static void _free_function(zend_function *fptr TSRMLS_DC) /* {{{ */
     257            1740 : {
     258            1740 :         if (fptr
     259                 :                 && fptr->type != ZEND_USER_FUNCTION
     260                 :                 && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
     261                 :         {
     262              19 :                 efree(fptr->internal_function.function_name.v);
     263              19 :                 efree(fptr);
     264                 :         }
     265            1740 : }
     266                 : /* }}} */
     267                 : 
     268                 : static void reflection_free_objects_storage(void *object TSRMLS_DC) /* {{{ */
     269            2101 : {
     270            2101 :         reflection_object *intern = (reflection_object *) object;
     271                 :         parameter_reference *reference;
     272                 : 
     273            2101 :         if (intern->ptr) {
     274            2029 :                 switch (intern->ref_type) {
     275                 :                 case REF_TYPE_PARAMETER:
     276              80 :                         reference = (parameter_reference*)intern->ptr;
     277              80 :                         _free_function(reference->fptr TSRMLS_CC);
     278              80 :                         efree(intern->ptr);
     279              80 :                         break;
     280                 :                 case REF_TYPE_FUNCTION:
     281            1105 :                         _free_function(intern->ptr TSRMLS_CC);
     282            1105 :                         break;
     283                 :                 case REF_TYPE_PROPERTY:
     284             238 :                         efree(intern->ptr);
     285                 :                         break;
     286                 :                 case REF_TYPE_OTHER:
     287                 :                         break;
     288                 :                 }
     289                 :         }
     290            2101 :         intern->ptr = NULL;
     291            2101 :         if (intern->obj) {
     292              92 :                 zval_ptr_dtor(&intern->obj);
     293                 :         }
     294            2101 :         zend_objects_free_object_storage(object TSRMLS_CC);
     295            2101 : }
     296                 : /* }}} */
     297                 : 
     298                 : static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
     299            2101 : {
     300                 :         zval tmp;
     301                 :         zend_object_value retval;
     302                 :         reflection_object *intern;
     303                 : 
     304            2101 :         intern = ecalloc(1, sizeof(reflection_object));
     305            2101 :         intern->zo.ce = class_type;
     306                 : 
     307            2101 :         zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
     308            2101 :         zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
     309            2101 :         retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
     310            2101 :         retval.handlers = &reflection_object_handlers;
     311            2101 :         return retval;
     312                 : }
     313                 : /* }}} */
     314                 : 
     315                 : static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC) /* {{{ */
     316            1188 : {
     317            1188 :         if (!object) {
     318               0 :                 ALLOC_ZVAL(object);
     319                 :         }
     320            1188 :         Z_TYPE_P(object) = IS_OBJECT;
     321            1188 :         object_init_ex(object, pce);
     322            1188 :         Z_SET_REFCOUNT_P(object, 1);
     323            1188 :         Z_SET_ISREF_P(object);
     324            1188 :         return object;
     325                 : }
     326                 : /* }}} */
     327                 : 
     328                 : static void _const_string(string *str, zstr name, zval *value, char *indent TSRMLS_DC);
     329                 : static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, zval* prop_name, zval* closure, char *indent TSRMLS_DC);
     330                 : static void _property_string(string *str, zend_property_info *prop, zstr prop_name, char* indent TSRMLS_DC);
     331                 : static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
     332                 : static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
     333                 : 
     334                 : /* {{{ _class_string */
     335                 : static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
     336              52 : {
     337              52 :         int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
     338                 :         string sub_indent;
     339                 :         
     340              52 :         string_init(&sub_indent);
     341              52 :         string_printf(&sub_indent, "%s    ", indent);
     342                 : 
     343                 :         /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
     344              52 :         if (ce->type == ZEND_USER_CLASS && ce->doc_comment.v) {
     345               0 :                 string_printf(str, "%s%v", indent, ce->doc_comment.v);
     346               0 :                 string_write(str, "\n", 1);
     347                 :         }
     348                 : 
     349              52 :         if (obj) {
     350               7 :                 string_printf(str, "%sObject of class [ ", indent);
     351                 :         } else {
     352              45 :                 string_printf(str, "%s%s [ ", indent, (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : "Class");
     353                 :         }
     354              52 :         string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
     355              52 :         if (ce->module) {
     356              29 :                 string_printf(str, ":%s", ce->module->name);
     357                 :         }
     358              52 :         string_printf(str, "> ");
     359              52 :         if (ce->get_iterator != NULL) {
     360               0 :                 string_printf(str, "<iterateable> ");
     361                 :         }
     362              52 :         if (ce->ce_flags & ZEND_ACC_INTERFACE) {
     363               3 :                 string_printf(str, "interface ");
     364                 :         } else {
     365              49 :                 if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
     366               2 :                         string_printf(str, "abstract ");
     367                 :                 }
     368              49 :                 if (ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
     369               0 :                         string_printf(str, "final ");
     370                 :                 } 
     371              49 :                 string_printf(str, "class ");
     372                 :         }
     373              52 :         string_printf(str, "%v", ce->name);
     374              52 :         if (ce->parent) {
     375              20 :                 string_printf(str, " extends %v", ce->parent->name);
     376                 :         }
     377                 : 
     378              52 :         if (ce->num_interfaces) {
     379                 :                 zend_uint i;
     380                 : 
     381              17 :                 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
     382               0 :                         string_printf(str, " extends %v", ce->interfaces[0]->name);
     383                 :                 } else {
     384              17 :                         string_printf(str, " implements %v", ce->interfaces[0]->name);
     385                 :                 }
     386              17 :                 for (i = 1; i < ce->num_interfaces; ++i) {
     387               0 :                         string_printf(str, ", %v", ce->interfaces[i]->name);
     388                 :                 }
     389                 :         }
     390              52 :         string_printf(str, " ] {\n");
     391                 : 
     392                 :         /* The information where a class is declared is only available for user classes */
     393              52 :         if (ce->type == ZEND_USER_CLASS) {
     394              23 :                 string_printf(str, "%s  @@ %s %d-%d\n", indent, ce->filename,
     395                 :                                                 ce->line_start, ce->line_end);
     396                 :         }
     397                 : 
     398                 :         /* Constants */
     399                 :         if (&ce->constants_table) {
     400              52 :                 zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
     401              52 :                 string_printf(str, "\n");
     402              52 :                 count = zend_hash_num_elements(&ce->constants_table);
     403              52 :                 string_printf(str, "%s  - Constants [%d] {\n", indent, count);
     404              52 :                 if (count > 0) {
     405                 :                         HashPosition pos;
     406                 :                         zval **value;
     407                 :                         zstr key;
     408                 :                         uint key_len;
     409                 :                         ulong num_index;
     410                 : 
     411              14 :                         zend_hash_internal_pointer_reset_ex(&ce->constants_table, &pos);
     412                 : 
     413              72 :                         while (zend_hash_get_current_data_ex(&ce->constants_table, (void **) &value, &pos) == SUCCESS) {
     414              44 :                                 zend_hash_get_current_key_ex(&ce->constants_table, &key, &key_len, &num_index, 0, &pos);
     415                 : 
     416              44 :                                 _const_string(str, key, *value, indent TSRMLS_CC);
     417              44 :                                 zend_hash_move_forward_ex(&ce->constants_table, &pos);
     418                 :                         }
     419                 :                 }
     420              52 :                 string_printf(str, "%s  }\n", indent);
     421                 :         }
     422                 : 
     423                 :         /* Static properties */
     424                 :         if (&ce->properties_info) {
     425                 :                 /* counting static properties */                
     426              52 :                 count = zend_hash_num_elements(&ce->properties_info);
     427              52 :                 if (count > 0) {
     428                 :                         HashPosition pos;
     429                 :                         zend_property_info *prop;
     430                 : 
     431              29 :                         zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
     432                 : 
     433             113 :                         while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
     434              55 :                                 if(prop->flags & ZEND_ACC_SHADOW) {
     435              10 :                                         count_shadow_props++;
     436              45 :                                 } else if (prop->flags & ZEND_ACC_STATIC) {
     437               1 :                                         count_static_props++;
     438                 :                                 }
     439              55 :                                 zend_hash_move_forward_ex(&ce->properties_info, &pos);
     440                 :                         }
     441                 :                 }
     442                 : 
     443                 :                 /* static properties */         
     444              52 :                 string_printf(str, "\n%s  - Static properties [%d] {\n", indent, count_static_props);
     445              52 :                 if (count_static_props > 0) {
     446                 :                         HashPosition pos;
     447                 :                         zend_property_info *prop;
     448                 : 
     449               1 :                         zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
     450                 : 
     451               4 :                         while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
     452               2 :                                 if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
     453               1 :                                         _property_string(str, prop, NULL_ZSTR, sub_indent.string TSRMLS_CC);
     454                 :                                 }
     455                 : 
     456               2 :                                 zend_hash_move_forward_ex(&ce->properties_info, &pos);
     457                 :                         }
     458                 :                 }
     459              52 :                 string_printf(str, "%s  }\n", indent);
     460                 :         }
     461                 :         
     462                 :         /* Static methods */
     463                 :         if (&ce->function_table) {
     464                 :                 /* counting static methods */           
     465              52 :                 count = zend_hash_num_elements(&ce->function_table);
     466              52 :                 if (count > 0) {
     467                 :                         HashPosition pos;
     468                 :                         zend_function *mptr;
     469                 : 
     470              41 :                         zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
     471                 : 
     472             668 :                         while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
     473             586 :                                 if (mptr->common.fn_flags & ZEND_ACC_STATIC
     474                 :                                         && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
     475                 :                                 {
     476              21 :                                         count_static_funcs++;
     477                 :                                 }
     478             586 :                                 zend_hash_move_forward_ex(&ce->function_table, &pos);
     479                 :                         }
     480                 :                 }
     481                 : 
     482                 :                 /* static methods */            
     483              52 :                 string_printf(str, "\n%s  - Static methods [%d] {", indent, count_static_funcs);
     484              52 :                 if (count_static_funcs > 0) {
     485                 :                         HashPosition pos;
     486                 :                         zend_function *mptr;
     487                 : 
     488              19 :                         zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
     489                 : 
     490             490 :                         while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
     491             452 :                                 if (mptr->common.fn_flags & ZEND_ACC_STATIC
     492                 :                                         && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
     493                 :                                 {
     494              21 :                                         string_printf(str, "\n");
     495              21 :                                         _function_string(str, mptr, ce, NULL, NULL, sub_indent.string TSRMLS_CC);
     496                 :                                 }
     497             452 :                                 zend_hash_move_forward_ex(&ce->function_table, &pos);
     498                 :                         }
     499                 :                 } else {
     500              33 :                         string_printf(str, "\n");
     501                 :                 }
     502              52 :                 string_printf(str, "%s  }\n", indent);
     503                 :         }
     504                 : 
     505                 :         /* Default/Implicit properties */
     506                 :         if (&ce->properties_info) {
     507              52 :                 count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
     508              52 :                 string_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
     509              52 :                 if (count > 0) {
     510                 :                         HashPosition pos;
     511                 :                         zend_property_info *prop;
     512                 : 
     513              26 :                         zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
     514                 : 
     515             103 :                         while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
     516              51 :                                 if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
     517              44 :                                         _property_string(str, prop, NULL_ZSTR, sub_indent.string TSRMLS_CC);
     518                 :                                 }
     519              51 :                                 zend_hash_move_forward_ex(&ce->properties_info, &pos);
     520                 :                         }
     521                 :                 }
     522              52 :                 string_printf(str, "%s  }\n", indent);
     523                 :         }
     524                 : 
     525              52 :         if (obj && Z_OBJ_HT_P(obj)->get_properties) {
     526                 :                 string       dyn;
     527               7 :                 HashTable    *properties = Z_OBJ_HT_P(obj)->get_properties(obj TSRMLS_CC);
     528                 :                 HashPosition pos;
     529                 :                 zval         **prop;
     530                 : 
     531               7 :                 string_init(&dyn);
     532               7 :                 count = 0;
     533                 : 
     534               7 :                 if (properties && zend_hash_num_elements(properties)) {
     535               6 :                         zend_hash_internal_pointer_reset_ex(properties, &pos);
     536                 : 
     537              26 :                         while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
     538                 :                                 zstr prop_name;
     539                 :                                 uint  prop_name_size;
     540                 :                                 zend_uchar prop_type;
     541                 :                                 ulong index;
     542                 : 
     543              14 :                                 if ((prop_type = zend_hash_get_current_key_ex(properties, &prop_name, &prop_name_size, &index, 0, &pos)) == HASH_KEY_IS_UNICODE) {
     544              14 :                                         if (prop_name_size && prop_name.u[0]) { /* skip all private and protected properties */
     545              11 :                                                 if (!zend_u_hash_exists(&ce->properties_info, prop_type, prop_name, prop_name_size)) {
     546               5 :                                                         count++;
     547               5 :                                                         _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC);       
     548                 :                                                 }
     549                 :                                         }
     550                 :                                 }
     551              14 :                                 zend_hash_move_forward_ex(properties, &pos);
     552                 :                         }
     553                 :                 }
     554                 : 
     555               7 :                 string_printf(str, "\n%s  - Dynamic properties [%d] {\n", indent, count);
     556               7 :                 string_append(str, &dyn);
     557               7 :                 string_printf(str, "%s  }\n", indent);
     558               7 :                 string_free(&dyn);
     559                 :         }
     560                 : 
     561                 :         /* Non static methods */
     562                 :         if (&ce->function_table) {
     563              52 :                 count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
     564              52 :                 if (count > 0) {
     565                 :                         HashPosition pos;
     566                 :                         zend_function *mptr;
     567                 :                         string dyn;
     568                 : 
     569              39 :                         count = 0;
     570              39 :                         string_init(&dyn);
     571              39 :                         zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
     572                 : 
     573             660 :                         while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
     574             582 :                                 if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
     575                 :                                         && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
     576                 :                                 {
     577                 :                                         zstr key;
     578                 :                                         uint key_len;
     579                 :                                         ulong num_index;
     580             554 :                                         uint lcname_len, len = u_strlen(mptr->common.function_name.u);
     581             554 :                                         zstr lcname = zend_u_str_case_fold(IS_UNICODE, mptr->common.function_name, len, 1, &lcname_len);
     582                 : 
     583                 :                                         /* Do not display old-style inherited constructors */
     584             554 :                                         if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0
     585                 :                                                 || mptr->common.scope == ce
     586                 :                                                 || zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_UNICODE
     587                 :                                                 || zend_u_binary_strcmp(key.u, key_len-1, lcname.u, lcname_len) == 0)
     588                 :                                         {
     589                 :                                                 zend_function *closure;
     590                 :                                                 /* see if this is a closure */
     591             554 :                                                 if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
     592                 :                                                         && ZEND_U_EQUAL(IS_UNICODE, lcname, len, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)
     593                 :                                                         && (closure = zend_get_closure_invoke_method(obj TSRMLS_CC)) != NULL)
     594                 :                                                 {
     595               0 :                                                         mptr = closure;
     596                 :                                                 } else {
     597             554 :                                                         closure = NULL;
     598                 :                                                 }
     599                 : 
     600             554 :                                                 string_printf(&dyn, "\n");
     601             554 :                                                 _function_string(&dyn, mptr, ce, NULL, NULL, sub_indent.string TSRMLS_CC);
     602             554 :                                                 count++;
     603             554 :                                                 _free_function(closure TSRMLS_CC);
     604                 :                                         }
     605             554 :                                         efree(lcname.v);
     606                 :                                 }
     607             582 :                                 zend_hash_move_forward_ex(&ce->function_table, &pos);
     608                 :                         }
     609              39 :                         string_printf(str, "\n%s  - Methods [%d] {", indent, count);
     610              39 :                         if (!count) {
     611               1 :                                 string_printf(str, "\n");
     612                 :                         }
     613              39 :                         string_append(str, &dyn);
     614              39 :                         string_free(&dyn);
     615                 :                 } else {
     616              13 :                         string_printf(str, "\n%s  - Methods [0] {\n", indent);
     617                 :                 }
     618              52 :                 string_printf(str, "%s  }\n", indent);
     619                 :         }
     620                 :         
     621              52 :         string_printf(str, "%s}\n", indent);
     622              52 :         string_free(&sub_indent);
     623              52 : }
     624                 : /* }}} */
     625                 : 
     626                 : /* {{{ _const_string */
     627                 : static void _const_string(string *str, zstr name, zval *value, char *indent TSRMLS_DC)
     628              58 : {
     629                 :         char *type;
     630                 :         zval value_copy;
     631                 :         int use_copy;
     632                 : 
     633              58 :         type = zend_zval_type_name(value);
     634                 : 
     635              58 :         zend_make_printable_zval(value, &value_copy, &use_copy);
     636              58 :         if (use_copy) {
     637              58 :                 value = &value_copy;
     638                 :         }
     639                 : 
     640              58 :         string_printf(str, "%s    Constant [ %s %v ] { %s }\n",
     641                 :                                         indent, type, name, Z_STRVAL_P(value));
     642                 : 
     643              58 :         if (use_copy) {
     644              58 :                 zval_dtor(value);
     645                 :         }
     646              58 : }
     647                 : /* }}} */
     648                 : 
     649                 : /* {{{ _get_recv_opcode */
     650                 : static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
     651              60 : {
     652              60 :         zend_op *op = op_array->opcodes;
     653              60 :         zend_op *end = op + op_array->last;
     654                 : 
     655              60 :         ++offset;
     656             232 :         while (op < end) {
     657             172 :                 if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
     658                 :                         && op->op1.u.constant.value.lval == offset)
     659                 :                 {
     660              60 :                         return op;
     661                 :                 }
     662             112 :                 ++op;
     663                 :         }
     664               0 :         return NULL;
     665                 : }
     666                 : /* }}} */
     667                 : 
     668                 : /* {{{ _parameter_string */
     669                 : static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC)
     670             529 : {
     671             529 :         string_printf(str, "Parameter #%d [ ", offset);
     672             529 :         if (offset >= required) {
     673             168 :                 string_printf(str, "<optional> ");
     674                 :         } else {
     675             361 :                 string_printf(str, "<required> ");
     676                 :         }
     677             529 :         if (arg_info->class_name.v) {
     678               7 :                 string_printf(str, "%v ", arg_info->class_name);
     679               7 :                 if (arg_info->allow_null) {
     680               3 :                         string_printf(str, "or NULL ");
     681                 :                 }
     682             522 :         } else if (arg_info->array_type_hint) {
     683              10 :                 string_printf(str, "array ");
     684              10 :                 if (arg_info->allow_null) {
     685               1 :                         string_printf(str, "or NULL ");
     686                 :                 }
     687                 :         }
     688             529 :         if (arg_info->pass_by_reference) {
     689              13 :                 string_write(str, "&", sizeof("&")-1);
     690                 :         }
     691             529 :         if (arg_info->name.v) {
     692             529 :                 string_printf(str, "$%v", arg_info->name);
     693                 :         } else {
     694               0 :                 string_printf(str, "$param%d", offset);
     695                 :         }
     696             529 :         if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
     697              23 :                 zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
     698              23 :                 if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
     699                 :                         zval *zv, zv_copy;
     700                 :                         int use_copy;
     701              23 :                         string_write(str, " = ", sizeof(" = ")-1);
     702              23 :                         ALLOC_ZVAL(zv);
     703              23 :                         *zv = precv->op2.u.constant;
     704              23 :                         zval_copy_ctor(zv);
     705              23 :                         INIT_PZVAL(zv);
     706              23 :                         zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
     707              23 :                         if (Z_TYPE_P(zv) == IS_BOOL) {
     708               2 :                                 if (Z_LVAL_P(zv)) {
     709               0 :                                         string_write(str, "true", sizeof("true")-1);
     710                 :                                 } else {
     711               2 :                                         string_write(str, "false", sizeof("false")-1);
     712                 :                                 }
     713              21 :                         } else if (Z_TYPE_P(zv) == IS_NULL) {
     714              10 :                                 string_write(str, "NULL", sizeof("NULL")-1);
     715              11 :                         } else if (Z_TYPE_P(zv) == IS_STRING) {
     716               0 :                                 string_write(str, "b'", sizeof("b")-1);
     717               0 :                                 string_write(str, "'", sizeof("'")-1);
     718               0 :                                 string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15));
     719               0 :                                 if (Z_STRLEN_P(zv) > 15) {
     720               0 :                                         string_write(str, "...", sizeof("...")-1);
     721                 :                                 }
     722               0 :                                 string_write(str, "'", sizeof("'")-1);
     723              11 :                         } else if (Z_TYPE_P(zv) == IS_UNICODE) {
     724               8 :                                 string_write(str, "'", sizeof("'")-1);
     725               8 :                                 zend_make_printable_zval(zv, &zv_copy, &use_copy);
     726               8 :                                 string_write(str, Z_STRVAL(zv_copy), MIN(Z_STRLEN(zv_copy), 15));
     727               8 :                                 if (Z_STRLEN(zv_copy) > 15) {
     728               1 :                                         string_write(str, "...", sizeof("...")-1);
     729                 :                                 }
     730               8 :                                 string_write(str, "'", sizeof("'")-1);
     731               8 :                                 if (use_copy) {
     732               8 :                                         zval_dtor(&zv_copy);
     733                 :                                 }
     734                 :                         } else {
     735               3 :                                 zend_make_printable_zval(zv, &zv_copy, &use_copy);
     736               3 :                                 string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
     737               3 :                                 if (use_copy) {
     738               3 :                                         zval_dtor(&zv_copy);
     739                 :                                 }
     740                 :                         }
     741              23 :                         zval_ptr_dtor(&zv);
     742                 :                 }
     743                 :         }
     744             529 :         string_write(str, " ]", sizeof(" ]")-1);
     745             529 : }
     746                 : /* }}} */
     747                 : 
     748                 : /* {{{ _function_parameter_string */
     749                 : static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
     750             728 : {
     751             728 :         struct _zend_arg_info *arg_info = fptr->common.arg_info;
     752             728 :         zend_uint i, required = fptr->common.required_num_args;
     753                 : 
     754             728 :         if (!arg_info) {
     755              58 :                 return;
     756                 :         }
     757                 : 
     758             670 :         string_printf(str, "\n");
     759             670 :         string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
     760            1195 :         for (i = 0; i < fptr->common.num_args; i++) {
     761             525 :                 string_printf(str, "%s  ", indent);
     762             525 :                 _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC);
     763             525 :                 string_write(str, "\n", sizeof("\n")-1);
     764             525 :                 arg_info++;
     765                 :         }
     766             670 :         string_printf(str, "%s}\n", indent);
     767                 : }
     768                 : /* }}} */
     769                 : 
     770                 : /* {{{ _function_string */
     771                 : static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, zval* prop_name, zval* closure, char* indent TSRMLS_DC)
     772             728 : {
     773                 :         string param_indent;
     774                 :         zend_function *overwrites;
     775                 :         zstr lc_name;
     776                 :         unsigned int lc_name_len;
     777                 : 
     778                 :         /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
     779                 :          * What's "wrong" is that any whitespace before the doc comment start is 
     780                 :          * swallowed, leading to an unaligned comment.
     781                 :          */
     782             728 :         if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment.v) {
     783               1 :                 string_printf(str, "%s%v\n", indent, fptr->op_array.doc_comment.v);
     784                 :         }
     785                 : 
     786             728 :         string_write(str, indent, strlen(indent));
     787             728 :         string_printf(str, closure ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
     788             728 :         string_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
     789             728 :         if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
     790               0 :                 string_printf(str, ", deprecated");
     791                 :         }
     792             728 :         if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
     793             683 :                 string_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
     794                 :         }
     795             728 :         if (scope && fptr->common.scope) {
     796             594 :                 if (fptr->common.scope != scope) {
     797             189 :                         string_printf(str, ", inherits %v", fptr->common.scope->name);
     798             405 :                 } else if (fptr->common.scope->parent) {
     799              64 :                         lc_name = zend_u_str_case_fold(IS_UNICODE, fptr->common.function_name, USTR_LEN(fptr->common.function_name), 1, &lc_name_len);
     800              64 :                         if (zend_u_hash_find(&fptr->common.scope->parent->function_table, IS_UNICODE, lc_name, lc_name_len + 1, (void**) &overwrites) == SUCCESS) {
     801              13 :                                 if (fptr->common.scope != overwrites->common.scope) {
     802              13 :                                         string_printf(str, ", overwrites %v", overwrites->common.scope->name);
     803                 :                                 }
     804                 :                         }
     805              64 :                         efree(lc_name.v);
     806                 :                 }
     807                 :         }
     808             728 :         if (fptr->common.prototype && fptr->common.prototype->common.scope) {
     809              10 :                 string_printf(str, ", prototype %v", fptr->common.prototype->common.scope->name);
     810                 :         }
     811             728 :         if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
     812              21 :                 string_printf(str, ", ctor");
     813                 :         }
     814             728 :         if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
     815               2 :                 string_printf(str, ", dtor");
     816                 :         }
     817             728 :         string_printf(str, "> ");
     818                 : 
     819             728 :         if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
     820               9 :                 string_printf(str, "abstract ");
     821                 :         }
     822             728 :         if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
     823              33 :                 string_printf(str, "final ");
     824                 :         }
     825             728 :         if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
     826              23 :                 string_printf(str, "static ");
     827                 :         }
     828                 : 
     829             728 :         if (fptr->common.scope) {
     830                 :                 /* These are mutually exclusive */
     831             594 :                 switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
     832                 :                         case ZEND_ACC_PUBLIC:
     833             570 :                                 string_printf(str, "public ");
     834             570 :                                 break;
     835                 :                         case ZEND_ACC_PRIVATE:
     836              19 :                                 string_printf(str, "private ");
     837              19 :                                 break;
     838                 :                         case ZEND_ACC_PROTECTED:
     839               5 :                                 string_printf(str, "protected ");
     840               5 :                                 break;
     841                 :                         default:
     842               0 :                                 string_printf(str, "<visibility error> ");
     843                 :                                 break;
     844                 :                 }
     845             594 :                 string_printf(str, "method ");
     846                 :         } else {
     847             134 :                 string_printf(str, "function ");
     848                 :         }
     849                 : 
     850             728 :         if (fptr->op_array.return_reference) {
     851               0 :                 string_printf(str, "&");
     852                 :         }
     853             730 :         if (closure && prop_name) {
     854               2 :                 string_printf(str, "%R ] {\n", Z_TYPE_P(prop_name), Z_UNIVAL_P(prop_name));
     855                 :         } else {
     856             726 :                 string_printf(str, "%v ] {\n", fptr->common.function_name);
     857                 :         }
     858                 :         /* The information where a function is declared is only available for user classes */
     859             728 :         if (fptr->type == ZEND_USER_FUNCTION) {
     860              45 :                 string_printf(str, "%s  @@ %s %d - %d\n", indent, 
     861                 :                                                 fptr->op_array.filename,
     862                 :                                                 fptr->op_array.line_start,
     863                 :                                                 fptr->op_array.line_end);
     864                 :         }
     865             728 :         if (closure) {
     866               2 :                 const zend_function *closure_fptr = zend_get_closure_method_def(closure TSRMLS_CC);
     867               2 :                 zval *closure_this = zend_get_closure_this_ptr(closure TSRMLS_CC);
     868               2 :                 HashTable *static_variables = NULL;
     869               2 :                 int index = 0, count = closure_this ? 1 : 0;
     870               2 :                 if (closure_fptr->type == ZEND_USER_FUNCTION && closure_fptr->op_array.static_variables) {
     871               2 :                         static_variables = closure_fptr->op_array.static_variables;
     872               2 :                         count += zend_hash_num_elements(static_variables);
     873                 :                 }
     874               2 :                 if (count) {
     875               2 :                         string_printf(str, "\n");
     876               2 :                         string_printf(str, "%s  - Static Parameters [%d] {\n", indent, count);
     877               2 :                         if (closure_this) {
     878               1 :                                 string_printf(str, "%s    Parameter #%d [ %v $this ]\n", indent, index++, Z_OBJCE_P(closure_this)->name);
     879                 :                         }
     880               2 :                         if (static_variables) {
     881                 :                                 HashPosition pos;
     882                 :                                 uint key_len;
     883                 :                                 zstr key;
     884                 :                                 ulong num_index;
     885               2 :                                 zend_hash_internal_pointer_reset_ex(static_variables, &pos);
     886               8 :                                 while (index < count) {
     887               4 :                                         zend_hash_get_current_key_ex(static_variables, &key, &key_len, &num_index, 0, &pos);
     888               4 :                                         string_printf(str, "%s    Parameter #%d [ $%v ]\n", indent, index++, key);
     889               4 :                                         zend_hash_move_forward_ex(static_variables, &pos);
     890                 :                                 }
     891                 :                         }
     892               2 :                         string_printf(str, "%s  }\n", indent);
     893                 :                 }
     894                 :         }
     895             728 :         string_init(&param_indent);
     896             728 :         string_printf(&param_indent, "%s  ", indent);
     897             728 :         _function_parameter_string(str, fptr, param_indent.string TSRMLS_CC);
     898             728 :         string_free(&param_indent);
     899             728 :         string_printf(str, "%s}\n", indent);
     900             728 : }
     901                 : /* }}} */
     902                 : 
     903                 : /* {{{ _property_string */
     904                 : static void _property_string(string *str, zend_property_info *prop, zstr sz_prop_name, char* indent TSRMLS_DC)
     905              63 : {
     906                 :         zstr class_name;
     907                 :         zstr prop_name;
     908                 : 
     909              63 :         string_printf(str, "%sProperty [ ", indent);
     910              63 :         if (!prop) {
     911               5 :                 string_printf(str, "<dynamic> public $%v", sz_prop_name);
     912                 :         } else {
     913              58 :                 if (!(prop->flags & ZEND_ACC_STATIC)) {
     914              54 :                         if (prop->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
     915               0 :                                 string_write(str, "<implicit> ", sizeof("<implicit> ") - 1);
     916                 :                         } else {
     917              54 :                                 string_write(str, "<default> ", sizeof("<default> ") - 1);
     918                 :                         }
     919                 :                 }
     920                 :         
     921                 :                 /* These are mutually exclusive */
     922              58 :                 switch (prop->flags & ZEND_ACC_PPP_MASK) {
     923                 :                         case ZEND_ACC_PUBLIC:
     924              33 :                                 string_printf(str, "public ");
     925              33 :                                 break;
     926                 :                         case ZEND_ACC_PRIVATE:
     927               9 :                                 string_printf(str, "private ");
     928               9 :                                 break;
     929                 :                         case ZEND_ACC_PROTECTED:
     930              16 :                                 string_printf(str, "protected ");
     931                 :                                 break;
     932                 :                 }
     933              58 :                 if(prop->flags & ZEND_ACC_STATIC) {
     934               4 :                         string_printf(str, "static ");
     935                 :                 }
     936                 : 
     937              58 :                 zend_u_unmangle_property_name(IS_UNICODE, prop->name, prop->name_length, &class_name, &prop_name);
     938              58 :                 string_printf(str, "$%v", prop_name);
     939                 :         }
     940                 : 
     941              63 :         string_printf(str, " ]\n");
     942              63 : }
     943                 : /* }}} */
     944                 : 
     945                 : static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     946             654 : {
     947             654 :         string *str = va_arg(args, string *);
     948             654 :         char *indent = va_arg(args, char *);
     949             654 :         int number = va_arg(args, int);
     950             654 :         char *comma = "";
     951                 : 
     952             654 :         if (number == ini_entry->module_number) {
     953               2 :                 string_printf(str, "    %sEntry [ %s <", indent, ini_entry->name);
     954               2 :                 if (ini_entry->modifiable == ZEND_INI_ALL) {
     955               2 :                         string_printf(str, "ALL");
     956                 :                 } else {
     957               0 :                         if (ini_entry->modifiable & ZEND_INI_USER) {
     958               0 :                                 string_printf(str, "USER");
     959               0 :                                 comma = ",";
     960                 :                         }
     961               0 :                         if (ini_entry->modifiable & ZEND_INI_PERDIR) {
     962               0 :                                 string_printf(str, "%sPERDIR", comma);
     963               0 :                                 comma = ",";
     964                 :                         }
     965               0 :                         if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
     966               0 :                                 string_printf(str, "%sSYSTEM", comma);
     967                 :                         }
     968                 :                 }
     969                 : 
     970               2 :                 string_printf(str, "> ]\n");
     971               2 :                 string_printf(str, "    %s  Current = '%s'\n", indent, ini_entry->value ? ini_entry->value : "");
     972               2 :                 if (ini_entry->modified) {
     973               0 :                         string_printf(str, "    %s  Default = '%s'\n", indent, ini_entry->orig_value ? ini_entry->orig_value : "");
     974                 :                 }
     975               2 :                 string_printf(str, "    %s}\n", indent);
     976                 :         }
     977             654 :         return ZEND_HASH_APPLY_KEEP;
     978                 : }
     979                 : /* }}} */
     980                 : 
     981                 : static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     982             468 : {
     983             468 :         string *str = va_arg(args, string *);
     984             468 :         char *indent = va_arg(args, char *);
     985             468 :         struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
     986             468 :         int *num_classes = va_arg(args, int*);
     987                 : 
     988             468 :         if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
     989              22 :                 string_printf(str, "\n");
     990              22 :                 _class_string(str, *pce, NULL, indent TSRMLS_CC);
     991              22 :                 (*num_classes)++;
     992                 :         }
     993             468 :         return ZEND_HASH_APPLY_KEEP;
     994                 : }
     995                 : /* }}} */
     996                 : 
     997                 : static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
     998            6006 : {
     999            6006 :         string *str = va_arg(args, string *);
    1000            6006 :         char *indent = va_arg(args, char *);
    1001            6006 :         struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
    1002            6006 :         int *num_classes = va_arg(args, int*);
    1003                 : 
    1004            6006 :         if (constant->module_number  == module->module_number) {
    1005              14 :                 _const_string(str, constant->name, &constant->value, indent TSRMLS_CC);
    1006              14 :                 (*num_classes)++;
    1007                 :         }
    1008            6006 :         return ZEND_HASH_APPLY_KEEP;
    1009                 : }
    1010                 : /* }}} */
    1011                 : 
    1012                 : /* {{{ _extension_string */
    1013                 : static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC)
    1014               3 : {
    1015               3 :         string_printf(str, "%sExtension [ ", indent);
    1016               3 :         if (module->type == MODULE_PERSISTENT) {
    1017               3 :                 string_printf(str, "<persistent>");
    1018                 :         }
    1019               3 :         if (module->type == MODULE_TEMPORARY) {
    1020               0 :                 string_printf(str, "<temporary>" );
    1021                 :         }
    1022               3 :         string_printf(str, " extension #%d %s version %s ] {\n",
    1023                 :                                         module->module_number, module->name,
    1024                 :                                         (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
    1025                 : 
    1026               3 :         if (module->deps) {
    1027               0 :                 const zend_module_dep* dep = module->deps;
    1028                 : 
    1029               0 :                 string_printf(str, "\n  - Dependencies {\n");
    1030                 : 
    1031               0 :                 while(dep->name) {
    1032               0 :                         string_printf(str, "%s    Dependency [ %s (", indent, dep->name);
    1033                 :                         
    1034               0 :                         switch(dep->type) {
    1035                 :                         case MODULE_DEP_REQUIRED:
    1036               0 :                                 string_write(str, "Required", sizeof("Required") - 1);
    1037               0 :                                 break;
    1038                 :                         case MODULE_DEP_CONFLICTS:
    1039               0 :                                 string_write(str, "Conflicts", sizeof("Conflicts") - 1);
    1040               0 :                                 break;
    1041                 :                         case MODULE_DEP_OPTIONAL:
    1042               0 :                                 string_write(str, "Optional", sizeof("Optional") - 1);
    1043               0 :                                 break;
    1044                 :                         default:
    1045               0 :                                 string_write(str, "Error", sizeof("Error") - 1); /* shouldn't happen */
    1046                 :                                 break;
    1047                 :                         }
    1048                 : 
    1049               0 :                         if (dep->rel) {      
    1050               0 :                                 string_printf(str, " %s", dep->rel);
    1051                 :                         }
    1052               0 :                         if (dep->version) {  
    1053               0 :                                 string_printf(str, " %s", dep->version);
    1054                 :                         }
    1055               0 :                         string_write(str, ") ]\n", sizeof(") ]\n") - 1);
    1056               0 :                         dep++;
    1057                 :                 }
    1058               0 :                 string_printf(str, "%s  }\n", indent);
    1059                 :         }
    1060                 : 
    1061                 :         {
    1062                 :                 string str_ini;
    1063               3 :                 string_init(&str_ini);
    1064               3 :                 zend_hash_apply_with_arguments(EG(ini_directives) TSRMLS_CC, (apply_func_args_t) _extension_ini_string, 3, &str_ini, indent, module->module_number);
    1065               3 :                 if (str_ini.len > 1) {
    1066               1 :                         string_printf(str, "\n  - INI {\n");
    1067               1 :                         string_append(str, &str_ini);
    1068               1 :                         string_printf(str, "%s  }\n", indent);
    1069                 :                 }
    1070               3 :                 string_free(&str_ini);
    1071                 :         }
    1072                 : 
    1073                 :         {
    1074                 :                 string str_constants;
    1075               3 :                 int num_constants = 0;
    1076                 :                 
    1077               3 :                 string_init(&str_constants);
    1078               3 :                 zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
    1079               3 :                 if (num_constants) {
    1080               1 :                         string_printf(str, "\n  - Constants [%d] {\n", num_constants);
    1081               1 :                         string_append(str, &str_constants);
    1082               1 :                         string_printf(str, "%s  }\n", indent);
    1083                 :                 }
    1084               3 :                 string_free(&str_constants);
    1085                 :         }
    1086                 : 
    1087               3 :         if (module->functions && module->functions->fname) {
    1088                 :                 zend_function *fptr;
    1089               1 :                 const zend_function_entry *func = module->functions;
    1090                 : 
    1091               1 :                 string_printf(str, "\n  - Functions {\n");
    1092                 : 
    1093                 :                 /* Is there a better way of doing this? */
    1094              11 :                 while (func->fname) {
    1095               9 :                         if (zend_ascii_hash_find(EG(function_table), func->fname, strlen(func->fname) + 1, (void**) &fptr) == FAILURE) {
    1096               0 :                                 zend_error(E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
    1097               0 :                                 func++;
    1098               0 :                                 continue;
    1099                 :                         }
    1100                 :                         
    1101               9 :                         _function_string(str, fptr, NULL, NULL, NULL, "    " TSRMLS_CC);
    1102               9 :                         func++;
    1103                 :                 }
    1104               1 :                 string_printf(str, "%s  }\n", indent);
    1105                 :         }
    1106                 :         
    1107                 :         {
    1108                 :                 string str_classes;
    1109                 :                 string sub_indent;
    1110               3 :                 int num_classes = 0;
    1111                 :                 
    1112               3 :                 string_init(&sub_indent);
    1113               3 :                 string_printf(&sub_indent, "%s    ", indent);
    1114               3 :                 string_init(&str_classes);
    1115               3 :                 zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) _extension_class_string, 4, &str_classes, sub_indent.string, module, &num_classes);
    1116               3 :                 if (num_classes) {
    1117               2 :                         string_printf(str, "\n  - Classes [%d] {", num_classes);
    1118               2 :                         string_append(str, &str_classes);
    1119               2 :                         string_printf(str, "%s  }\n", indent);
    1120                 :                 }
    1121               3 :                 string_free(&str_classes);
    1122               3 :                 string_free(&sub_indent);
    1123                 :         }
    1124                 : 
    1125               3 :         string_printf(str, "%s}\n", indent);
    1126               3 : }
    1127                 : /* }}} */
    1128                 : 
    1129                 : /* {{{ _function_check_flag */
    1130                 : static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
    1131             410 : {
    1132                 :         reflection_object *intern;
    1133                 :         zend_function *mptr;
    1134                 : 
    1135             410 :         if (zend_parse_parameters_none() == FAILURE) {
    1136               6 :                 return;
    1137                 :         }
    1138             404 :         GET_REFLECTION_OBJECT_PTR(mptr);
    1139             404 :         RETURN_BOOL(mptr->common.fn_flags & mask);
    1140                 : }
    1141                 : /* }}} */
    1142                 : 
    1143                 : /* {{{ zend_reflection_class_factory */
    1144                 : PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC)
    1145             129 : {
    1146                 :         reflection_object *intern;
    1147                 :         zval *name;
    1148                 : 
    1149             129 :         MAKE_STD_ZVAL(name);
    1150             129 :         ZVAL_UNICODEL(name, ce->name.u, ce->name_length, 1);
    1151             129 :         reflection_instantiate(reflection_class_ptr, object TSRMLS_CC);
    1152             129 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1153             129 :         intern->ptr = ce;
    1154             129 :         intern->ref_type = REF_TYPE_OTHER;
    1155             129 :         intern->ce = ce;
    1156             129 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1157             129 : }
    1158                 : /* }}} */
    1159                 : 
    1160                 : /* {{{ reflection_extension_factory */
    1161                 : static void reflection_extension_factory(zval *object, const char *name_str TSRMLS_DC)
    1162               2 : {
    1163                 :         reflection_object *intern;
    1164                 :         zval *name;
    1165               2 :         int name_len = strlen(name_str);
    1166                 :         char *lcname;
    1167                 :         struct _zend_module_entry *module;
    1168                 :         ALLOCA_FLAG(use_heap)
    1169                 : 
    1170               2 :         lcname = do_alloca(name_len + 1, use_heap);
    1171               2 :         zend_str_tolower_copy(lcname, name_str, name_len);
    1172               2 :         if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
    1173               0 :                 free_alloca(lcname, use_heap);
    1174               0 :                 return;
    1175                 :         }
    1176               2 :         free_alloca(lcname, use_heap);
    1177                 : 
    1178               2 :         reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC);
    1179               2 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1180               2 :         MAKE_STD_ZVAL(name);
    1181               2 :         ZVAL_ASCII_STRINGL(name, module->name, name_len, 1);
    1182               2 :         intern->ptr = module;
    1183               2 :         intern->ref_type = REF_TYPE_OTHER;
    1184               2 :         intern->ce = NULL;
    1185               2 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1186                 : }
    1187                 : /* }}} */
    1188                 : 
    1189                 : /* {{{ reflection_parameter_factory */
    1190                 : static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, zval *object TSRMLS_DC)
    1191              63 : {
    1192                 :         reflection_object *intern;
    1193                 :         parameter_reference *reference;
    1194                 :         zval *name;
    1195                 : 
    1196              63 :         MAKE_STD_ZVAL(name);
    1197              63 :         if (arg_info->name.v) {
    1198              63 :                 ZVAL_UNICODEL(name, arg_info->name.u, arg_info->name_len, 1);
    1199                 :         } else {
    1200               0 :                 ZVAL_NULL(name);
    1201                 :         }
    1202              63 :         reflection_instantiate(reflection_parameter_ptr, object TSRMLS_CC);
    1203              63 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1204              63 :         reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
    1205              63 :         reference->arg_info = arg_info;
    1206              63 :         reference->offset = offset;
    1207              63 :         reference->required = required;
    1208              63 :         reference->fptr = fptr;
    1209              63 :         intern->ptr = reference;
    1210              63 :         intern->ref_type = REF_TYPE_PARAMETER;
    1211              63 :         intern->ce = fptr->common.scope;
    1212              63 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1213              63 : }
    1214                 : /* }}} */
    1215                 : 
    1216                 : /* {{{ reflection_function_factory */
    1217                 : static void reflection_function_factory(zend_function *function, zval *object TSRMLS_DC)
    1218             534 : {
    1219                 :         reflection_object *intern;
    1220                 :         zval *name;
    1221                 : 
    1222             534 :         MAKE_STD_ZVAL(name);
    1223             534 :         ZVAL_UNICODE(name, function->common.function_name.u, 1);
    1224                 : 
    1225             534 :         reflection_instantiate(reflection_function_ptr, object TSRMLS_CC);
    1226             534 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1227             534 :         intern->ptr = function;
    1228             534 :         intern->ref_type = REF_TYPE_FUNCTION;
    1229             534 :         intern->ce = NULL;
    1230             534 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1231             534 : }
    1232                 : /* }}} */
    1233                 : 
    1234                 : /* {{{ reflection_method_factory */
    1235                 : static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *object TSRMLS_DC)
    1236             292 : {
    1237                 :         reflection_object *intern;
    1238                 :         zval *name;
    1239                 :         zval *classname;
    1240                 : 
    1241             292 :         MAKE_STD_ZVAL(name);
    1242             292 :         MAKE_STD_ZVAL(classname);
    1243             292 :         ZVAL_UNICODE(name, method->common.function_name.u, 1);
    1244             292 :         ZVAL_UNICODEL(classname, method->common.scope->name.u, method->common.scope->name_length, 1);
    1245                 : 
    1246             292 :         reflection_instantiate(reflection_method_ptr, object TSRMLS_CC);
    1247             292 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1248             292 :         intern->ptr = method;
    1249             292 :         intern->ref_type = REF_TYPE_FUNCTION;
    1250             292 :         intern->ce = ce;
    1251             292 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1252             292 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
    1253             292 : }
    1254                 : /* }}} */
    1255                 : 
    1256                 : /* {{{ reflection_property_factory */
    1257                 : static void reflection_property_factory(zend_class_entry *ce, zend_property_info *prop, zval *object TSRMLS_DC)
    1258             168 : {
    1259                 :         reflection_object *intern;
    1260                 :         zval *name;
    1261                 :         zval *classname;
    1262                 :         property_reference *reference;
    1263                 :         zstr class_name, prop_name;
    1264             168 :         zend_uchar utype = IS_UNICODE;
    1265                 : 
    1266             168 :         zend_u_unmangle_property_name(utype, prop->name, prop->name_length, &class_name, &prop_name);
    1267                 :         
    1268             168 :         if (!(prop->flags & ZEND_ACC_PRIVATE)) {
    1269                 :                 /* we have to search the class hierarchy for this (implicit) public or protected property */
    1270             128 :                 zend_class_entry *tmp_ce = ce, *store_ce = ce;
    1271             128 :                 zend_property_info *tmp_info = NULL;
    1272             128 :                 int prop_name_len = u_strlen(prop_name.u);
    1273                 :                 
    1274             268 :                 while (tmp_ce && zend_u_hash_find(&tmp_ce->properties_info, utype, prop_name, prop_name_len + 1, (void **) &tmp_info) != SUCCESS) {
    1275              12 :                         ce = tmp_ce;
    1276              12 :                         tmp_ce = tmp_ce->parent;
    1277                 :                 }
    1278                 : 
    1279             246 :                 if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */
    1280             118 :                         prop = tmp_info;
    1281                 :                 } else { /* not found, use initial value */
    1282              10 :                         ce = store_ce;
    1283                 :                 }
    1284                 :         }
    1285                 : 
    1286             168 :         MAKE_STD_ZVAL(name);
    1287             168 :         MAKE_STD_ZVAL(classname);
    1288             168 :         ZVAL_UNICODE(name, prop_name.u, 1);
    1289             168 :         ZVAL_UNICODEL(classname, prop->ce->name.u, prop->ce->name_length, 1);
    1290                 : 
    1291             168 :         reflection_instantiate(reflection_property_ptr, object TSRMLS_CC);
    1292             168 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1293             168 :         reference = (property_reference*) emalloc(sizeof(property_reference));
    1294             168 :         reference->ce = ce;
    1295             168 :         reference->prop = *prop;
    1296             168 :         intern->ptr = reference;
    1297             168 :         intern->ref_type = REF_TYPE_PROPERTY;
    1298             168 :         intern->ce = ce;
    1299             168 :         intern->ignore_visibility = 0;
    1300             168 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1301             168 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
    1302             168 : }
    1303                 : /* }}} */
    1304                 : 
    1305                 : /* {{{ _reflection_export */
    1306                 : static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
    1307              44 : {
    1308                 :         zval *reflector_ptr;
    1309              44 :         zval output, *output_ptr = &output;
    1310                 :         zval *argument_ptr, *argument2_ptr;
    1311                 :         zval *retval_ptr, **params[2];
    1312                 :         int result;
    1313              44 :         int return_output = 0;
    1314                 :         zend_fcall_info fci;
    1315                 :         zend_fcall_info_cache fcc;
    1316                 :         zval fname;
    1317                 : 
    1318              44 :         if (ctor_argc == 1) {
    1319              13 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &argument_ptr, &return_output) == FAILURE) {
    1320               0 :                         return;
    1321                 :                 }
    1322                 :         } else {
    1323              31 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
    1324               4 :                         return;
    1325                 :                 }
    1326                 :         }
    1327                 : 
    1328              40 :         INIT_PZVAL(&output);
    1329                 : 
    1330                 :         /* Create object */
    1331              40 :         MAKE_STD_ZVAL(reflector_ptr);
    1332              40 :         if (object_and_properties_init(reflector_ptr, ce_ptr, NULL) == FAILURE) {
    1333               0 :                 _DO_THROW("Could not create reflector");
    1334                 :         }
    1335                 : 
    1336                 :         /* Call __construct() */
    1337              40 :         params[0] = &argument_ptr;
    1338              40 :         params[1] = &argument2_ptr;
    1339                 : 
    1340              40 :         fci.size = sizeof(fci);
    1341              40 :         fci.function_table = NULL;
    1342              40 :         fci.function_name = NULL;
    1343              40 :         fci.symbol_table = NULL;
    1344              40 :         fci.object_ptr = reflector_ptr;
    1345              40 :         fci.retval_ptr_ptr = &retval_ptr;
    1346              40 :         fci.param_count = ctor_argc;
    1347              40 :         fci.params = params;
    1348              40 :         fci.no_separation = 1;
    1349                 : 
    1350              40 :         fcc.initialized = 1;
    1351              40 :         fcc.function_handler = ce_ptr->constructor;
    1352              40 :         fcc.calling_scope = ce_ptr;
    1353              40 :         fcc.called_scope = Z_OBJCE_P(reflector_ptr);
    1354              40 :         fcc.object_ptr = reflector_ptr;
    1355                 : 
    1356              40 :         result = zend_call_function(&fci, &fcc TSRMLS_CC);
    1357                 :         
    1358              40 :         if (retval_ptr) {
    1359              33 :                 zval_ptr_dtor(&retval_ptr);
    1360                 :         }
    1361                 : 
    1362              40 :         if (EG(exception)) {
    1363               7 :                 zval_ptr_dtor(&reflector_ptr);
    1364               7 :                 return;
    1365                 :         }
    1366              33 :         if (result == FAILURE) {
    1367               0 :                 zval_ptr_dtor(&reflector_ptr);
    1368               0 :                 _DO_THROW("Could not create reflector");
    1369                 :         }
    1370                 : 
    1371                 :         /* Call static reflection::export */
    1372              33 :         ZVAL_BOOL(&output, return_output);
    1373              33 :         params[0] = &reflector_ptr;
    1374              33 :         params[1] = &output_ptr;
    1375                 : 
    1376              33 :         ZVAL_ASCII_STRINGL(&fname, "reflection::export", sizeof("reflection::export") - 1, 1);
    1377              33 :         fci.function_table = &reflection_ptr->function_table;
    1378              33 :         fci.function_name = &fname;
    1379              33 :         fci.object_ptr = NULL;
    1380              33 :         fci.retval_ptr_ptr = &retval_ptr;
    1381              33 :         fci.param_count = 2;
    1382              33 :         fci.params = params;
    1383              33 :         fci.no_separation = 1;
    1384                 : 
    1385              33 :         result = zend_call_function(&fci, NULL TSRMLS_CC);
    1386                 : 
    1387              33 :         zval_dtor(&fname);
    1388                 : 
    1389              33 :         if (result == FAILURE && EG(exception) == NULL) {
    1390               0 :                 zval_ptr_dtor(&reflector_ptr);
    1391               0 :                 zval_ptr_dtor(&retval_ptr);
    1392               0 :                 _DO_THROW("Could not execute reflection::export()");
    1393                 :         }
    1394                 : 
    1395              33 :         if (return_output) {
    1396              13 :                 COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
    1397                 :         } else {
    1398              20 :                 zval_ptr_dtor(&retval_ptr);
    1399                 :         }
    1400                 : 
    1401                 :         /* Destruct reflector which is no longer needed */
    1402              33 :         zval_ptr_dtor(&reflector_ptr);
    1403                 : }
    1404                 : /* }}} */
    1405                 : 
    1406                 : /* {{{ Preventing __clone from being called */
    1407                 : ZEND_METHOD(reflection, __clone)
    1408               0 : {
    1409                 :         /* Should never be executable */
    1410               0 :         _DO_THROW("Cannot clone object using __clone()");
    1411                 : }
    1412                 : /* }}} */
    1413                 : 
    1414                 : /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return]) U
    1415                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    1416                 : ZEND_METHOD(reflection, export)
    1417             165 : {
    1418                 :         zval *object, fname, *retval_ptr;
    1419                 :         int result;
    1420             165 :         zend_bool return_output = 0;
    1421                 : 
    1422             165 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &object, reflector_ptr, &return_output) == FAILURE) {
    1423               2 :                 return;
    1424                 :         }
    1425                 : 
    1426                 :         /* Invoke the __toString() method */
    1427             163 :         ZVAL_ASCII_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1, 1);
    1428             163 :         result= call_user_function_ex(NULL, &object, &fname, &retval_ptr, 0, NULL, 0, NULL TSRMLS_CC);
    1429             163 :         zval_dtor(&fname);
    1430                 : 
    1431             163 :         if (result == FAILURE) {
    1432               0 :                 _DO_THROW("Invocation of method __toString() failed");
    1433                 :                 /* Returns from this function */
    1434                 :         }
    1435                 : 
    1436             163 :         if (!retval_ptr) {
    1437               0 :                 zend_error(E_WARNING, "%v::__toString() did not return anything", Z_OBJCE_P(object)->name);
    1438               0 :                 RETURN_FALSE;
    1439                 :         }
    1440                 : 
    1441             163 :         if (return_output) {
    1442              13 :                 COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
    1443                 :         } else {
    1444                 :                 /* No need for _r variant, return of __toString should always be a string */
    1445             150 :                 zend_print_zval(retval_ptr, 0);
    1446             150 :                 zend_printf("\n");
    1447             150 :                 zval_ptr_dtor(&retval_ptr);
    1448                 :         }
    1449                 : }
    1450                 : /* }}} */
    1451                 : 
    1452                 : /* {{{ proto public static array Reflection::getModifierNames(int modifiers) U
    1453                 :    Returns an array of modifier names */
    1454                 : ZEND_METHOD(reflection, getModifierNames)
    1455              17 : {
    1456                 :         long modifiers;
    1457                 : 
    1458              17 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &modifiers) == FAILURE) {
    1459               0 :                 return;
    1460                 :         }
    1461                 : 
    1462              17 :         array_init(return_value);
    1463                 : 
    1464              17 :         if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
    1465               3 :                 add_next_index_ascii_stringl(return_value, "abstract", sizeof("abstract")-1, 1);
    1466                 :         }
    1467              17 :         if (modifiers & (ZEND_ACC_FINAL | ZEND_ACC_FINAL_CLASS)) {
    1468               3 :                 add_next_index_ascii_stringl(return_value, "final", sizeof("final")-1, 1);
    1469                 :         }
    1470              17 :         if (modifiers & ZEND_ACC_IMPLICIT_PUBLIC) {
    1471               1 :                 add_next_index_ascii_stringl(return_value, "public", sizeof("public")-1, 1);
    1472                 :         }
    1473                 : 
    1474                 :         /* These are mutually exclusive */
    1475              17 :         switch (modifiers & ZEND_ACC_PPP_MASK) {
    1476                 :                 case ZEND_ACC_PUBLIC:
    1477               7 :                         add_next_index_ascii_stringl(return_value, "public", sizeof("public")-1, 1);
    1478               7 :                         break;
    1479                 :                 case ZEND_ACC_PRIVATE:
    1480               2 :                         add_next_index_ascii_stringl(return_value, "private", sizeof("private")-1, 1);
    1481               2 :                         break;
    1482                 :                 case ZEND_ACC_PROTECTED:
    1483               4 :                         add_next_index_ascii_stringl(return_value, "protected", sizeof("protected")-1, 1);
    1484                 :                         break;
    1485                 :         }
    1486                 : 
    1487              17 :         if (modifiers & ZEND_ACC_STATIC) {
    1488               3 :                 add_next_index_ascii_stringl(return_value, "static", sizeof("static")-1, 1);
    1489                 :         }
    1490                 : }
    1491                 : /* }}} */
    1492                 : 
    1493                 : /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return]) U
    1494                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    1495                 : ZEND_METHOD(reflection_function, export)
    1496               2 : {
    1497               2 :         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
    1498               2 : }
    1499                 : /* }}} */
    1500                 : 
    1501                 : /* {{{ proto public void ReflectionFunction::__construct(string name) U
    1502                 :    Constructor. Throws an Exception in case the given function does not exist */
    1503                 : ZEND_METHOD(reflection_function, __construct)
    1504             168 : {
    1505                 :         zval *name;
    1506                 :         zval *object;
    1507             168 :         zval *closure = NULL;
    1508                 :         unsigned int lcname_len;
    1509                 :         zstr lcname;
    1510                 :         reflection_object *intern;
    1511                 :         zend_function *fptr;
    1512                 :         zstr name_str;
    1513                 :         int name_len;
    1514                 :         zend_uchar type;
    1515                 : 
    1516             168 :         object = getThis();
    1517             168 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    1518             168 :         if (intern == NULL) {
    1519               0 :                 return;
    1520                 :         }
    1521                 : 
    1522             168 :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &closure, zend_ce_closure) == SUCCESS) {
    1523               3 :                 fptr = (zend_function*)zend_get_closure_method_def(closure TSRMLS_CC);
    1524               3 :                 Z_ADDREF_P(closure);
    1525             165 :         } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name_str, &name_len, &type) == SUCCESS) {
    1526                 :                 zstr nsname;
    1527                 : 
    1528             162 :                 lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
    1529                 : 
    1530                 :                 /* Ignore leading "\" */
    1531             162 :                 nsname = lcname;
    1532             162 :                 if (lcname.s[0] == '\\') {
    1533               1 :                         if (type == IS_UNICODE) {
    1534               1 :                                 nsname.u = &lcname.u[1];
    1535                 :                         } else {
    1536               0 :                                 nsname.s = &lcname.s[1];
    1537                 :                         }
    1538               1 :                         lcname_len--;
    1539                 :                 }
    1540                 : 
    1541             162 :                 if (zend_u_hash_find(EG(function_table), type, nsname, lcname_len + 1, (void **)&fptr) == FAILURE) {
    1542               3 :                         efree(lcname.v);
    1543               3 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    1544                 :                                 "Function %R() does not exist", type, name_str);
    1545               3 :                         return;
    1546                 :                 }
    1547             159 :                 efree(lcname.v);
    1548                 :         } else {
    1549               3 :                 return;
    1550                 :         }
    1551                 : 
    1552             162 :         MAKE_STD_ZVAL(name);
    1553             162 :         ZVAL_UNICODE(name, fptr->common.function_name.u, 1);
    1554             162 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    1555             162 :         intern->ptr = fptr;
    1556             162 :         intern->ref_type = REF_TYPE_FUNCTION;
    1557             162 :         intern->obj = closure;
    1558             162 :         intern->ce = NULL;
    1559                 : }
    1560                 : /* }}} */
    1561                 : 
    1562                 : /* {{{ proto public string ReflectionFunction::__toString() U
    1563                 :    Returns a string representation */
    1564                 : ZEND_METHOD(reflection_function, __toString)
    1565             125 : {
    1566                 :         reflection_object *intern;
    1567                 :         zend_function *fptr;
    1568                 :         string str;
    1569                 :         zval* name;
    1570                 : 
    1571             125 :         if (zend_parse_parameters_none() == FAILURE) {
    1572               0 :                 return;
    1573                 :         }
    1574             125 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1575             125 :         _default_lookup_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
    1576             125 :         string_init(&str);
    1577             125 :         _function_string(&str, fptr, intern->ce, name, intern->obj, "" TSRMLS_CC);
    1578             125 :         RETURN_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), str.string, str.len - 1, ZSTR_AUTOFREE);
    1579                 : }
    1580                 : /* }}} */
    1581                 : 
    1582                 : /* {{{ proto public string ReflectionFunction::getName() U
    1583                 :    Returns this function's name */
    1584                 : ZEND_METHOD(reflection_function, getName)
    1585             192 : {
    1586             192 :         if (zend_parse_parameters_none() == FAILURE) {
    1587               1 :                 return;
    1588                 :         }
    1589             191 :         _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
    1590                 : }
    1591                 : /* }}} */
    1592                 : 
    1593                 : /* {{{ proto public bool ReflectionFunction::isClosure() U
    1594                 :    Returns whether this is a closure */
    1595                 : ZEND_METHOD(reflection_function, isClosure)
    1596               3 : {
    1597                 :         reflection_object *intern;
    1598                 :         zend_function *fptr;
    1599                 : 
    1600               3 :         if (zend_parse_parameters_none() == FAILURE) {
    1601               0 :                 return;
    1602                 :         }
    1603               3 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1604               3 :         RETURN_BOOL(intern->obj);
    1605                 : }
    1606                 : /* }}} */
    1607                 : 
    1608                 : /* {{{ proto public bool ReflectionFunction::getClosureThis() U
    1609                 :    Returns this pointer bound to closure */
    1610                 : ZEND_METHOD(reflection_function, getClosureThis)
    1611               2 : {
    1612                 :         reflection_object *intern;
    1613                 :         zend_function *fptr;
    1614                 :         zval* closure_this;
    1615                 : 
    1616               2 :         if (zend_parse_parameters_none() == FAILURE) {
    1617               0 :                 return;
    1618                 :         }
    1619               2 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1620               2 :         if (intern->obj) {
    1621               2 :                 closure_this = zend_get_closure_this_ptr(intern->obj TSRMLS_CC);
    1622               2 :                 if (closure_this) {
    1623               1 :                         RETURN_ZVAL(closure_this, 1, 0);
    1624                 :                 }
    1625                 :         }
    1626                 : }
    1627                 : /* }}} */
    1628                 : 
    1629                 : /* {{{ proto public bool ReflectionFunction::isInternal() U
    1630                 :    Returns whether this is an internal function */
    1631                 : ZEND_METHOD(reflection_function, isInternal)
    1632              72 : {
    1633                 :         reflection_object *intern;
    1634                 :         zend_function *fptr;
    1635                 : 
    1636              72 :         if (zend_parse_parameters_none() == FAILURE) {
    1637               1 :                 return;
    1638                 :         }
    1639              71 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1640              71 :         RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
    1641                 : }
    1642                 : /* }}} */
    1643                 : 
    1644                 : /* {{{ proto public bool ReflectionFunction::isUserDefined() U
    1645                 :    Returns whether this is an user-defined function */
    1646                 : ZEND_METHOD(reflection_function, isUserDefined)
    1647              72 : {
    1648                 :         reflection_object *intern;
    1649                 :         zend_function *fptr;
    1650                 : 
    1651              72 :         if (zend_parse_parameters_none() == FAILURE) {
    1652               1 :                 return;
    1653                 :         }
    1654              71 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1655              71 :         RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
    1656                 : }
    1657                 : /* }}} */
    1658                 : 
    1659                 : /* {{{ proto public bool ReflectionFunction::isDisabled() U
    1660                 :    Returns whether this function has been disabled or not */
    1661                 : ZEND_METHOD(reflection_function, isDisabled)
    1662               1 : {
    1663                 :         reflection_object *intern;
    1664                 :         zend_function *fptr;
    1665                 : 
    1666               1 :         METHOD_NOTSTATIC(reflection_function_ptr);
    1667               1 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1668               1 :         RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
    1669                 : }
    1670                 : /* }}} */
    1671                 : 
    1672                 : /* {{{ proto public string ReflectionFunction::getFileName() U
    1673                 :    Returns the filename of the file this function was declared in */
    1674                 : ZEND_METHOD(reflection_function, getFileName)
    1675              14 : {
    1676                 :         reflection_object *intern;
    1677                 :         zend_function *fptr;
    1678                 : 
    1679              14 :         if (zend_parse_parameters_none() == FAILURE) {
    1680               1 :                 return;
    1681                 :         }
    1682              13 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1683              13 :         if (fptr->type == ZEND_USER_FUNCTION) {
    1684              11 :                 RETURN_RT_STRING(fptr->op_array.filename, 1);
    1685                 :         }
    1686               2 :         RETURN_FALSE;
    1687                 : }
    1688                 : /* }}} */
    1689                 : 
    1690                 : /* {{{ proto public int ReflectionFunction::getStartLine() U
    1691                 :    Returns the line this function's declaration starts at */
    1692                 : ZEND_METHOD(reflection_function, getStartLine)
    1693              13 : {
    1694                 :         reflection_object *intern;
    1695                 :         zend_function *fptr;
    1696                 : 
    1697              13 :         if (zend_parse_parameters_none() == FAILURE) {
    1698               1 :                 return;
    1699                 :         }
    1700              12 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1701              12 :         if (fptr->type == ZEND_USER_FUNCTION) {
    1702              10 :                 RETURN_LONG(fptr->op_array.line_start);
    1703                 :         }
    1704               2 :         RETURN_FALSE;
    1705                 : }
    1706                 : /* }}} */
    1707                 : 
    1708                 : /* {{{ proto public int ReflectionFunction::getEndLine() U
    1709                 :    Returns the line this function's declaration ends at */
    1710                 : ZEND_METHOD(reflection_function, getEndLine)
    1711              13 : {
    1712                 :         reflection_object *intern;
    1713                 :         zend_function *fptr;
    1714                 : 
    1715              13 :         if (zend_parse_parameters_none() == FAILURE) {
    1716               1 :                 return;
    1717                 :         }
    1718              12 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1719              12 :         if (fptr->type == ZEND_USER_FUNCTION) {
    1720              10 :                 RETURN_LONG(fptr->op_array.line_end);
    1721                 :         }
    1722               2 :         RETURN_FALSE;
    1723                 : }
    1724                 : /* }}} */
    1725                 : 
    1726                 : /* {{{ proto public string ReflectionFunction::getDocComment() U
    1727                 :    Returns the doc comment for this function */
    1728                 : ZEND_METHOD(reflection_function, getDocComment)
    1729              19 : {
    1730                 :         reflection_object *intern;
    1731                 :         zend_function *fptr;
    1732                 : 
    1733              19 :         if (zend_parse_parameters_none() == FAILURE) {
    1734               2 :                 return;
    1735                 :         }
    1736              17 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1737              17 :         if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment.v) {
    1738              11 :                 RETURN_ZSTRL(IS_UNICODE, fptr->op_array.doc_comment, fptr->op_array.doc_comment_len, 1);
    1739                 :         }
    1740               6 :         RETURN_FALSE;
    1741                 : }
    1742                 : /* }}} */
    1743                 : 
    1744                 : /* {{{ proto public array ReflectionFunction::getStaticVariables() U
    1745                 :    Returns an associative array containing this function's static variables and their values */
    1746                 : ZEND_METHOD(reflection_function, getStaticVariables)
    1747              69 : {
    1748                 :         zval *tmp_copy;
    1749                 :         reflection_object *intern;
    1750                 :         zend_function *fptr;
    1751                 :         
    1752              69 :         if (zend_parse_parameters_none() == FAILURE) {
    1753               1 :                 return;
    1754                 :         }
    1755              68 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1756                 : 
    1757                 :         /* Return an empty array in case no static variables exist */
    1758              68 :         array_init(return_value);
    1759              68 :         if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
    1760               5 :                 zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
    1761               5 :                 zend_hash_copy(Z_ARRVAL_P(return_value), fptr->op_array.static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
    1762                 :         }
    1763                 : }
    1764                 : /* }}} */
    1765                 : 
    1766                 : /* {{{ proto public mixed ReflectionFunction::getClosure()
    1767                 :    Returns a dynamically created closure for the function */
    1768                 : ZEND_METHOD(reflection_function, getClosure)
    1769               3 : {
    1770                 :         reflection_object *intern;
    1771                 :         zend_function *fptr;
    1772                 :         
    1773               3 :         if (zend_parse_parameters_none() == FAILURE) {
    1774               1 :                 return;
    1775                 :         }
    1776               2 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1777                 : 
    1778               2 :         zend_create_closure(return_value, fptr, NULL, NULL TSRMLS_CC);
    1779                 : }
    1780                 : /* }}} */
    1781                 : 
    1782                 : /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args]) U
    1783                 :    Invokes the function */
    1784                 : ZEND_METHOD(reflection_function, invoke)
    1785               3 : {
    1786                 :         zval *retval_ptr;
    1787               3 :         zval ***params = NULL;
    1788               3 :         int result, num_args = 0;
    1789                 :         zend_fcall_info fci;
    1790                 :         zend_fcall_info_cache fcc;
    1791                 :         reflection_object *intern;
    1792                 :         zend_function *fptr;
    1793                 :         
    1794               3 :         METHOD_NOTSTATIC(reflection_function_ptr);
    1795               3 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1796                 : 
    1797               3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &params, &num_args) == FAILURE) {
    1798               0 :                 return;
    1799                 :         }
    1800                 : 
    1801               3 :         fci.size = sizeof(fci);
    1802               3 :         fci.function_table = NULL;
    1803               3 :         fci.function_name = NULL;
    1804               3 :         fci.symbol_table = NULL;
    1805               3 :         fci.object_ptr = NULL;
    1806               3 :         fci.retval_ptr_ptr = &retval_ptr;
    1807               3 :         fci.param_count = num_args;
    1808               3 :         fci.params = params;
    1809               3 :         fci.no_separation = 1;
    1810                 : 
    1811               3 :         fcc.initialized = 1;
    1812               3 :         fcc.function_handler = fptr;
    1813               3 :         fcc.calling_scope = EG(scope);
    1814               3 :         fcc.called_scope = NULL;
    1815               3 :         fcc.object_ptr = NULL;
    1816                 : 
    1817               3 :         result = zend_call_function(&fci, &fcc TSRMLS_CC);
    1818                 : 
    1819               3 :         if (num_args) {
    1820               2 :                 efree(params);
    1821                 :         }
    1822                 : 
    1823               3 :         if (result == FAILURE) {
    1824               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    1825                 :                         "Invocation of function %v() failed", fptr->common.function_name);
    1826               0 :                 return;
    1827                 :         }
    1828                 : 
    1829               3 :         if (retval_ptr) {
    1830               3 :                 COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
    1831                 :         }
    1832                 : }
    1833                 : /* }}} */
    1834                 : 
    1835                 : static int _zval_array_to_c_array(zval **arg, zval ****params TSRMLS_DC) /* {{{ */
    1836              25 : {
    1837              25 :         *(*params)++ = arg;
    1838              25 :         return ZEND_HASH_APPLY_KEEP;
    1839                 : } /* }}} */
    1840                 : 
    1841                 : /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args) U
    1842                 :    Invokes the function and pass its arguments as array. */
    1843                 : ZEND_METHOD(reflection_function, invokeArgs)
    1844               2 : {
    1845                 :         zval *retval_ptr;
    1846                 :         zval ***params;
    1847                 :         int result;
    1848                 :         int argc;
    1849                 :         zend_fcall_info fci;
    1850                 :         zend_fcall_info_cache fcc;
    1851                 :         reflection_object *intern;
    1852                 :         zend_function *fptr;
    1853                 :         zval *param_array;
    1854                 :         
    1855               2 :         METHOD_NOTSTATIC(reflection_function_ptr);
    1856               2 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1857                 : 
    1858               2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &param_array) == FAILURE) {
    1859               0 :                 return;
    1860                 :         }
    1861                 : 
    1862               2 :         argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
    1863                 :         
    1864               2 :         params = safe_emalloc(sizeof(zval **), argc, 0);
    1865               2 :         zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);        
    1866               2 :         params -= argc;
    1867                 : 
    1868               2 :         fci.size = sizeof(fci);
    1869               2 :         fci.function_table = NULL;
    1870               2 :         fci.function_name = NULL;
    1871               2 :         fci.symbol_table = NULL;
    1872               2 :         fci.object_ptr = NULL;
    1873               2 :         fci.retval_ptr_ptr = &retval_ptr;
    1874               2 :         fci.param_count = argc;
    1875               2 :         fci.params = params;
    1876               2 :         fci.no_separation = 1;
    1877                 : 
    1878               2 :         fcc.initialized = 1;
    1879               2 :         fcc.function_handler = fptr;
    1880               2 :         fcc.calling_scope = EG(scope);
    1881               2 :         fcc.called_scope = NULL;
    1882               2 :         fcc.object_ptr = NULL;
    1883                 : 
    1884               2 :         result = zend_call_function(&fci, &fcc TSRMLS_CC);
    1885                 : 
    1886               2 :         efree(params);
    1887                 : 
    1888               2 :         if (result == FAILURE) {
    1889               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    1890                 :                         "Invocation of function %v() failed", fptr->common.function_name);
    1891               0 :                 return;
    1892                 :         }
    1893                 : 
    1894               2 :         if (retval_ptr) {
    1895               2 :                 COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
    1896                 :         }
    1897                 : }
    1898                 : /* }}} */
    1899                 : 
    1900                 : /* {{{ proto public bool ReflectionFunction::returnsReference() U
    1901                 :    Gets whether this function returns a reference */
    1902                 : ZEND_METHOD(reflection_function, returnsReference)
    1903              62 : {
    1904                 :         reflection_object *intern;
    1905                 :         zend_function *fptr;
    1906                 : 
    1907              62 :         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
    1908              62 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1909                 : 
    1910              62 :         RETURN_BOOL(fptr->op_array.return_reference);
    1911                 : }
    1912                 : /* }}} */
    1913                 : 
    1914                 : /* {{{ proto public bool ReflectionFunction::getNumberOfParameters() U
    1915                 :    Gets the number of required parameters */
    1916                 : ZEND_METHOD(reflection_function, getNumberOfParameters)
    1917              65 : {
    1918                 :         reflection_object *intern;
    1919                 :         zend_function *fptr;
    1920                 : 
    1921              65 :         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
    1922              65 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1923                 : 
    1924              65 :         RETURN_LONG(fptr->common.num_args);
    1925                 : }
    1926                 : /* }}} */
    1927                 : 
    1928                 : /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters() U
    1929                 :    Gets the number of required parameters */
    1930                 : ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
    1931              66 : {
    1932                 :         reflection_object *intern;
    1933                 :         zend_function *fptr;
    1934                 : 
    1935              66 :         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
    1936              66 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1937                 : 
    1938              66 :         RETURN_LONG(fptr->common.required_num_args);
    1939                 : }
    1940                 : /* }}} */
    1941                 : 
    1942                 : /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters() U
    1943                 :    Returns an array of parameter objects for this function */
    1944                 : ZEND_METHOD(reflection_function, getParameters)
    1945              84 : {
    1946                 :         reflection_object *intern;
    1947                 :         zend_function *fptr;
    1948                 :         zend_uint i;
    1949                 :         struct _zend_arg_info *arg_info;
    1950                 : 
    1951              84 :         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
    1952              84 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1953                 : 
    1954              84 :         arg_info= fptr->common.arg_info;
    1955                 : 
    1956              84 :         array_init(return_value);
    1957             147 :         for (i = 0; i < fptr->common.num_args; i++) {
    1958                 :                 zval *parameter;   
    1959                 : 
    1960              63 :                 ALLOC_ZVAL(parameter);
    1961              63 :                 reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
    1962              63 :                 add_next_index_zval(return_value, parameter);
    1963                 : 
    1964              63 :                 arg_info++;
    1965                 :         }
    1966                 : }
    1967                 : /* }}} */
    1968                 : 
    1969                 : /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension() U
    1970                 :    Returns NULL or the extension the function belongs to */
    1971                 : ZEND_METHOD(reflection_function, getExtension)
    1972               2 : {
    1973                 :         reflection_object *intern;
    1974                 :         zend_function *fptr;
    1975                 :         zend_internal_function *internal;
    1976                 : 
    1977               2 :         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
    1978               2 :         GET_REFLECTION_OBJECT_PTR(fptr);
    1979                 : 
    1980               2 :         if (fptr->type != ZEND_INTERNAL_FUNCTION) {
    1981               1 :                 RETURN_NULL();
    1982                 :         }
    1983                 : 
    1984               1 :         internal = (zend_internal_function *)fptr;
    1985               1 :         if (internal->module) {
    1986               1 :                 reflection_extension_factory(return_value, internal->module->name TSRMLS_CC);
    1987                 :         } else {
    1988               0 :                 RETURN_NULL();
    1989                 :         }
    1990                 : }
    1991                 : /* }}} */
    1992                 : 
    1993                 : /* {{{ proto public string|false ReflectionFunction::getExtensionName() U
    1994                 :    Returns false or the name of the extension the function belongs to */
    1995                 : ZEND_METHOD(reflection_function, getExtensionName)
    1996               3 : {
    1997                 :         reflection_object *intern;
    1998                 :         zend_function *fptr;
    1999                 :         zend_internal_function *internal;
    2000                 : 
    2001               3 :         METHOD_NOTSTATIC(reflection_function_abstract_ptr);
    2002               3 :         GET_REFLECTION_OBJECT_PTR(fptr);
    2003                 : 
    2004               3 :         if (fptr->type != ZEND_INTERNAL_FUNCTION) {
    2005               1 :                 RETURN_FALSE;
    2006                 :         }
    2007                 : 
    2008               2 :         internal = (zend_internal_function *)fptr;
    2009               2 :         if (internal->module) {
    2010               2 :                 RETURN_ASCII_STRING(internal->module->name, 1);
    2011                 :         } else {
    2012               0 :                 RETURN_FALSE;
    2013                 :         }
    2014                 : }
    2015                 : /* }}} */
    2016                 : 
    2017                 : /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException U
    2018                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    2019                 : ZEND_METHOD(reflection_parameter, export)
    2020               8 : {
    2021               8 :         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
    2022               8 : }
    2023                 : /* }}} */
    2024                 : 
    2025                 : /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter) U
    2026                 :    Constructor. Throws an Exception in case the given method does not exist */
    2027                 : ZEND_METHOD(reflection_parameter, __construct)
    2028              25 : {
    2029                 :         parameter_reference *ref;
    2030                 :         zval *reference, **parameter;
    2031                 :         zval *object;
    2032                 :         zval *name;
    2033                 :         reflection_object *intern;
    2034                 :         zend_function *fptr;
    2035                 :         struct _zend_arg_info *arg_info;
    2036                 :         int position;
    2037              25 :         zend_class_entry *ce = NULL;
    2038                 : 
    2039              25 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zZ", &reference, &parameter) == FAILURE) {
    2040               0 :                 return;
    2041                 :         }
    2042                 : 
    2043              25 :         object = getThis();
    2044              25 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    2045              25 :         if (intern == NULL) {
    2046               0 :                 return;
    2047                 :         }
    2048                 :         
    2049                 :         /* First, find the function */
    2050              25 :         switch (Z_TYPE_P(reference)) {
    2051                 :                 case IS_UNICODE:
    2052                 :                 case IS_STRING: {
    2053                 :                                 unsigned int lcname_len;
    2054                 :                                 zstr lcname;
    2055                 : 
    2056               4 :                                 lcname = zend_u_str_case_fold(Z_TYPE_P(reference), Z_UNIVAL_P(reference), Z_UNILEN_P(reference), 1, &lcname_len);
    2057               4 :                                 if (zend_u_hash_find(EG(function_table), Z_TYPE_P(reference), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
    2058               0 :                                         efree(lcname.v);
    2059               0 :                                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2060                 :                                                 "Function %R() does not exist", Z_TYPE_P(reference), Z_UNIVAL_P(reference));
    2061               0 :                                         return;
    2062                 :                                 }
    2063               4 :                                 efree(lcname.v);
    2064                 :                         }
    2065               4 :                         ce = fptr->common.scope;
    2066               4 :                         break;
    2067                 : 
    2068                 :                 case IS_ARRAY: {
    2069                 :                                 zval **classref;
    2070                 :                                 zval **method;
    2071                 :                                 zend_class_entry **pce;
    2072                 :                                 unsigned int lcname_len;
    2073                 :                                 zstr lcname;
    2074                 :                                 
    2075              11 :                                 if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
    2076                 :                                         || (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE))
    2077                 :                                 {
    2078               0 :                                         _DO_THROW("Expected array($object, $method) or array($classname, $method)");
    2079                 :                                         /* returns out of this function */
    2080                 :                                 }
    2081                 : 
    2082              11 :                                 if (Z_TYPE_PP(classref) == IS_OBJECT) {
    2083               5 :                                         ce = Z_OBJCE_PP(classref);
    2084                 :                                 } else {
    2085               6 :                                         convert_to_unicode_ex(classref);
    2086               6 :                                         if (zend_u_lookup_class(Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_UNILEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
    2087               1 :                                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    2088                 :                                                                 "Class %R does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref));
    2089               1 :                                                 return;
    2090                 :                                         }
    2091               5 :                                         ce = *pce;
    2092                 :                                 }
    2093                 :                                 
    2094              10 :                                 convert_to_unicode_ex(method);
    2095              10 :                                 lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_UNIVAL_PP(method), Z_UNILEN_PP(method), 1, &lcname_len);
    2096              10 :                                 if (ce == zend_ce_closure && Z_TYPE_PP(classref) == IS_OBJECT
    2097                 :                                         && lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1
    2098                 :                                         && ZEND_U_EQUAL(IS_UNICODE, lcname, lcname_len, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    2099                 :                                         && (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
    2100                 :                                 {
    2101                 :                                         /* do nothing, fptr is already set */
    2102               6 :                                 } else if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
    2103               2 :                                         efree(lcname.v);
    2104               2 :                                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2105                 :                                                 "Method %v::%R() does not exist", ce->name, Z_TYPE_PP(method), Z_UNIVAL_PP(method));
    2106               2 :                                         return;
    2107                 :                                 }
    2108               8 :                                 efree(lcname.v);
    2109                 :                         }
    2110               8 :                         break;
    2111                 : 
    2112                 :                 case IS_OBJECT: {
    2113               9 :                                 ce = Z_OBJCE_P(reference);
    2114                 :                                 
    2115               9 :                                 if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
    2116               6 :                                         fptr = zend_get_closure_invoke_method(reference TSRMLS_CC);
    2117               3 :                                 } else if (zend_u_hash_find(&ce->function_table, IS_STRING, ZSTR(ZEND_INVOKE_FUNC_NAME), sizeof(ZEND_INVOKE_FUNC_NAME), (void **)&fptr) == FAILURE) {
    2118               1 :                                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    2119                 :                                                 "Method %v::%s() does not exist", ce->name, ZEND_INVOKE_FUNC_NAME);
    2120               1 :                                         return;
    2121                 :                                 }
    2122                 :                         }
    2123               8 :                         break;
    2124                 : 
    2125                 :                 default:
    2126               1 :                         _DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
    2127                 :                         /* returns out of this function */
    2128                 :         }
    2129                 :         
    2130                 :         /* Now, search for the parameter */
    2131              20 :         arg_info = fptr->common.arg_info;
    2132              20 :         if (Z_TYPE_PP(parameter) == IS_LONG) {
    2133               9 :                 position= Z_LVAL_PP(parameter);
    2134               9 :                 if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
    2135               1 :                         if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
    2136               1 :                                 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
    2137               1 :                                         efree(fptr->common.function_name.v);
    2138                 :                                 }
    2139               1 :                                 efree(fptr);
    2140                 :                         }
    2141               1 :                         _DO_THROW("The parameter specified by its offset could not be found");
    2142                 :                         /* returns out of this function */
    2143                 :                 }
    2144                 :         } else {
    2145                 :                 zend_uint i;
    2146                 : 
    2147              11 :                 position= -1;
    2148              11 :                 convert_to_unicode_ex(parameter);
    2149              19 :                 for (i = 0; i < fptr->common.num_args; i++) {
    2150              17 :                         if (Z_TYPE_PP(parameter) == IS_STRING && arg_info[i].name.s && strcmp(arg_info[i].name.s, Z_STRVAL_PP(parameter)) == 0) {
    2151               0 :                                 position= i;
    2152               0 :                                 break;
    2153              17 :                         } else if (Z_TYPE_PP(parameter) == IS_UNICODE && arg_info[i].name.u && u_strcmp(arg_info[i].name.u, Z_USTRVAL_PP(parameter)) == 0) {
    2154               9 :                                 position= i;
    2155               9 :                                 break;
    2156                 :                         }
    2157                 :                 }
    2158              11 :                 if (position == -1) {
    2159               2 :                         if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
    2160               0 :                                 if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
    2161               0 :                                         efree(fptr->common.function_name.v);
    2162                 :                                 }
    2163               0 :                                 efree(fptr);
    2164                 :                         }
    2165               2 :                         _DO_THROW("The parameter specified by its name could not be found");
    2166                 :                         /* returns out of this function */
    2167                 :                 }
    2168                 :         }
    2169                 :         
    2170              17 :         MAKE_STD_ZVAL(name);
    2171              17 :         if (arg_info[position].name.v) {
    2172              17 :                 ZVAL_UNICODEL(name, arg_info[position].name.u, arg_info[position].name_len, 1);
    2173                 :         } else {
    2174               0 :                 ZVAL_NULL(name);
    2175                 :         }
    2176              17 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    2177                 : 
    2178              17 :         ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
    2179              17 :         ref->arg_info = &arg_info[position];
    2180              17 :         ref->offset = (zend_uint)position;
    2181              17 :         ref->required = fptr->common.required_num_args;
    2182              17 :         ref->fptr = fptr;
    2183              17 :         intern->ptr = ref;
    2184              17 :         intern->ref_type = REF_TYPE_PARAMETER;
    2185              17 :         intern->ce = ce;
    2186                 : }
    2187                 : /* }}} */
    2188                 : 
    2189                 : /* {{{ proto public string ReflectionParameter::__toString() U
    2190                 :    Returns a string representation */
    2191                 : ZEND_METHOD(reflection_parameter, __toString)
    2192               4 : {
    2193                 :         reflection_object *intern;
    2194                 :         parameter_reference *param;
    2195                 :         string str;
    2196                 : 
    2197               4 :         if (zend_parse_parameters_none() == FAILURE) {
    2198               0 :                 return;
    2199                 :         }
    2200               4 :         GET_REFLECTION_OBJECT_PTR(param);
    2201               4 :         string_init(&str);
    2202               4 :         _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC);
    2203               4 :         RETURN_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), str.string, str.len - 1, ZSTR_AUTOFREE);
    2204                 : }
    2205                 : /* }}} */
    2206                 : 
    2207                 : /* {{{ proto public string ReflectionParameter::getName() U
    2208                 :    Returns this parameters's name */
    2209                 : ZEND_METHOD(reflection_parameter, getName)
    2210              29 : {
    2211              29 :         if (zend_parse_parameters_none() == FAILURE) {
    2212               0 :                 return;
    2213                 :         }
    2214              29 :         _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
    2215                 : }
    2216                 : /* }}} */
    2217                 : 
    2218                 : /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction() U
    2219                 :    Returns the ReflectionFunction for the function of this parameter */
    2220                 : ZEND_METHOD(reflection_parameter, getDeclaringFunction)
    2221              18 : {
    2222                 :         reflection_object *intern;
    2223                 :         parameter_reference *param;
    2224                 : 
    2225              18 :         if (zend_parse_parameters_none() == FAILURE) {
    2226               0 :                 return;
    2227                 :         }
    2228              18 :         GET_REFLECTION_OBJECT_PTR(param);
    2229                 : 
    2230              18 :         if (!param->fptr->common.scope) {
    2231               9 :                 reflection_function_factory(_copy_function(param->fptr TSRMLS_CC), return_value TSRMLS_CC);
    2232                 :         } else {
    2233               9 :                 reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr TSRMLS_CC), return_value TSRMLS_CC);
    2234                 :         }
    2235                 : }
    2236                 : /* }}} */
    2237                 : 
    2238                 : /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass() U
    2239                 :    Returns in which class this parameter is defined (not the typehint of the parameter) */
    2240                 : ZEND_METHOD(reflection_parameter, getDeclaringClass)
    2241              14 : {
    2242                 :         reflection_object *intern;
    2243                 :         parameter_reference *param;
    2244                 : 
    2245              14 :         if (zend_parse_parameters_none() == FAILURE) {
    2246               0 :                 return;
    2247                 :         }
    2248              14 :         GET_REFLECTION_OBJECT_PTR(param);
    2249                 : 
    2250              14 :         if (param->fptr->common.scope) {
    2251               7 :                 zend_reflection_class_factory(param->fptr->common.scope, return_value TSRMLS_CC);
    2252                 :         }       
    2253                 : }
    2254                 : /* }}} */
    2255                 : 
    2256                 : /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass() U
    2257                 :    Returns this parameters's class hint or NULL if there is none */
    2258                 : ZEND_METHOD(reflection_parameter, getClass)
    2259              17 : {
    2260                 :         reflection_object *intern;
    2261                 :         parameter_reference *param;
    2262                 :         zend_class_entry **pce, *ce;
    2263                 : 
    2264              17 :         if (zend_parse_parameters_none() == FAILURE) {
    2265               0 :                 return;
    2266                 :         }
    2267              17 :         GET_REFLECTION_OBJECT_PTR(param);
    2268                 : 
    2269              17 :         if (param->arg_info->class_name.v) {
    2270                 : 
    2271                 :                 /* Class name is stored as a string, we might also get "self" or "parent"
    2272                 :                  * - For "self", simply use the function scope. If scope is NULL then
    2273                 :                  *   the function is global and thus self does not make any sense
    2274                 :                  *
    2275                 :                  * - For "parent", use the function scope's parent. If scope is NULL then
    2276                 :                  *   the function is global and thus parent does not make any sense.
    2277                 :                  *   If the parent is NULL then the class does not extend anything and
    2278                 :                  *   thus parent does not make any sense, either.
    2279                 :                  *
    2280                 :                  * TODO: Think about moving these checks to the compiler or some sort of
    2281                 :                  * lint-mode.
    2282                 :                  */
    2283               9 :                 if (ZEND_U_EQUAL(IS_UNICODE, param->arg_info->class_name, param->arg_info->class_name_len, "self", sizeof("self")- 1)) {
    2284               1 :                         ce = param->fptr->common.scope;
    2285               1 :                         if (!ce) {
    2286               0 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2287                 :                                         "Parameter uses 'self' as type hint but function is not a class member!");
    2288               0 :                                 return;
    2289                 :                         }
    2290               1 :                         pce= &ce;
    2291               8 :                 } else if (ZEND_U_EQUAL(IS_UNICODE, param->arg_info->class_name,  param->arg_info->class_name_len, "parent", sizeof("parent")- 1)) {
    2292               0 :                         ce = param->fptr->common.scope;
    2293               0 :                         if (!ce) {
    2294               0 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2295                 :                                         "Parameter uses 'parent' as type hint but function is not a class member!");
    2296               0 :                                 return;
    2297                 :                         }
    2298               0 :                         if (!ce->parent) {
    2299               0 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2300                 :                                         "Parameter uses 'parent' as type hint although class does not have a parent!");
    2301               0 :                                 return;
    2302                 :                         }
    2303               0 :                         pce= &ce->parent;
    2304               8 :                 } else if (zend_u_lookup_class(IS_UNICODE, param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
    2305               2 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2306                 :                                 "Class %v does not exist", param->arg_info->class_name);
    2307               2 :                         return;
    2308                 :                 }
    2309               7 :                 zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
    2310                 :         }
    2311                 : }
    2312                 : /* }}} */
    2313                 : 
    2314                 : /* {{{ proto public bool ReflectionParameter::isArray() U
    2315                 :    Returns whether parameter MUST be an array */
    2316                 : ZEND_METHOD(reflection_parameter, isArray)
    2317              14 : {
    2318                 :         reflection_object *intern;
    2319                 :         parameter_reference *param;
    2320                 : 
    2321              14 :         if (zend_parse_parameters_none() == FAILURE) {
    2322               0 :                 return;
    2323                 :         }
    2324              14 :         GET_REFLECTION_OBJECT_PTR(param);
    2325                 : 
    2326              14 :         RETVAL_BOOL(param->arg_info->array_type_hint);
    2327                 : }
    2328                 : /* }}} */
    2329                 : 
    2330                 : /* {{{ proto public bool ReflectionParameter::allowsNull() U
    2331                 :    Returns whether NULL is allowed as this parameters's value */
    2332                 : ZEND_METHOD(reflection_parameter, allowsNull)
    2333              14 : {
    2334                 :         reflection_object *intern;
    2335                 :         parameter_reference *param;
    2336                 : 
    2337              14 :         if (zend_parse_parameters_none() == FAILURE) {
    2338               0 :                 return;
    2339                 :         }
    2340              14 :         GET_REFLECTION_OBJECT_PTR(param);
    2341                 : 
    2342              14 :         RETVAL_BOOL(param->arg_info->allow_null);
    2343                 : }
    2344                 : /* }}} */
    2345                 : 
    2346                 : /* {{{ proto public bool ReflectionParameter::isPassedByReference() U
    2347                 :    Returns whether this parameters is passed to by reference */
    2348                 : ZEND_METHOD(reflection_parameter, isPassedByReference)
    2349              18 : {
    2350                 :         reflection_object *intern;
    2351                 :         parameter_reference *param;
    2352                 : 
    2353              18 :         if (zend_parse_parameters_none() == FAILURE) {
    2354               0 :                 return;
    2355                 :         }
    2356              18 :         GET_REFLECTION_OBJECT_PTR(param);
    2357                 : 
    2358              18 :         RETVAL_BOOL(param->arg_info->pass_by_reference);
    2359                 : }
    2360                 : /* }}} */
    2361                 : 
    2362                 : /* {{{ proto public bool ReflectionParameter::getPosition() U
    2363                 :    Returns whether this parameter is an optional parameter */
    2364                 : ZEND_METHOD(reflection_parameter, getPosition)
    2365              16 : {
    2366                 :         reflection_object *intern;
    2367                 :         parameter_reference *param;
    2368                 : 
    2369              16 :         if (zend_parse_parameters_none() == FAILURE) {
    2370               0 :                 return;
    2371                 :         }
    2372              16 :         GET_REFLECTION_OBJECT_PTR(param);
    2373                 : 
    2374              16 :         RETVAL_LONG(param->offset);
    2375                 : }
    2376                 : /* }}} */
    2377                 : 
    2378                 : /* {{{ proto public bool ReflectionParameter::isOptional() U
    2379                 :    Returns whether this parameter is an optional parameter */
    2380                 : ZEND_METHOD(reflection_parameter, isOptional)
    2381              50 : {
    2382                 :         reflection_object *intern;
    2383                 :         parameter_reference *param;
    2384                 : 
    2385              50 :         if (zend_parse_parameters_none() == FAILURE) {
    2386               0 :                 return;
    2387                 :         }
    2388              50 :         GET_REFLECTION_OBJECT_PTR(param);
    2389                 : 
    2390              50 :         RETVAL_BOOL(param->offset >= param->required);
    2391                 : }
    2392                 : /* }}} */
    2393                 : 
    2394                 : /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable() U
    2395                 :    Returns whether the default value of this parameter is available */
    2396                 : ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
    2397              32 : {
    2398                 :         reflection_object *intern;
    2399                 :         parameter_reference *param;
    2400                 :         zend_op *precv;
    2401                 : 
    2402              32 :         if (zend_parse_parameters_none() == FAILURE) {
    2403               0 :                 return;
    2404                 :         }
    2405              32 :         GET_REFLECTION_OBJECT_PTR(param);
    2406                 : 
    2407              32 :         if (param->fptr->type != ZEND_USER_FUNCTION)
    2408                 :         {
    2409               0 :                 RETURN_FALSE;
    2410                 :         }
    2411              32 :         if (param->offset < param->required) {
    2412              12 :                 RETURN_FALSE;
    2413                 :         }
    2414              20 :         precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
    2415              20 :         if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
    2416               0 :                 RETURN_FALSE;
    2417                 :         }
    2418              20 :         RETURN_TRUE;
    2419                 : }
    2420                 : /* }}} */
    2421                 : 
    2422                 : /* {{{ proto public bool ReflectionParameter::getDefaultValue() U
    2423                 :    Returns the default value of this parameter or throws an exception */
    2424                 : ZEND_METHOD(reflection_parameter, getDefaultValue)
    2425              17 : {
    2426                 :         reflection_object *intern;
    2427                 :         parameter_reference *param;
    2428                 :         zend_op *precv;
    2429                 : 
    2430              17 :         if (zend_parse_parameters_none() == FAILURE) {
    2431               0 :                 return;
    2432                 :         }
    2433              17 :         GET_REFLECTION_OBJECT_PTR(param);
    2434                 : 
    2435              17 :         if (param->fptr->type != ZEND_USER_FUNCTION)
    2436                 :         {
    2437               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
    2438               0 :                 return;
    2439                 :         }
    2440              17 :         if (param->offset < param->required) {
    2441               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); 
    2442               0 :                 return;
    2443                 :         }
    2444              17 :         precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
    2445              17 :         if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
    2446               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); 
    2447               0 :                 return;
    2448                 :         }
    2449                 : 
    2450              17 :         *return_value = precv->op2.u.constant;
    2451              17 :         INIT_PZVAL(return_value);
    2452              17 :         if (Z_TYPE_P(return_value) != IS_CONSTANT) {
    2453               9 :                 zval_copy_ctor(return_value);
    2454                 :         }
    2455              17 :         zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
    2456                 : }
    2457                 : /* }}} */
    2458                 : 
    2459                 : /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException U
    2460                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    2461                 : ZEND_METHOD(reflection_method, export)
    2462               9 : {
    2463               9 :         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
    2464               9 : }
    2465                 : /* }}} */
    2466                 : 
    2467                 : /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name]) U
    2468                 :    Constructor. Throws an Exception in case the given method does not exist */
    2469                 : ZEND_METHOD(reflection_method, __construct)
    2470             139 : {
    2471                 :         zval *name, *classname;
    2472                 :         zval *object, *orig_obj;
    2473                 :         reflection_object *intern;
    2474                 :         unsigned int lcname_len;
    2475                 :         zstr lcname;
    2476                 :         zend_class_entry **pce;
    2477                 :         zend_class_entry *ce;
    2478                 :         zend_function *mptr;
    2479                 :         zstr name_str;
    2480                 :         zstr tmp;
    2481             139 :         int name_len, tmp_len, free_name_str = 0;
    2482                 :         zval ztmp;
    2483                 :         zend_uchar type;
    2484                 : 
    2485             139 :         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o", &classname) == SUCCESS) {
    2486               4 :                 name_str.u = USTR_MAKE(ZEND_INVOKE_FUNC_NAME);
    2487               4 :                 free_name_str = 1;
    2488               4 :                 type = IS_UNICODE;
    2489               4 :                 name_len = sizeof(ZEND_INVOKE_FUNC_NAME)-1;
    2490               4 :                 orig_obj = classname;
    2491             135 :         } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "zt", &classname, &name_str, &name_len, &type) == FAILURE) {
    2492              48 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name_str, &name_len, &type) == FAILURE) {
    2493               4 :                         return;
    2494                 :                 }
    2495              44 :                 if ((type == IS_UNICODE && (tmp.u = u_strstr(name_str.u, u_doublecolon)) == NULL)
    2496                 :                         || (type == IS_STRING  && (tmp.s =   strstr(name_str.s, "::")) == NULL))
    2497                 :                 {
    2498               5 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %R", type, name_str);
    2499               5 :                         return;
    2500                 :                 }
    2501              39 :                 classname = &ztmp;
    2502              39 :                 if (type == IS_UNICODE) {
    2503              39 :                         tmp_len = tmp.u - name_str.u;
    2504                 :                 } else {
    2505               0 :                         tmp_len = tmp.s - name_str.s;
    2506                 :                 }
    2507              39 :                 ZVAL_ZSTRL(classname, type, name_str, tmp_len, 1);
    2508              39 :                 name_len = name_len - (tmp_len + 2);
    2509              39 :                 if (type == IS_UNICODE) {
    2510              39 :                         name_str.u = tmp.u + 2;
    2511                 :                 } else {
    2512               0 :                         name_str.s = tmp.s + 2;
    2513                 :                 }
    2514              39 :                 orig_obj = NULL;
    2515              87 :         } else if (Z_TYPE_P(classname) == IS_OBJECT) {
    2516               4 :                 orig_obj = classname;
    2517                 :         } else {
    2518              83 :                 orig_obj = NULL;
    2519                 :         }
    2520                 : 
    2521             130 :         object = getThis();
    2522             130 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    2523             130 :         if (intern == NULL) {
    2524               0 :                 if (free_name_str) {
    2525               0 :                         efree(name_str.v);
    2526                 :                 }
    2527               0 :                 return;
    2528                 :         }
    2529                 :         
    2530                 :         /* Find the class entry */
    2531             130 :         switch (Z_TYPE_P(classname)) {
    2532                 :                 case IS_STRING:
    2533                 :                 case IS_UNICODE:
    2534             120 :                         if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
    2535               8 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    2536                 :                                                 "Class %R does not exist", Z_TYPE_P(classname), Z_UNIVAL_P(classname)); 
    2537               8 :                                 if (classname == &ztmp) {
    2538               6 :                                         zval_dtor(&ztmp);
    2539                 :                                 }
    2540               8 :                                 if (free_name_str) {
    2541               0 :                                         efree(name_str.v);
    2542                 :                                 }
    2543               8 :                                 return;
    2544                 :                         }
    2545             112 :                         ce = *pce;
    2546             112 :                         break;
    2547                 : 
    2548                 :                 case IS_OBJECT:
    2549               8 :                         ce = Z_OBJCE_P(classname);
    2550               8 :                         break;
    2551                 : 
    2552                 :                 default:
    2553               2 :                         if (classname == &ztmp) {
    2554               0 :                                 zval_dtor(&ztmp);
    2555                 :                         }
    2556               2 :                         _DO_THROW("The parameter class is expected to be either a string or an object");
    2557                 :                         /* returns out of this function */
    2558                 :         }
    2559                 : 
    2560             120 :         if (classname == &ztmp) {
    2561              33 :                 zval_dtor(&ztmp);
    2562                 :         }
    2563                 : 
    2564             120 :         lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
    2565                 : 
    2566             120 :         if (ce == zend_ce_closure && orig_obj && (lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    2567                 :                 && ZEND_U_EQUAL(IS_UNICODE, lcname, lcname_len, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    2568                 :                 && (mptr = zend_get_closure_invoke_method(orig_obj TSRMLS_CC)) != NULL)
    2569                 :         {
    2570                 :                 /* do nothing, mptr already set */
    2571             117 :         } else if (zend_u_hash_find(&ce->function_table, type, lcname, lcname_len + 1, (void **) &mptr) == FAILURE) {
    2572                 :                 /* Check if this is a property storing a closure */
    2573               5 :                 mptr = NULL;  /* Set by closure detection again */
    2574               5 :                 if (orig_obj) {
    2575                 :                         zval **callable, member;
    2576                 :                         zend_property_info *property_info;
    2577               2 :                         zend_object *zobj = zend_objects_get_address(orig_obj TSRMLS_CC);
    2578                 : 
    2579               2 :                         ZVAL_ZSTRL(&member, type, name_str, name_len, 0);
    2580               2 :                         property_info = zend_get_property_info(ce, &member, 1 TSRMLS_CC);
    2581                 :         
    2582               2 :                         if (property_info && zend_u_hash_quick_find(zobj->properties, type, property_info->name, property_info->name_length+1, property_info->h, (void **) &callable) == SUCCESS) {
    2583                 :                                 zval *callable_obj;
    2584                 :                                 zend_class_entry *ce_ptr;
    2585                 :                                 zend_function *fbc;
    2586                 :         
    2587               2 :                                 if (Z_TYPE_PP(callable) == IS_OBJECT
    2588                 :                                 && Z_OBJ_HANDLER_PP(callable, get_closure)
    2589                 :                                 && Z_OBJ_HANDLER_PP(callable, get_closure)(*callable, &ce_ptr, &fbc, &callable_obj TSRMLS_CC) == SUCCESS) {
    2590               2 :                                         mptr = fbc;
    2591               2 :                                         Z_ADDREF_PP(callable);
    2592               2 :                                         intern->obj = *callable;
    2593                 :                                 }
    2594                 :                         }
    2595                 :                 }
    2596               5 :                 if (!mptr) {
    2597               3 :                         efree(lcname.v);
    2598               3 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2599                 :                                 "Method %v::%R() does not exist", ce->name, type, name_str);
    2600               3 :                         if (free_name_str) {
    2601               0 :                                 efree(name_str.v);
    2602                 :                         }
    2603               3 :                         return;
    2604                 :                 }
    2605                 :         }
    2606                 :         
    2607             117 :         MAKE_STD_ZVAL(classname);
    2608             117 :         MAKE_STD_ZVAL(name);
    2609                 : 
    2610             117 :         if (intern->obj) {
    2611               2 :                 ZVAL_UNICODEL(classname, ce->name.u, ce->name_length, 1);
    2612               2 :                 ZVAL_ZSTRL(name, type, name_str, name_len, 1);          
    2613                 :         } else {
    2614             115 :                 ZVAL_UNICODEL(classname, mptr->common.scope->name.u, mptr->common.scope->name_length, 1);
    2615             115 :                 ZVAL_UNICODE(name, mptr->common.function_name.u, 1);
    2616                 :         }
    2617             117 :         efree(lcname.v);
    2618             117 :         if (free_name_str) {
    2619               4 :                 efree(name_str.v);
    2620                 :         }
    2621                 :         
    2622             117 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
    2623             117 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
    2624                 :         
    2625             117 :         intern->ptr = mptr;
    2626             117 :         intern->ref_type = REF_TYPE_FUNCTION;
    2627             117 :         intern->ce = ce;
    2628                 : }
    2629                 : /* }}} */
    2630                 : 
    2631                 : /* {{{ proto public string ReflectionMethod::__toString() U
    2632                 :    Returns a string representation */
    2633                 : ZEND_METHOD(reflection_method, __toString)
    2634              19 : {
    2635                 :         reflection_object *intern;
    2636                 :         zend_function *mptr;
    2637                 :         string str;
    2638                 :         zval* name;
    2639                 : 
    2640              19 :         if (zend_parse_parameters_none() == FAILURE) {
    2641               0 :                 return;
    2642                 :         }
    2643              19 :         GET_REFLECTION_OBJECT_PTR(mptr);
    2644              19 :         _default_lookup_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
    2645              19 :         string_init(&str);
    2646              19 :         _function_string(&str, mptr, intern->ce, name, intern->obj, "" TSRMLS_CC);
    2647              19 :         RETURN_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), str.string, str.len - 1, ZSTR_AUTOFREE);
    2648                 : }
    2649                 : /* }}} */
    2650                 : 
    2651                 : /* {{{ proto public mixed ReflectionMethod::getClosure([mixed object])
    2652                 :    Invokes the function */
    2653                 : ZEND_METHOD(reflection_method, getClosure)
    2654               8 : {
    2655                 :         reflection_object *intern;
    2656                 :         zval *obj;
    2657                 :         zend_function *mptr;
    2658                 :         
    2659               8 :         METHOD_NOTSTATIC(reflection_method_ptr);
    2660               8 :         GET_REFLECTION_OBJECT_PTR(mptr);
    2661                 : 
    2662               8 :         if (mptr->common.fn_flags & ZEND_ACC_STATIC)  {
    2663               3 :                 zend_create_closure(return_value, mptr, mptr->common.scope, NULL TSRMLS_CC);
    2664                 :         } else {
    2665               5 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
    2666               2 :                         return;
    2667                 :                 }
    2668                 : 
    2669               3 :                 if (!instanceof_function(Z_OBJCE_P(obj), mptr->common.scope TSRMLS_CC)) {
    2670               1 :                         _DO_THROW("Given object is not an instance of the class this method was declared in");
    2671                 :                         /* Returns from this function */
    2672                 :                 }
    2673                 : 
    2674                 :                 /* This is an original closure object and __invoke is to be called. */
    2675               2 :                 if (Z_OBJCE_P(obj) == zend_ce_closure && mptr->type == ZEND_INTERNAL_FUNCTION &&
    2676                 :                         (mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
    2677                 :                 {
    2678               1 :                         RETURN_ZVAL(obj, 1, 0);
    2679                 :                 } else {
    2680               1 :                         zend_create_closure(return_value, mptr, mptr->common.scope, obj TSRMLS_CC);
    2681                 :                 }
    2682                 :         }
    2683                 : }
    2684                 : /* }}} */
    2685                 : 
    2686                 : /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args) U
    2687                 :    Invokes the method. */
    2688                 : ZEND_METHOD(reflection_method, invoke)
    2689              30 : {
    2690                 :         zval *retval_ptr;
    2691              30 :         zval ***params = NULL;
    2692                 :         zval *object_ptr;
    2693                 :         reflection_object *intern;
    2694                 :         zend_function *mptr;
    2695              30 :         int result, num_args = 0;
    2696                 :         zend_fcall_info fci;
    2697                 :         zend_fcall_info_cache fcc;
    2698                 :         zend_class_entry *obj_ce;
    2699                 :         
    2700              30 :         METHOD_NOTSTATIC(reflection_method_ptr);
    2701                 :         
    2702              30 :         GET_REFLECTION_OBJECT_PTR(mptr);
    2703                 : 
    2704              30 :         if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
    2705                 :                  || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
    2706                 :                  && intern->ignore_visibility == 0)
    2707                 :         {
    2708               6 :                 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
    2709               1 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2710                 :                                 "Trying to invoke abstract method %v::%v()", 
    2711                 :                                 mptr->common.scope->name, mptr->common.function_name);
    2712                 :                 } else {
    2713               5 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    2714                 :                                 "Trying to invoke %s method %v::%v() from scope %v", 
    2715                 :                                 mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
    2716                 :                                 mptr->common.scope->name, mptr->common.function_name,
    2717                 :                                 Z_OBJCE_P(getThis())->name);
    2718                 :                 }
    2719               6 :                 return;
    2720                 :         }
    2721                 : 
    2722              24 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &params, &num_args) == FAILURE) {
    2723               1 :                 return;
    2724                 :         }
    2725                 :         
    2726                 :         /* In case this is a static method, we should'nt pass an object_ptr
    2727                 :          * (which is used as calling context aka $this). We can thus ignore the
    2728                 :          * first parameter.
    2729                 :          *
    2730                 :          * Else, we verify that the given object is an instance of the class.
    2731                 :          */
    2732              23 :         if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
    2733               7 :                 object_ptr = NULL;
    2734               7 :                 obj_ce = mptr->common.scope;
    2735                 :         } else {
    2736              16 :                 if ((Z_TYPE_PP(params[0]) != IS_OBJECT)) {
    2737               2 :                         efree(params);
    2738               2 :                         _DO_THROW("Non-object passed to Invoke()");
    2739                 :                         /* Returns from this function */
    2740                 :                 }
    2741              14 :                 obj_ce = Z_OBJCE_PP(params[0]);
    2742                 : 
    2743              14 :                 if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
    2744               2 :                         efree(params);
    2745               2 :                         _DO_THROW("Given object is not an instance of the class this method was declared in");
    2746                 :                         /* Returns from this function */
    2747                 :                 }
    2748                 :         
    2749              12 :                 object_ptr = *params[0];
    2750                 :         }
    2751                 :         
    2752              19 :         fci.size = sizeof(fci);
    2753              19 :         fci.function_table = NULL;
    2754              19 :         fci.function_name = NULL;
    2755              19 :         fci.symbol_table = NULL;
    2756              19 :         fci.object_ptr = object_ptr;
    2757              19 :         fci.retval_ptr_ptr = &retval_ptr;
    2758              19 :         fci.param_count = num_args-1;
    2759              19 :         fci.params = params+1;
    2760              19 :         fci.no_separation = 1;
    2761                 : 
    2762              19 :         fcc.initialized = 1;
    2763              19 :         fcc.function_handler = mptr;
    2764              19 :         fcc.calling_scope = obj_ce;
    2765              19 :         fcc.called_scope = obj_ce;
    2766              19 :         fcc.object_ptr = object_ptr;
    2767                 : 
    2768              19 :         result = zend_call_function(&fci, &fcc TSRMLS_CC);
    2769                 :         
    2770              19 :         efree(params);
    2771                 : 
    2772              19 :         if (result == FAILURE) {
    2773               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2774                 :                         "Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
    2775               0 :                 return;
    2776                 :         }
    2777                 : 
    2778              19 :         if (retval_ptr) {
    2779              17 :                 COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
    2780                 :         }
    2781                 : }
    2782                 : /* }}} */
    2783                 : 
    2784                 : /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args) U
    2785                 :    Invokes the function and pass its arguments as array. */
    2786                 : ZEND_METHOD(reflection_method, invokeArgs)
    2787              28 : {
    2788                 :         zval *retval_ptr;
    2789                 :         zval ***params;
    2790                 :         zval *object;
    2791                 :         reflection_object *intern;
    2792                 :         zend_function *mptr;
    2793                 :         int argc;
    2794                 :         int result;
    2795                 :         zend_fcall_info fci;
    2796                 :         zend_fcall_info_cache fcc;
    2797                 :         zend_class_entry *obj_ce;
    2798                 :         zval *param_array;
    2799                 :         
    2800              28 :         METHOD_NOTSTATIC(reflection_method_ptr);
    2801                 : 
    2802              28 :         GET_REFLECTION_OBJECT_PTR(mptr);
    2803                 : 
    2804              28 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a", &object, &param_array) == FAILURE) {
    2805               7 :                 return;
    2806                 :         }
    2807                 : 
    2808              21 :         if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
    2809                 :                  || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
    2810                 :                  && intern->ignore_visibility == 0)
    2811                 :         {
    2812               6 :                 if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
    2813               1 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2814                 :                                 "Trying to invoke abstract method %v::%v()", 
    2815                 :                                 mptr->common.scope->name, mptr->common.function_name);
    2816                 :                 } else {
    2817               5 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    2818                 :                                 "Trying to invoke %s method %v::%v() from scope %v", 
    2819                 :                                 mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
    2820                 :                                 mptr->common.scope->name, mptr->common.function_name,
    2821                 :                                 Z_OBJCE_P(getThis())->name);
    2822                 :                 }
    2823               6 :                 return;
    2824                 :         }
    2825                 : 
    2826              15 :         argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
    2827                 :         
    2828              15 :         params = safe_emalloc(sizeof(zval **), argc, 0);
    2829              15 :         zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);        
    2830              15 :         params -= argc;
    2831                 :         
    2832                 :         /* In case this is a static method, we should'nt pass an object_ptr
    2833                 :          * (which is used as calling context aka $this). We can thus ignore the
    2834                 :          * first parameter.
    2835                 :          *
    2836                 :          * Else, we verify that the given object is an instance of the class.
    2837                 :          */
    2838              15 :         if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
    2839               4 :                 object = NULL;
    2840               4 :                 obj_ce = mptr->common.scope;
    2841                 :         } else {
    2842              11 :                 if (!object) {
    2843               0 :                         efree(params);
    2844               0 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    2845                 :                                 "Trying to invoke non static method %v::%v() without an object", 
    2846                 :                                 mptr->common.scope->name, mptr->common.function_name);
    2847               0 :                         return;
    2848                 :                 }
    2849                 :                 
    2850              11 :                 obj_ce = Z_OBJCE_P(object);
    2851                 : 
    2852              11 :                 if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
    2853               1 :                         efree(params);
    2854               1 :                         _DO_THROW("Given object is not an instance of the class this method was declared in");
    2855                 :                         /* Returns from this function */
    2856                 :                 }
    2857                 :         }
    2858                 :         
    2859              14 :         fci.size = sizeof(fci);
    2860              14 :         fci.function_table = NULL;
    2861              14 :         fci.function_name = NULL;
    2862              14 :         fci.symbol_table = NULL;
    2863              14 :         fci.object_ptr = object;
    2864              14 :         fci.retval_ptr_ptr = &retval_ptr;
    2865              14 :         fci.param_count = argc;
    2866              14 :         fci.params = params;
    2867              14 :         fci.no_separation = 1;
    2868                 : 
    2869              14 :         fcc.initialized = 1;
    2870              14 :         fcc.function_handler = mptr;
    2871              14 :         fcc.calling_scope = obj_ce;
    2872              14 :         fcc.called_scope = obj_ce;
    2873              14 :         fcc.object_ptr = object;
    2874                 : 
    2875              14 :         result = zend_call_function(&fci, &fcc TSRMLS_CC);
    2876                 :         
    2877              14 :         efree(params);
    2878                 : 
    2879              14 :         if (result == FAILURE) {
    2880               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    2881                 :                         "Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
    2882               0 :                 return;
    2883                 :         }
    2884                 : 
    2885              14 :         if (retval_ptr) {
    2886              12 :                 COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
    2887                 :         }
    2888                 : }
    2889                 : /* }}} */
    2890                 : 
    2891                 : /* {{{ proto public bool ReflectionMethod::isFinal() U
    2892                 :    Returns whether this method is final */
    2893                 : ZEND_METHOD(reflection_method, isFinal)
    2894              68 : {
    2895              68 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
    2896              68 : }
    2897                 : /* }}} */
    2898                 : 
    2899                 : /* {{{ proto public bool ReflectionMethod::isAbstract() U
    2900                 :    Returns whether this method is abstract */
    2901                 : ZEND_METHOD(reflection_method, isAbstract)
    2902              69 : {
    2903              69 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
    2904              69 : }
    2905                 : /* }}} */
    2906                 : 
    2907                 : /* {{{ proto public bool ReflectionMethod::isPublic() U
    2908                 :    Returns whether this method is public */
    2909                 : ZEND_METHOD(reflection_method, isPublic)
    2910              68 : {
    2911              68 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
    2912              68 : }
    2913                 : /* }}} */
    2914                 : 
    2915                 : /* {{{ proto public bool ReflectionMethod::isPrivate() U
    2916                 :    Returns whether this method is private */
    2917                 : ZEND_METHOD(reflection_method, isPrivate)
    2918              68 : {
    2919              68 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
    2920              68 : }
    2921                 : /* }}} */
    2922                 : 
    2923                 : /* {{{ proto public bool ReflectionMethod::isProtected() U
    2924                 :    Returns whether this method is protected */
    2925                 : ZEND_METHOD(reflection_method, isProtected)
    2926              68 : {
    2927              68 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
    2928              68 : }
    2929                 : /* }}} */
    2930                 : 
    2931                 : /* {{{ proto public bool ReflectionMethod::isStatic() U
    2932                 :    Returns whether this method is static */
    2933                 : ZEND_METHOD(reflection_method, isStatic)
    2934              68 : {
    2935              68 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
    2936              68 : }
    2937                 : /* }}} */
    2938                 : 
    2939                 : /* {{{ proto public bool ReflectionFunction::isDeprecated() U
    2940                 :    Returns whether this function is deprecated */
    2941                 : ZEND_METHOD(reflection_function, isDeprecated)
    2942               1 : {
    2943               1 :         _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
    2944               1 : }
    2945                 : /* }}} */
    2946                 : 
    2947                 : /* {{{ proto public bool ReflectionFunction::inNamespace()
    2948                 :    Returns whether this function is defined in namespace */
    2949                 : ZEND_METHOD(reflection_function, inNamespace)
    2950               2 : {
    2951                 :         zval **name;
    2952                 :         zstr colon;
    2953                 : 
    2954               2 :         if (zend_parse_parameters_none() == FAILURE) {
    2955               0 :                 return;
    2956                 :         }
    2957               2 :         if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
    2958               0 :                 RETURN_FALSE;
    2959                 :         }
    2960               2 :         if (Z_TYPE_PP(name) == IS_STRING
    2961                 :                 && (colon.s = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
    2962                 :                 && colon.s > Z_STRVAL_PP(name))
    2963                 :         {
    2964               0 :                 RETURN_TRUE;
    2965               2 :         } else if (Z_TYPE_PP(name) == IS_UNICODE
    2966                 :                 && (colon.u = u_memrchr(Z_USTRVAL_PP(name), '\\', Z_USTRLEN_PP(name)))
    2967                 :                 && colon.u > Z_USTRVAL_PP(name))
    2968                 :         {
    2969               1 :                 RETURN_TRUE;
    2970                 :         }
    2971               1 :         RETURN_FALSE;
    2972                 : }
    2973                 : /* }}} */
    2974                 : 
    2975                 : /* {{{ proto public string ReflectionFunction::getNamespaceName() U
    2976                 :    Returns the name of namespace where this function is defined */
    2977                 : ZEND_METHOD(reflection_function, getNamespaceName)
    2978               2 : {
    2979                 :         zval **name;
    2980                 :         zstr backslash;
    2981                 : 
    2982               2 :         if (zend_parse_parameters_none() == FAILURE) {
    2983               0 :                 return;
    2984                 :         }
    2985               2 :         if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
    2986               0 :                 RETURN_FALSE;
    2987                 :         }
    2988               2 :         if (Z_TYPE_PP(name) == IS_STRING
    2989                 :                 && (backslash.s = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
    2990                 :                 && backslash.s > Z_STRVAL_PP(name))
    2991                 :         {
    2992               0 :                 RETURN_STRINGL(Z_STRVAL_PP(name), backslash.s - Z_STRVAL_PP(name), 1);
    2993               2 :         } else if (Z_TYPE_PP(name) == IS_UNICODE
    2994                 :                 && (backslash.u = u_memrchr(Z_USTRVAL_PP(name), '\\', Z_USTRLEN_PP(name)))
    2995                 :                 && backslash.u > Z_USTRVAL_PP(name))
    2996                 :         {
    2997               1 :                 RETURN_UNICODEL(Z_USTRVAL_PP(name), backslash.u - Z_USTRVAL_PP(name), 1);
    2998                 :         }
    2999               1 :         RETURN_EMPTY_UNICODE();
    3000                 : }
    3001                 : /* }}} */
    3002                 : 
    3003                 : /* {{{ proto public string ReflectionFunction::getShortName() U
    3004                 :    Returns the short name of the function (without namespace part) */
    3005                 : ZEND_METHOD(reflection_function, getShortName)
    3006               2 : {
    3007                 :         zval **name;
    3008                 :         zstr backslash;
    3009                 : 
    3010               2 :         if (zend_parse_parameters_none() == FAILURE) {
    3011               0 :                 return;
    3012                 :         }
    3013               2 :         if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
    3014               0 :                 RETURN_FALSE;
    3015                 :         }
    3016               2 :         if (Z_TYPE_PP(name) == IS_STRING
    3017                 :                 && (backslash.s = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
    3018                 :                 && backslash.s > Z_STRVAL_PP(name))
    3019                 :         {
    3020               0 :                 RETURN_STRINGL(backslash.s + 1, Z_STRLEN_PP(name) - (backslash.s - Z_STRVAL_PP(name) + 1), 1);
    3021               2 :         } else if (Z_TYPE_PP(name) == IS_UNICODE
    3022                 :                 && (backslash.u = u_memrchr(Z_USTRVAL_PP(name), '\\', Z_USTRLEN_PP(name)))
    3023                 :                 && backslash.u > Z_USTRVAL_PP(name))
    3024                 :         {
    3025               1 :                 RETURN_UNICODEL(backslash.u + 1, Z_USTRLEN_PP(name) - (backslash.u - Z_USTRVAL_PP(name) + 1), 1);
    3026                 :         }
    3027               1 :         RETURN_ZVAL(*name, 1, 0);
    3028                 : }
    3029                 : /* }}} */
    3030                 : 
    3031                 : /* {{{ proto public bool ReflectionMethod::isConstructor() U
    3032                 :    Returns whether this method is the constructor */
    3033                 : ZEND_METHOD(reflection_method, isConstructor)
    3034              84 : {
    3035                 :         reflection_object *intern;
    3036                 :         zend_function *mptr;
    3037                 : 
    3038              84 :         if (zend_parse_parameters_none() == FAILURE) {
    3039               1 :                 return;
    3040                 :         }
    3041              83 :         GET_REFLECTION_OBJECT_PTR(mptr);
    3042                 :         /* we need to check if the ctor is the ctor of the class level we we 
    3043                 :          * looking at since we might be looking at an inherited old style ctor
    3044                 :          * defined in base class. */
    3045              83 :         RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
    3046                 : }
    3047                 : /* }}} */
    3048                 : 
    3049                 : /* {{{ proto public bool ReflectionMethod::isDestructor() U
    3050                 :    Returns whether this method is static */
    3051                 : ZEND_METHOD(reflection_method, isDestructor)
    3052              68 : {
    3053                 :         reflection_object *intern;
    3054                 :         zend_function *mptr;
    3055                 : 
    3056              68 :         if (zend_parse_parameters_none() == FAILURE) {
    3057               1 :                 return;
    3058                 :         }
    3059              67 :         GET_REFLECTION_OBJECT_PTR(mptr);
    3060              67 :         RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
    3061                 : }
    3062                 : /* }}} */
    3063                 : 
    3064                 : /* {{{ proto public int ReflectionMethod::getModifiers() U
    3065                 :    Returns a bitfield of the access modifiers for this method */
    3066                 : ZEND_METHOD(reflection_method, getModifiers)
    3067             111 : {
    3068                 :         reflection_object *intern;
    3069                 :         zend_function *mptr;
    3070                 : 
    3071             111 :         if (zend_parse_parameters_none() == FAILURE) {
    3072               2 :                 return;
    3073                 :         }
    3074             109 :         GET_REFLECTION_OBJECT_PTR(mptr);
    3075                 : 
    3076             109 :         RETURN_LONG(mptr->common.fn_flags);
    3077                 : }
    3078                 : /* }}} */
    3079                 : 
    3080                 : /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass() U
    3081                 :    Get the declaring class */
    3082                 : ZEND_METHOD(reflection_method, getDeclaringClass)
    3083              15 : {
    3084                 :         reflection_object *intern;
    3085                 :         zend_function *mptr;
    3086                 : 
    3087              15 :         METHOD_NOTSTATIC(reflection_method_ptr);
    3088              15 :         GET_REFLECTION_OBJECT_PTR(mptr);
    3089                 : 
    3090              15 :         zend_reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC);
    3091                 : }
    3092                 : /* }}} */
    3093                 : 
    3094                 : /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype() U
    3095                 :    Get the prototype */
    3096                 : ZEND_METHOD(reflection_method, getPrototype)
    3097               0 : {
    3098                 :         reflection_object *intern;
    3099                 :         zend_function *mptr;
    3100                 : 
    3101               0 :         METHOD_NOTSTATIC(reflection_method_ptr);
    3102               0 :         GET_REFLECTION_OBJECT_PTR(mptr);
    3103                 :         
    3104               0 :         if (!mptr->common.prototype) {
    3105               0 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    3106                 :                         "Method %v::%v does not have a prototype", intern->ce->name, mptr->common.function_name);
    3107               0 :                 return;
    3108                 :         }
    3109                 : 
    3110               0 :         reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, return_value TSRMLS_CC);
    3111                 : }
    3112                 : /* }}} */
    3113                 : 
    3114                 : /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
    3115                 :    Sets whether non-public methods can be invoked */
    3116                 : ZEND_METHOD(reflection_method, setAccessible)
    3117               0 : {
    3118                 :         reflection_object *intern;
    3119                 :         zend_bool visible;
    3120                 : 
    3121               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == FAILURE) {
    3122               0 :                 return;
    3123                 :         }
    3124                 : 
    3125               0 :         intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
    3126                 : 
    3127               0 :         if (intern == NULL) {
    3128               0 :                 return;
    3129                 :         }
    3130                 : 
    3131               0 :         intern->ignore_visibility = visible;
    3132                 : }
    3133                 : /* }}} */
    3134                 : 
    3135                 : /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException U
    3136                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    3137                 : ZEND_METHOD(reflection_class, export)
    3138               5 : {
    3139               5 :         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
    3140               5 : }
    3141                 : /* }}} */
    3142                 : 
    3143                 : /* {{{ reflection_class_object_ctor */
    3144                 : static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
    3145             473 : {
    3146                 :         zval *argument;
    3147                 :         zval *object;
    3148                 :         zval *classname;
    3149                 :         reflection_object *intern;
    3150                 :         zend_class_entry **ce;
    3151                 :         zstr name;
    3152                 :         int name_len;
    3153                 :         zend_uchar name_type;
    3154                 : 
    3155             473 :         if (is_object) {
    3156              94 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &argument) == FAILURE) {
    3157               7 :                         return;
    3158                 :                 }
    3159                 :         } else {
    3160             379 :                 if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "o", &argument) == FAILURE) {
    3161             365 :                         argument = NULL;
    3162             365 :                         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &name_type) == FAILURE) {
    3163               3 :                                 return;
    3164                 :                         }
    3165                 :                 }
    3166                 :         }
    3167                 : 
    3168             463 :         object = getThis();
    3169             463 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    3170             463 :         if (intern == NULL) {
    3171               0 :                 return;
    3172                 :         }
    3173                 :         
    3174             463 :         if (argument) {
    3175             101 :                 MAKE_STD_ZVAL(classname);
    3176             101 :                 ZVAL_UNICODEL(classname, Z_OBJCE_P(argument)->name.u, Z_OBJCE_P(argument)->name_length, 1);
    3177             101 :                 zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
    3178             101 :                 intern->ptr = Z_OBJCE_P(argument);
    3179             101 :                 if (is_object) {
    3180              87 :                         intern->obj = argument;
    3181              87 :                         zval_add_ref(&argument);
    3182                 :                 }
    3183                 :         } else { 
    3184             362 :                 if (zend_u_lookup_class(name_type, name, name_len, &ce TSRMLS_CC) == FAILURE) {
    3185               7 :                         if (!EG(exception)) {
    3186               7 :                                 zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %R does not exist", name_type, name);
    3187                 :                         }
    3188               7 :                         return;
    3189                 :                 }
    3190                 : 
    3191             355 :                 MAKE_STD_ZVAL(classname);
    3192             355 :                 ZVAL_UNICODEL(classname, (*ce)->name.u, (*ce)->name_length, 1);
    3193             355 :                 zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
    3194                 : 
    3195             355 :                 intern->ptr = *ce;
    3196                 :         }
    3197             456 :         intern->ref_type = REF_TYPE_OTHER;
    3198                 : }
    3199                 : /* }}} */
    3200                 : 
    3201                 : /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException U
    3202                 :    Constructor. Takes a string or an instance as an argument */
    3203                 : ZEND_METHOD(reflection_class, __construct)
    3204             379 : {
    3205             379 :         reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    3206             379 : }
    3207                 : /* }}} */
    3208                 : 
    3209                 : /* {{{ proto public array ReflectionClass::getStaticProperties() U
    3210                 :    Returns an associative array containing all static property values of the class */
    3211                 : ZEND_METHOD(reflection_class, getStaticProperties)
    3212              20 : {
    3213                 :         reflection_object *intern;
    3214                 :         zend_class_entry *ce;
    3215                 :         HashPosition pos;
    3216                 :         zval **value;
    3217                 :         
    3218              20 :         if (zend_parse_parameters_none() == FAILURE) {
    3219               4 :                 return;
    3220                 :         }
    3221                 :         
    3222              16 :         GET_REFLECTION_OBJECT_PTR(ce);
    3223                 : 
    3224              16 :         zend_update_class_constants(ce TSRMLS_CC);
    3225                 : 
    3226              16 :         array_init(return_value);
    3227              16 :         zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
    3228                 : 
    3229              84 :         while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
    3230                 :                 uint key_len;
    3231                 :                 zstr key;
    3232                 :                 ulong num_index;
    3233                 : 
    3234              52 :                 if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE) {
    3235                 :                         zstr prop_name, class_name;
    3236                 :                         int prop_name_len;
    3237                 :                         zval *prop_copy;
    3238                 : 
    3239              52 :                         zend_u_unmangle_property_name(IS_UNICODE, key, key_len-1, &class_name, &prop_name);
    3240              52 :                         prop_name_len = u_strlen(prop_name.u);
    3241                 : 
    3242                 :                         /* filter privates from base classes */
    3243              52 :                         if (!(class_name.s && class_name.s[0] != '*' && u_strcmp(class_name.u, ce->name.u))) {                               
    3244                 :                                 /* copy: enforce read only access */
    3245              41 :                                 ALLOC_ZVAL(prop_copy);
    3246              41 :                                 *prop_copy = **value;
    3247              41 :                                 zval_copy_ctor(prop_copy);
    3248              41 :                                 INIT_PZVAL(prop_copy);
    3249                 : 
    3250              41 :                                 add_u_assoc_zval(return_value, IS_UNICODE, prop_name, prop_copy);
    3251                 :                         }
    3252                 :                 }
    3253              52 :                 zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
    3254                 :         }
    3255                 : }
    3256                 : /* }}} */
    3257                 : 
    3258                 : /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default]) U
    3259                 :    Returns the value of a static property */
    3260                 : ZEND_METHOD(reflection_class, getStaticPropertyValue)
    3261              31 : {
    3262                 :         reflection_object *intern;
    3263                 :         zend_class_entry *ce;
    3264                 :         zstr name;
    3265                 :         int name_len;
    3266              31 :         zval **prop, *def_value = NULL;
    3267                 :         zend_uchar name_type;
    3268                 :         
    3269              31 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|z", &name, &name_len, &name_type, &def_value) == FAILURE) {
    3270               3 :                 return;
    3271                 :         }
    3272                 : 
    3273              28 :         GET_REFLECTION_OBJECT_PTR(ce);
    3274                 : 
    3275              28 :         zend_update_class_constants(ce TSRMLS_CC);
    3276              28 :         prop = zend_std_get_static_property(ce, name_type, name, name_len, 1 TSRMLS_CC);
    3277              28 :         if (!prop) {
    3278              12 :                 if (def_value) {
    3279               3 :                         RETURN_ZVAL(def_value, 1, 0);
    3280                 :                 } else {
    3281               9 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    3282                 :                                 "Class %v does not have a property named %R", ce->name, name_type, name);
    3283                 :                 }
    3284               9 :                 return;
    3285                 :         } else {
    3286              16 :                 RETURN_ZVAL(*prop, 1, 0);
    3287                 :         }
    3288                 : }
    3289                 : /* }}} */
    3290                 : 
    3291                 : /* {{{ proto public void ReflectionClass::setStaticPropertyValue($name, $value) U
    3292                 :    Sets the value of a static property */
    3293                 : ZEND_METHOD(reflection_class, setStaticPropertyValue)
    3294              18 : {
    3295                 :         reflection_object *intern;
    3296                 :         zend_class_entry *ce;
    3297                 :         zstr name;
    3298                 :         int name_len;
    3299                 :         zval **variable_ptr, *value;
    3300                 :         int refcount;
    3301                 :         zend_uchar is_ref;
    3302                 :         zend_uchar name_type;
    3303                 :         
    3304              18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "tz", &name, &name_len, &name_type, &value) == FAILURE) {
    3305               4 :                 return;
    3306                 :         }
    3307                 : 
    3308              14 :         GET_REFLECTION_OBJECT_PTR(ce);
    3309                 : 
    3310              14 :         zend_update_class_constants(ce TSRMLS_CC);
    3311              14 :         variable_ptr = zend_std_get_static_property(ce, name_type, name, name_len, 1 TSRMLS_CC);
    3312              14 :         if (!variable_ptr) {
    3313               4 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    3314                 :                                 "Class %v does not have a property named %R", ce->name, name_type, name);
    3315               4 :                 return;
    3316                 :         }       
    3317              10 :         refcount = Z_REFCOUNT_PP(variable_ptr);
    3318              10 :         is_ref = Z_ISREF_PP(variable_ptr);
    3319              10 :         zval_dtor(*variable_ptr);
    3320              10 :         **variable_ptr = *value;
    3321              10 :         zval_copy_ctor(*variable_ptr);
    3322              10 :         Z_SET_REFCOUNT_PP(variable_ptr, refcount);
    3323              10 :         Z_SET_ISREF_TO_PP(variable_ptr, is_ref);
    3324                 : 
    3325                 : }
    3326                 : /* }}} */
    3327                 : 
    3328                 : /* {{{ proto public array ReflectionClass::getDefaultProperties() U
    3329                 :    Returns an associative array containing copies of all default property values of the class */
    3330                 : ZEND_METHOD(reflection_class, getDefaultProperties)
    3331              16 : {
    3332                 :         reflection_object *intern;
    3333                 :         zend_class_entry *ce;
    3334                 :         int count, i;
    3335                 :         HashTable *ht_list[3];
    3336                 :         
    3337              16 :         if (zend_parse_parameters_none() == FAILURE) {
    3338               4 :                 return;
    3339                 :         }
    3340              12 :         GET_REFLECTION_OBJECT_PTR(ce);
    3341              12 :         array_init(return_value);
    3342                 : 
    3343              12 :         zend_update_class_constants(ce TSRMLS_CC);
    3344                 : 
    3345              12 :         ht_list[0] = CE_STATIC_MEMBERS(ce);
    3346              12 :         ht_list[1] = &ce->default_properties;
    3347              12 :         ht_list[2] = NULL; /* this should be always the last element */
    3348                 : 
    3349              36 :         for (i = 0; ht_list[i] != NULL; i++) {
    3350              24 :                 count = zend_hash_num_elements(ht_list[i]);
    3351              24 :                 if (count > 0) {
    3352                 :                         HashPosition pos;
    3353                 :                         zval **prop;
    3354                 : 
    3355              17 :                         zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
    3356             135 :                         while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
    3357                 :                                 zstr key, class_name, prop_name;
    3358                 :                                 uint key_len;
    3359                 :                                 ulong num_index;
    3360                 :                                 zval *prop_copy;
    3361                 : 
    3362             101 :                                 zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
    3363             101 :                                 zend_hash_move_forward_ex(ht_list[i], &pos);
    3364             101 :                                 zend_u_unmangle_property_name(IS_UNICODE, key, key_len-1, &class_name, &prop_name);
    3365             101 :                                 if (class_name.s && class_name.s[0] != '*'
    3366                 :                                         && u_strcmp(class_name.u, ce->name.u))
    3367                 :                                 {
    3368                 :                                         /* filter privates from base classes */
    3369              13 :                                         continue;
    3370                 :                                 }
    3371                 : 
    3372                 :                                 /* copy: enforce read only access */
    3373              88 :                                 ALLOC_ZVAL(prop_copy);
    3374              88 :                                 *prop_copy = **prop;
    3375              88 :                                 zval_copy_ctor(prop_copy);
    3376              88 :                                 INIT_PZVAL(prop_copy);
    3377                 : 
    3378              88 :                                 add_u_assoc_zval(return_value, IS_UNICODE, prop_name, prop_copy);
    3379                 :                         }
    3380                 :                 }
    3381                 :         }
    3382                 : }
    3383                 : /* }}} */
    3384                 : 
    3385                 : /* {{{ proto public string ReflectionClass::__toString() U
    3386                 :    Returns a string representation */
    3387                 : ZEND_METHOD(reflection_class, __toString)
    3388              30 : {
    3389                 :         reflection_object *intern;
    3390                 :         zend_class_entry *ce;
    3391                 :         string str;
    3392                 : 
    3393              30 :         if (zend_parse_parameters_none() == FAILURE) {
    3394               0 :                 return;
    3395                 :         }
    3396              30 :         GET_REFLECTION_OBJECT_PTR(ce);
    3397              30 :         string_init(&str);
    3398              30 :         _class_string(&str, ce, intern->obj, "" TSRMLS_CC);
    3399              30 :         RETURN_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), str.string, str.len - 1, ZSTR_AUTOFREE);
    3400                 : }
    3401                 : /* }}} */
    3402                 : 
    3403                 : /* {{{ proto public string ReflectionClass::getName() U
    3404                 :    Returns the class' name */
    3405                 : ZEND_METHOD(reflection_class, getName)
    3406              80 : {
    3407              80 :         if (zend_parse_parameters_none() == FAILURE) {
    3408               5 :                 return;
    3409                 :         }
    3410              75 :         _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
    3411                 : }
    3412                 : /* }}} */
    3413                 : 
    3414                 : /* {{{ proto public bool ReflectionClass::isInternal() U
    3415                 :    Returns whether this class is an internal class */
    3416                 : ZEND_METHOD(reflection_class, isInternal)
    3417              18 : {
    3418                 :         reflection_object *intern;
    3419                 :         zend_class_entry *ce;
    3420                 : 
    3421              18 :         if (zend_parse_parameters_none() == FAILURE) {
    3422               4 :                 return;
    3423                 :         }
    3424              14 :         GET_REFLECTION_OBJECT_PTR(ce);
    3425              14 :         RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
    3426                 : }
    3427                 : /* }}} */
    3428                 : 
    3429                 : /* {{{ proto public bool ReflectionClass::isUserDefined() U
    3430                 :    Returns whether this class is user-defined */
    3431                 : ZEND_METHOD(reflection_class, isUserDefined)
    3432              18 : {
    3433                 :         reflection_object *intern;
    3434                 :         zend_class_entry *ce;
    3435                 : 
    3436              18 :         if (zend_parse_parameters_none() == FAILURE) {
    3437               4 :                 return;
    3438                 :         }
    3439              14 :         GET_REFLECTION_OBJECT_PTR(ce);
    3440              14 :         RETURN_BOOL(ce->type == ZEND_USER_CLASS);
    3441                 : }
    3442                 : /* }}} */
    3443                 : 
    3444                 : /* {{{ proto public string ReflectionClass::getFileName() U
    3445                 :    Returns the filename of the file this class was declared in */
    3446                 : ZEND_METHOD(reflection_class, getFileName)
    3447              10 : {
    3448                 :         reflection_object *intern;
    3449                 :         zend_class_entry *ce;
    3450                 : 
    3451              10 :         if (zend_parse_parameters_none() == FAILURE) {
    3452               4 :                 return;
    3453                 :         }
    3454               6 :         GET_REFLECTION_OBJECT_PTR(ce);
    3455               6 :         if (ce->type == ZEND_USER_CLASS) {
    3456               4 :                 RETURN_RT_STRING(ce->filename, 1);
    3457                 :         }
    3458               2 :         RETURN_FALSE;
    3459                 : }
    3460                 : /* }}} */
    3461                 : 
    3462                 : /* {{{ proto public int ReflectionClass::getStartLine() U
    3463                 :    Returns the line this class' declaration starts at */
    3464                 : ZEND_METHOD(reflection_class, getStartLine)
    3465              12 : {
    3466                 :         reflection_object *intern;
    3467                 :         zend_class_entry *ce;
    3468                 : 
    3469              12 :         if (zend_parse_parameters_none() == FAILURE) {
    3470               4 :                 return;
    3471                 :         }
    3472               8 :         GET_REFLECTION_OBJECT_PTR(ce);
    3473               8 :         if (ce->type == ZEND_USER_FUNCTION) {
    3474               6 :                 RETURN_LONG(ce->line_start);
    3475                 :         }
    3476               2 :         RETURN_FALSE;
    3477                 : }
    3478                 : /* }}} */
    3479                 : 
    3480                 : /* {{{ proto public int ReflectionClass::getEndLine() U
    3481                 :    Returns the line this class' declaration ends at */
    3482                 : ZEND_METHOD(reflection_class, getEndLine)
    3483              10 : {
    3484                 :         reflection_object *intern;
    3485                 :         zend_class_entry *ce;
    3486                 : 
    3487              10 :         if (zend_parse_parameters_none() == FAILURE) {
    3488               4 :                 return;
    3489                 :         }
    3490               6 :         GET_REFLECTION_OBJECT_PTR(ce);
    3491               6 :         if (ce->type == ZEND_USER_CLASS) {
    3492               4 :                 RETURN_LONG(ce->line_end);
    3493                 :         }
    3494               2 :         RETURN_FALSE;
    3495                 : }
    3496                 : /* }}} */
    3497                 : 
    3498                 : /* {{{ proto public string ReflectionClass::getDocComment() U
    3499                 :    Returns the doc comment for this class */
    3500                 : ZEND_METHOD(reflection_class, getDocComment)
    3501              13 : {
    3502                 :         reflection_object *intern;
    3503                 :         zend_class_entry *ce;
    3504                 : 
    3505              13 :         if (zend_parse_parameters_none() == FAILURE) {
    3506               4 :                 return;
    3507                 :         }
    3508               9 :         GET_REFLECTION_OBJECT_PTR(ce);
    3509               9 :         if (ce->type == ZEND_USER_CLASS && ce->doc_comment.v) {
    3510               5 :                 RETURN_ZSTRL(IS_UNICODE, ce->doc_comment, ce->doc_comment_len, 1);
    3511                 :         }
    3512               4 :         RETURN_FALSE;
    3513                 : }
    3514                 : /* }}} */
    3515                 : 
    3516                 : /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor() U
    3517                 :    Returns the class' constructor if there is one, NULL otherwise */
    3518                 : ZEND_METHOD(reflection_class, getConstructor)
    3519              36 : {
    3520                 :         reflection_object *intern;
    3521                 :         zend_class_entry *ce;
    3522                 : 
    3523              36 :         if (zend_parse_parameters_none() == FAILURE) {
    3524               8 :                 return;
    3525                 :         }
    3526              28 :         GET_REFLECTION_OBJECT_PTR(ce);
    3527                 : 
    3528              28 :         if (ce->constructor) {
    3529              23 :                 reflection_method_factory(ce, ce->constructor, return_value TSRMLS_CC);
    3530                 :         } else {
    3531               5 :                 RETURN_NULL();
    3532                 :         }
    3533                 : }
    3534                 : /* }}} */
    3535                 : 
    3536                 : /* {{{ proto public bool ReflectionClass::hasMethod(string name) U
    3537                 :    Returns whether a method exists or not */
    3538                 : ZEND_METHOD(reflection_class, hasMethod)
    3539              39 : {
    3540                 :         reflection_object *intern;
    3541                 :         zend_class_entry *ce;
    3542                 :         unsigned int lc_name_len;
    3543                 :         zstr name, lc_name; 
    3544                 :         int name_len;
    3545                 :         zend_uchar type;
    3546                 : 
    3547              39 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3548              39 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
    3549               4 :                 return;
    3550                 :         }
    3551                 : 
    3552              35 :         GET_REFLECTION_OBJECT_PTR(ce);
    3553              35 :         lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
    3554              35 :         if (zend_u_hash_exists(&ce->function_table, type, lc_name, lc_name_len + 1)) {
    3555              24 :                 efree(lc_name.v);
    3556              24 :                 RETURN_TRUE;
    3557                 :         } else {
    3558              11 :                 efree(lc_name.v);
    3559              11 :                 RETURN_FALSE;
    3560                 :         }
    3561                 : }
    3562                 : /* }}} */
    3563                 : 
    3564                 : /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException U
    3565                 :    Returns the class' method specified by its name */
    3566                 : ZEND_METHOD(reflection_class, getMethod)
    3567              42 : {
    3568                 :         reflection_object *intern;
    3569                 :         zend_class_entry *ce;
    3570                 :         zend_function *mptr;
    3571                 :         unsigned int lc_name_len;
    3572                 :         zstr name, lc_name; 
    3573                 :         int name_len;
    3574                 :         zend_uchar type;
    3575                 : 
    3576              42 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3577              42 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
    3578               4 :                 return;
    3579                 :         }
    3580                 : 
    3581              38 :         GET_REFLECTION_OBJECT_PTR(ce);
    3582              38 :         lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
    3583              39 :         if (ce == zend_ce_closure && intern->obj && (lc_name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    3584                 :                 && ZEND_U_EQUAL(IS_UNICODE, lc_name, lc_name_len, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    3585                 :                 && (mptr = zend_get_closure_invoke_method(intern->obj TSRMLS_CC)) != NULL)
    3586                 :         {
    3587               1 :                 reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
    3588               1 :                 efree(lc_name.v);
    3589              37 :         } else if (zend_u_hash_find(&ce->function_table, type, lc_name, lc_name_len + 1, (void**) &mptr) == SUCCESS) {
    3590              27 :                 reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
    3591              27 :                 efree(lc_name.v);
    3592                 :         } else {
    3593              10 :                 efree(lc_name.v);
    3594              10 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    3595                 :                                 "Method %R does not exist", type, name);
    3596              10 :                 return;
    3597                 :         }
    3598                 : }
    3599                 : /* }}} */
    3600                 : 
    3601                 : /* {{{ _addmethod */
    3602                 : static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, long filter, zval *obj TSRMLS_DC)
    3603             252 : {
    3604                 :         zval *method;
    3605             252 :         uint len = u_strlen(mptr->common.function_name.u);
    3606                 :         zend_function *closure;
    3607                 : 
    3608             252 :         if (mptr->common.fn_flags & filter) {
    3609                 :                 unsigned int lc_name_len;
    3610             232 :                 zstr lc_name = zend_u_str_case_fold(IS_UNICODE, mptr->common.function_name, len, 1, &lc_name_len);
    3611             232 :                 ALLOC_ZVAL(method);
    3612             232 :                 if (ce == zend_ce_closure && obj && (lc_name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    3613                 :                         && ZEND_U_EQUAL(IS_UNICODE, lc_name, lc_name_len, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1)
    3614                 :                         && (closure = zend_get_closure_invoke_method(obj TSRMLS_CC)) != NULL)
    3615                 :                 {
    3616               1 :                         mptr = closure;
    3617                 :                 }
    3618             232 :                 reflection_method_factory(ce, mptr, method TSRMLS_CC);
    3619             232 :                 add_next_index_zval(retval, method);
    3620             232 :                 efree(lc_name.v);
    3621                 :         }
    3622             252 : }
    3623                 : /* }}} */
    3624                 : 
    3625                 : /* {{{ _addmethod */
    3626                 : static int _addmethod_va(zend_function *mptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
    3627             251 : {
    3628             251 :         zend_class_entry *ce = *va_arg(args, zend_class_entry**);
    3629             251 :         zval *retval = va_arg(args, zval*);
    3630             251 :         long filter = va_arg(args, long);
    3631             251 :         zval *obj = va_arg(args, zval *);
    3632                 :         
    3633             251 :         _addmethod(mptr, ce, retval, filter, obj TSRMLS_CC);
    3634             251 :         return ZEND_HASH_APPLY_KEEP;
    3635                 : }
    3636                 : /* }}} */
    3637                 : 
    3638                 : /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter]) U
    3639                 :    Returns an array of this class' methods */
    3640                 : ZEND_METHOD(reflection_class, getMethods)
    3641              37 : {
    3642                 :         reflection_object *intern;
    3643                 :         zend_class_entry *ce;
    3644              37 :         long filter = 0;
    3645              37 :         int argc = ZEND_NUM_ARGS();
    3646                 : 
    3647              37 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3648              37 :         if (argc) {
    3649               7 :                 if (zend_parse_parameters(argc TSRMLS_CC, "|l", &filter) == FAILURE) {
    3650               2 :                         return;
    3651                 :                 }
    3652                 :         } else {
    3653                 :                 /* No parameters given, default to "return all" */
    3654              30 :                 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
    3655                 :         }
    3656                 : 
    3657              35 :         GET_REFLECTION_OBJECT_PTR(ce);
    3658                 : 
    3659              35 :         array_init(return_value);
    3660              35 :         zend_hash_apply_with_arguments(&ce->function_table TSRMLS_CC, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter, intern->obj);
    3661              35 :         if (intern->obj && instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
    3662               1 :                 zend_function *closure = zend_get_closure_invoke_method(intern->obj TSRMLS_CC);
    3663               1 :                 if (closure) {
    3664               1 :                         _addmethod(closure, ce, return_value, filter, intern->obj TSRMLS_CC);
    3665               1 :                         _free_function(closure TSRMLS_CC);
    3666                 :                 }
    3667                 :         }
    3668                 : }
    3669                 : /* }}} */
    3670                 : 
    3671                 : /* {{{ proto public bool ReflectionClass::hasProperty(string name) U
    3672                 :    Returns whether a property exists or not */
    3673                 : ZEND_METHOD(reflection_class, hasProperty)
    3674              43 : {
    3675                 :         reflection_object *intern;
    3676                 :         zend_property_info *property_info;
    3677                 :         zend_class_entry *ce;
    3678                 :         zstr name; 
    3679                 :         int name_len;
    3680                 :         zend_uchar name_type;
    3681                 :         zval *property;
    3682                 : 
    3683              43 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3684              43 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &name_type) == FAILURE) {
    3685               4 :                 return;
    3686                 :         }
    3687                 : 
    3688              39 :         GET_REFLECTION_OBJECT_PTR(ce);
    3689              39 :         if (zend_u_hash_find(&ce->properties_info, name_type, name, name_len+1, (void **) &property_info) == SUCCESS) {
    3690              20 :                 if (property_info->flags & ZEND_ACC_SHADOW) {
    3691               2 :                         RETURN_FALSE;
    3692                 :                 }
    3693              18 :                 RETURN_TRUE;
    3694                 :         } else {
    3695              19 :                 if (intern->obj && Z_OBJ_HANDLER_P(intern->obj, has_property))
    3696                 :                 {
    3697               2 :                         MAKE_STD_ZVAL(property);
    3698               2 :                         if (name_type == IS_STRING) {
    3699               0 :                                 ZVAL_STRINGL(property, name.s, name_len, 1);
    3700                 :                         } else {
    3701               2 :                                 ZVAL_UNICODEL(property, name.u, name_len, 1);
    3702                 :                         }
    3703               2 :                         if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 2 TSRMLS_CC)) {
    3704               0 :                                 zval_ptr_dtor(&property);
    3705               0 :                                 RETURN_TRUE;
    3706                 :                         }
    3707               2 :                         zval_ptr_dtor(&property);
    3708                 :                 }
    3709              19 :                 RETURN_FALSE;
    3710                 :         }
    3711                 : }
    3712                 : /* }}} */
    3713                 : 
    3714                 : /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException U
    3715                 :    Returns the class' property specified by its name */
    3716                 : ZEND_METHOD(reflection_class, getProperty)
    3717             102 : {
    3718                 :         reflection_object *intern;
    3719                 :         zend_class_entry *ce, **pce;
    3720                 :         zend_property_info *property_info;
    3721                 :         zstr name, classname;
    3722                 :         zstr tmp; 
    3723                 :         int name_len, classname_len;
    3724                 :         unsigned int tmp_len;
    3725                 :         zend_uchar name_type;
    3726                 : 
    3727             102 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3728             102 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &name_type) == FAILURE) {
    3729               4 :                 return;
    3730                 :         }
    3731                 : 
    3732              98 :         GET_REFLECTION_OBJECT_PTR(ce);
    3733              98 :         if (zend_u_hash_find(&ce->properties_info, name_type, name, name_len + 1, (void**) &property_info) == SUCCESS) {
    3734              45 :                 if ((property_info->flags & ZEND_ACC_SHADOW) == 0) {
    3735              39 :                         reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
    3736              39 :                         return;
    3737                 :                 }
    3738              53 :         } else if (intern->obj) {
    3739                 :                 /* Check for dynamic properties */
    3740               2 :                 if (zend_u_hash_exists(Z_OBJ_HT_P(intern->obj)->get_properties(intern->obj TSRMLS_CC), name_type, name, name_len+1)) {
    3741                 :                         zend_property_info property_info_tmp;
    3742               2 :                         property_info_tmp.flags = ZEND_ACC_IMPLICIT_PUBLIC;
    3743               2 :                         property_info_tmp.name = name;
    3744               2 :                         property_info_tmp.name_length = name_len;
    3745               2 :                         property_info_tmp.h = zend_u_get_hash_value(name_type, name, name_len+1);
    3746               2 :                         property_info_tmp.doc_comment = NULL_ZSTR;
    3747               2 :                         property_info_tmp.ce = ce;
    3748                 : 
    3749               2 :                         reflection_property_factory(ce, &property_info_tmp, return_value TSRMLS_CC);
    3750               2 :                         return;
    3751                 :                 }
    3752                 :         }
    3753              57 :         if ((name_type == IS_UNICODE && (tmp.u = u_strstr(name.u, u_doublecolon)) != NULL)
    3754                 :                 || (name_type == IS_STRING  && (tmp.s =   strstr(name.s, "::")) != NULL))
    3755                 :         {
    3756              33 :                 if (name_type == IS_UNICODE) {
    3757              33 :                         classname_len = tmp.u - name.u;
    3758                 :                 } else {
    3759               0 :                         classname_len = tmp.s - name.s;
    3760                 :                 }
    3761              33 :                 classname = zend_u_str_case_fold(name_type, name, classname_len, 1, &tmp_len);
    3762              33 :                 classname_len = tmp_len;
    3763              33 :                 name_len = name_len - (classname_len + 2);
    3764              33 :                 if (name_type == IS_UNICODE) {
    3765              33 :                         name.u = tmp.u + 2;
    3766                 :                 } else {
    3767               0 :                         name.s = tmp.s + 2;
    3768                 :                 }
    3769                 : 
    3770              33 :                 if (zend_u_lookup_class(name_type, classname, classname_len, &pce TSRMLS_CC) == FAILURE) {
    3771               3 :                         if (!EG(exception)) {
    3772               3 :                                 zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %R does not exist", name_type, classname);
    3773                 :                         }
    3774               3 :                         efree(classname.v);
    3775               3 :                         return;
    3776                 :                 }
    3777              30 :                 efree(classname.v);
    3778                 : 
    3779              30 :                 if (!instanceof_function(ce, *pce TSRMLS_CC)) {
    3780               8 :                         zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Fully qualified property name %v::%R does not specify a base class of %v", (*pce)->name, name_type, name, ce->name);
    3781               8 :                         return;
    3782                 :                 }
    3783              22 :                 ce = *pce;
    3784                 : 
    3785              22 :                 if (zend_u_hash_find(&ce->properties_info, name_type, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
    3786              20 :                         reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
    3787              20 :                         return;
    3788                 :                 }               
    3789                 :         }
    3790              26 :         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    3791                 :                         "Property %R does not exist", name_type, name);
    3792                 : }
    3793                 : /* }}} */
    3794                 : 
    3795                 : /* {{{ _addproperty */
    3796                 : static int _addproperty(zend_property_info *pptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
    3797             123 : {
    3798                 :         zval *property;
    3799             123 :         zend_class_entry *ce = *va_arg(args, zend_class_entry**);
    3800             123 :         zval *retval = va_arg(args, zval*);
    3801             123 :         long filter = va_arg(args, long);
    3802                 : 
    3803             123 :         if (pptr->flags      & ZEND_ACC_SHADOW) {
    3804               4 :                 return 0;
    3805                 :         }
    3806                 :         
    3807             119 :         if (pptr->flags      & filter) {
    3808              99 :                 ALLOC_ZVAL(property);
    3809              99 :                 reflection_property_factory(ce, pptr, property TSRMLS_CC);
    3810              99 :                 add_next_index_zval(retval, property);
    3811                 :         }
    3812             119 :         return 0;
    3813                 : }
    3814                 : /* }}} */
    3815                 : 
    3816                 : /* {{{ _adddynproperty */
    3817                 : static int _adddynproperty(zval **pptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
    3818              10 : {
    3819                 :         zval *property;
    3820              10 :         zend_class_entry *ce = *va_arg(args, zend_class_entry**);
    3821              10 :         zval *retval = va_arg(args, zval*), member;
    3822                 : 
    3823              10 :         if (hash_key->type == IS_UNICODE) {
    3824              10 :                 if (hash_key->arKey.u[0] == 0) {
    3825               2 :                         return 0; /* non public cannot be dynamic */
    3826                 :                 }
    3827               8 :                 ZVAL_UNICODEL(&member, hash_key->arKey.u, hash_key->nKeyLength-1, 0);
    3828                 :         } else {
    3829               0 :                 if (hash_key->arKey.s[0] == '\0') {
    3830               0 :                         return 0; /* non public cannot be dynamic */
    3831                 :                 }
    3832               0 :                 ZVAL_STRINGL(&member, hash_key->arKey.s, hash_key->nKeyLength-1, 0);
    3833                 :         }
    3834               8 :         if (zend_get_property_info(ce, &member, 1 TSRMLS_CC) == &EG(std_property_info)) {
    3835               8 :                 MAKE_STD_ZVAL(property);
    3836               8 :                 reflection_property_factory(ce, &EG(std_property_info), property TSRMLS_CC);
    3837               8 :                 add_next_index_zval(retval, property);
    3838                 :         }
    3839               8 :         return 0;
    3840                 : }
    3841                 : /* }}} */
    3842                 : 
    3843                 : /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter]) U
    3844                 :    Returns an array of this class' properties */
    3845                 : ZEND_METHOD(reflection_class, getProperties)
    3846              31 : {
    3847                 :         reflection_object *intern;
    3848                 :         zend_class_entry *ce;
    3849              31 :         long filter = 0;
    3850              31 :         int argc = ZEND_NUM_ARGS();
    3851                 : 
    3852              31 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3853              31 :         if (argc) {
    3854               7 :                 if (zend_parse_parameters(argc TSRMLS_CC, "|l", &filter) == FAILURE) {
    3855               2 :                         return;
    3856                 :                 }
    3857                 :         } else {
    3858                 :                 /* No parameters given, default to "return all" */
    3859              24 :                 filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
    3860                 :         }
    3861                 : 
    3862              29 :         GET_REFLECTION_OBJECT_PTR(ce);
    3863                 : 
    3864              29 :         array_init(return_value);
    3865              29 :         zend_hash_apply_with_arguments(&ce->properties_info TSRMLS_CC, (apply_func_args_t) _addproperty, 3, &ce, return_value, filter);
    3866                 : 
    3867              29 :         if (intern->obj && (filter & ZEND_ACC_PUBLIC) != 0 && Z_OBJ_HT_P(intern->obj)->get_properties) {
    3868               6 :                 HashTable *properties = Z_OBJ_HT_P(intern->obj)->get_properties(intern->obj TSRMLS_CC);
    3869               6 :                 zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t) _adddynproperty, 2, &ce, return_value);
    3870                 :         }
    3871                 : }
    3872                 : /* }}} */
    3873                 : 
    3874                 : /* {{{ proto public bool ReflectionClass::hasConstant(string name) U
    3875                 :    Returns whether a constant exists or not */
    3876                 : ZEND_METHOD(reflection_class, hasConstant)
    3877              17 : {
    3878                 :         reflection_object *intern;
    3879                 :         zend_class_entry *ce;
    3880                 :         zstr name;
    3881                 :         int name_len;
    3882                 :         zend_uchar name_type;
    3883                 : 
    3884              17 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3885              17 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &name_type) == FAILURE) {
    3886               4 :                 return;
    3887                 :         }
    3888                 : 
    3889              13 :         GET_REFLECTION_OBJECT_PTR(ce);
    3890              13 :         if (zend_u_hash_exists(&ce->constants_table, name_type, name, name_len + 1)) {
    3891               4 :                 RETURN_TRUE;
    3892                 :         } else {
    3893               9 :                 RETURN_FALSE;
    3894                 :         }
    3895                 : }
    3896                 : /* }}} */
    3897                 : 
    3898                 : /* {{{ proto public array ReflectionClass::getConstants() U
    3899                 :    Returns an associative array containing this class' constants and their values */
    3900                 : ZEND_METHOD(reflection_class, getConstants)
    3901              23 : {
    3902                 :         zval *tmp_copy;
    3903                 :         reflection_object *intern;
    3904                 :         zend_class_entry *ce;
    3905                 : 
    3906              23 :         if (zend_parse_parameters_none() == FAILURE) {
    3907               6 :                 return;
    3908                 :         }       
    3909              17 :         GET_REFLECTION_OBJECT_PTR(ce);
    3910              17 :         array_init(return_value);
    3911              17 :         zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
    3912              17 :         zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
    3913                 : }
    3914                 : /* }}} */
    3915                 : 
    3916                 : /* {{{ proto public mixed ReflectionClass::getConstant(string name) U
    3917                 :    Returns the class' constant specified by its name */
    3918                 : ZEND_METHOD(reflection_class, getConstant)
    3919              42 : {
    3920                 :         reflection_object *intern;
    3921                 :         zend_class_entry *ce;
    3922                 :         zval **value;
    3923                 :         zstr name; 
    3924                 :         int name_len;
    3925                 :         zend_uchar name_type;
    3926                 : 
    3927              42 :         METHOD_NOTSTATIC(reflection_class_ptr);
    3928              42 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &name_type) == FAILURE) {
    3929               8 :                 return;
    3930                 :         }
    3931                 : 
    3932              34 :         GET_REFLECTION_OBJECT_PTR(ce);
    3933              34 :         zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
    3934              34 :         if (zend_u_hash_find(&ce->constants_table, name_type, name, name_len + 1, (void **) &value) == FAILURE) {
    3935              22 :                 RETURN_FALSE;
    3936                 :         }
    3937              12 :         *return_value = **value;
    3938              12 :         zval_copy_ctor(return_value);
    3939              12 :         INIT_PZVAL(return_value);
    3940                 : }
    3941                 : /* }}} */
    3942                 : 
    3943                 : /* {{{ _class_check_flag */
    3944                 : static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
    3945              37 : {
    3946                 :         reflection_object *intern;
    3947                 :         zend_class_entry *ce;
    3948                 : 
    3949              37 :         if (zend_parse_parameters_none() == FAILURE) {
    3950               3 :                 return;
    3951                 :         }
    3952              34 :         GET_REFLECTION_OBJECT_PTR(ce);
    3953              34 :         RETVAL_BOOL(ce->ce_flags & mask);
    3954                 : }
    3955                 : /* }}} */
    3956                 : 
    3957                 : /* {{{ proto public bool ReflectionClass::isInstantiable() U
    3958                 :    Returns whether this class is instantiable */
    3959                 : ZEND_METHOD(reflection_class, isInstantiable)
    3960              55 : {
    3961                 :         reflection_object *intern;
    3962                 :         zend_class_entry *ce;
    3963                 : 
    3964              55 :         if (zend_parse_parameters_none() == FAILURE) {
    3965               4 :                 return;
    3966                 :         }
    3967              51 :         GET_REFLECTION_OBJECT_PTR(ce);
    3968              51 :         if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
    3969               7 :                 RETURN_FALSE;
    3970                 :         }
    3971                 : 
    3972                 :         /* Basically, the class is instantiable. Though, if there is a constructor
    3973                 :          * and it is not publicly accessible, it isn't! */
    3974              44 :         if (!ce->constructor) {
    3975              29 :                 RETURN_TRUE;
    3976                 :         }
    3977                 : 
    3978              15 :         RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
    3979                 : }
    3980                 : /* }}} */
    3981                 : 
    3982                 : /* {{{ proto public bool ReflectionClass::isInterface() U
    3983                 :    Returns whether this is an interface or a class */
    3984                 : ZEND_METHOD(reflection_class, isInterface)
    3985              13 : {
    3986              13 :         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
    3987              13 : }
    3988                 : /* }}} */
    3989                 : 
    3990                 : /* {{{ proto public bool ReflectionClass::isFinal() U
    3991                 :    Returns whether this class is final */
    3992                 : ZEND_METHOD(reflection_class, isFinal)
    3993              12 : {
    3994              12 :         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL_CLASS);
    3995              12 : }
    3996                 : /* }}} */
    3997                 : 
    3998                 : /* {{{ proto public bool ReflectionClass::isAbstract() U
    3999                 :    Returns whether this class is abstract */
    4000                 : ZEND_METHOD(reflection_class, isAbstract)
    4001              12 : {
    4002              12 :         _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
    4003              12 : }
    4004                 : /* }}} */
    4005                 : 
    4006                 : /* {{{ proto public int ReflectionClass::getModifiers() U
    4007                 :    Returns a bitfield of the access modifiers for this class */
    4008                 : ZEND_METHOD(reflection_class, getModifiers)
    4009              20 : {
    4010                 :         reflection_object *intern;
    4011                 :         zend_class_entry *ce;
    4012                 : 
    4013              20 :         if (zend_parse_parameters_none() == FAILURE) {
    4014               1 :                 return;
    4015                 :         }
    4016              19 :         GET_REFLECTION_OBJECT_PTR(ce);
    4017                 : 
    4018              19 :         RETURN_LONG(ce->ce_flags);
    4019                 : }
    4020                 : /* }}} */
    4021                 : 
    4022                 : /* {{{ proto public bool ReflectionClass::isInstance(stdclass object) U
    4023                 :    Returns whether the given object is an instance of this class */
    4024                 : ZEND_METHOD(reflection_class, isInstance)
    4025              59 : {
    4026                 :         reflection_object *intern;
    4027                 :         zend_class_entry *ce;
    4028                 :         zval *object;
    4029                 : 
    4030              59 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4031              59 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
    4032              14 :                 return;
    4033                 :         }
    4034              45 :         GET_REFLECTION_OBJECT_PTR(ce);  
    4035              45 :         RETURN_BOOL(HAS_CLASS_ENTRY(*object) && instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC));
    4036                 : }
    4037                 : /* }}} */
    4038                 : 
    4039                 : /* {{{ proto public stdclass ReflectionClass::newInstance(mixed* args, ...) U
    4040                 :    Returns an instance of this class */
    4041                 : ZEND_METHOD(reflection_class, newInstance)
    4042              46 : {
    4043              46 :         zval *retval_ptr = NULL;
    4044                 :         reflection_object *intern;
    4045                 :         zend_class_entry *ce;
    4046                 :         
    4047              46 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4048              46 :         GET_REFLECTION_OBJECT_PTR(ce);
    4049                 : 
    4050                 :         /* Run the constructor if there is one */
    4051              46 :         if (ce->constructor) {
    4052              23 :                 zval ***params = NULL;
    4053              23 :                 int num_args = 0;
    4054                 :                 zend_fcall_info fci;
    4055                 :                 zend_fcall_info_cache fcc;
    4056                 : 
    4057              23 :                 if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
    4058               2 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name);
    4059               2 :                         return;
    4060                 :                 }
    4061                 : 
    4062              21 :                 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &params, &num_args) == FAILURE) {
    4063               0 :                         if (params) {
    4064               0 :                                 efree(params);
    4065                 :                         }
    4066               0 :                         RETURN_FALSE;
    4067                 :                 }
    4068                 : 
    4069              21 :                 object_init_ex(return_value, ce);
    4070                 : 
    4071              21 :                 fci.size = sizeof(fci);
    4072              21 :                 fci.function_table = EG(function_table);
    4073              21 :                 fci.function_name = NULL;
    4074              21 :                 fci.symbol_table = NULL;
    4075              21 :                 fci.object_ptr = return_value;
    4076              21 :                 fci.retval_ptr_ptr = &retval_ptr;
    4077              21 :                 fci.param_count = num_args;
    4078              21 :                 fci.params = params;
    4079              21 :                 fci.no_separation = 1;
    4080                 : 
    4081              21 :                 fcc.initialized = 1;
    4082              21 :                 fcc.function_handler = ce->constructor;
    4083              21 :                 fcc.calling_scope = EG(scope);
    4084              21 :                 fcc.called_scope = Z_OBJCE_P(return_value);
    4085              21 :                 fcc.object_ptr = return_value;
    4086                 : 
    4087              21 :                 if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
    4088               1 :                         efree(params);
    4089               1 :                         if (retval_ptr) {
    4090               0 :                                 zval_ptr_dtor(&retval_ptr);
    4091                 :                         }
    4092               1 :                         zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name);
    4093               1 :                         RETURN_NULL();
    4094                 :                 }
    4095              20 :                 if (retval_ptr) {
    4096              20 :                         zval_ptr_dtor(&retval_ptr);
    4097                 :                 }
    4098                 :                 
    4099              20 :                 if (params) {
    4100              16 :                         efree(params);
    4101                 :                 }
    4102              23 :         } else if (!ZEND_NUM_ARGS()) {
    4103              20 :                 object_init_ex(return_value, ce);
    4104                 :         } else {
    4105               3 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %v does not have a constructor, so you cannot pass any constructor arguments", ce->name);
    4106                 :         }
    4107                 : }
    4108                 : /* }}} */
    4109                 : 
    4110                 : /* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args]) U
    4111                 :    Returns an instance of this class */
    4112                 : ZEND_METHOD(reflection_class, newInstanceArgs)
    4113              13 : {
    4114              13 :         zval *retval_ptr = NULL;
    4115                 :         reflection_object *intern;
    4116                 :         zend_class_entry *ce;
    4117              13 :         int argc = 0;
    4118                 :         HashTable *args;
    4119                 :         
    4120                 :         
    4121              13 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4122              13 :         GET_REFLECTION_OBJECT_PTR(ce);
    4123                 : 
    4124              13 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|h", &args) == FAILURE) {
    4125               0 :                 return;
    4126                 :         }
    4127              13 :         if (ZEND_NUM_ARGS() > 0) {
    4128               6 :                 argc = args->nNumOfElements;
    4129                 :         }
    4130                 :         
    4131                 :         /* Run the constructor if there is one */
    4132              13 :         if (ce->constructor) {
    4133              11 :                 zval ***params = NULL;
    4134                 :                 zend_fcall_info fci;
    4135                 :                 zend_fcall_info_cache fcc;
    4136                 : 
    4137              11 :                 if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
    4138               2 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name);
    4139               2 :                         return;
    4140                 :                 }
    4141                 :                 
    4142               9 :                 if (argc) {
    4143               5 :                         params = safe_emalloc(sizeof(zval **), argc, 0);
    4144               5 :                         zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);   
    4145               5 :                         params -= argc;
    4146                 :                 }
    4147                 : 
    4148               9 :                 object_init_ex(return_value, ce);
    4149                 : 
    4150               9 :                 fci.size = sizeof(fci);
    4151               9 :                 fci.function_table = EG(function_table);
    4152               9 :                 fci.function_name = NULL;
    4153               9 :                 fci.symbol_table = NULL;
    4154               9 :                 fci.object_ptr = return_value;
    4155               9 :                 fci.retval_ptr_ptr = &retval_ptr;
    4156               9 :                 fci.param_count = argc;
    4157               9 :                 fci.params = params;
    4158               9 :                 fci.no_separation = 1;
    4159                 : 
    4160               9 :                 fcc.initialized = 1;
    4161               9 :                 fcc.function_handler = ce->constructor;
    4162               9 :                 fcc.calling_scope = EG(scope);
    4163               9 :                 fcc.called_scope = Z_OBJCE_P(return_value);
    4164               9 :                 fcc.object_ptr = return_value;
    4165                 : 
    4166               9 :                 if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
    4167               1 :                         if (params) {
    4168               1 :                                 efree(params);
    4169                 :                         }
    4170               1 :                         if (retval_ptr) {
    4171               0 :                                 zval_ptr_dtor(&retval_ptr);
    4172                 :                         }
    4173               1 :                         zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name);
    4174               1 :                         RETURN_NULL();
    4175                 :                 }
    4176               8 :                 if (retval_ptr) {
    4177               8 :                         zval_ptr_dtor(&retval_ptr);
    4178                 :                 }
    4179               8 :                 if (params) {
    4180               4 :                         efree(params);
    4181                 :                 }
    4182               2 :         } else if (!ZEND_NUM_ARGS()) {
    4183               1 :                 object_init_ex(return_value, ce);
    4184                 :         } else {
    4185               1 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Class %v does not have a constructor, so you cannot pass any constructor arguments", ce->name);
    4186                 :         }
    4187                 : }
    4188                 : /* }}} */
    4189                 : 
    4190                 : /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces() U
    4191                 :    Returns an array of interfaces this class implements */
    4192                 : ZEND_METHOD(reflection_class, getInterfaces)
    4193              25 : {
    4194                 :         reflection_object *intern;
    4195                 :         zend_class_entry *ce;
    4196                 : 
    4197              25 :         if (zend_parse_parameters_none() == FAILURE) {
    4198               4 :                 return;
    4199                 :         }
    4200              21 :         GET_REFLECTION_OBJECT_PTR(ce);
    4201                 : 
    4202                 :         /* Return an empty array if this class implements no interfaces */
    4203              21 :         array_init(return_value);
    4204                 : 
    4205              21 :         if (ce->num_interfaces) {
    4206                 :                 zend_uint i;
    4207                 : 
    4208              58 :                 for (i=0; i < ce->num_interfaces; i++) {
    4209                 :                         zval *interface;
    4210              45 :                         ALLOC_ZVAL(interface);
    4211              45 :                         zend_reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC);
    4212              45 :                         add_u_assoc_zval_ex(return_value, IS_UNICODE, ce->interfaces[i]->name, ce->interfaces[i]->name_length + 1, interface);
    4213                 :                 }
    4214                 :         }
    4215                 : }
    4216                 : /* }}} */
    4217                 : 
    4218                 : /* {{{ proto public String[] ReflectionClass::getInterfaceNames() U
    4219                 :    Returns an array of names of interfaces this class implements */
    4220                 : ZEND_METHOD(reflection_class, getInterfaceNames)
    4221               1 : {
    4222                 :         reflection_object *intern;
    4223                 :         zend_class_entry *ce;
    4224                 :         zend_uint i;
    4225                 : 
    4226               1 :         if (zend_parse_parameters_none() == FAILURE) {
    4227               0 :                 return;
    4228                 :         }
    4229               1 :         GET_REFLECTION_OBJECT_PTR(ce);
    4230                 : 
    4231                 :         /* Return an empty array if this class implements no interfaces */
    4232               1 :         array_init(return_value);
    4233                 : 
    4234               3 :         for (i=0; i < ce->num_interfaces; i++) {
    4235               2 :                 add_next_index_unicodel(return_value, ce->interfaces[i]->name.u, ce->interfaces[i]->name_length, 1);
    4236                 :         }
    4237                 : }
    4238                 : /* }}} */
    4239                 : 
    4240                 : /* {{{ proto public ReflectionClass ReflectionClass::getParentClass() U
    4241                 :    Returns the class' parent class, or, if none exists, FALSE */
    4242                 : ZEND_METHOD(reflection_class, getParentClass)
    4243              10 : {
    4244                 :         reflection_object *intern;
    4245                 :         zend_class_entry *ce;
    4246                 : 
    4247              10 :         if (zend_parse_parameters_none() == FAILURE) {
    4248               3 :                 return;
    4249                 :         }
    4250               7 :         GET_REFLECTION_OBJECT_PTR(ce);
    4251                 :         
    4252               7 :         if (ce->parent) {
    4253               2 :                 zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC);
    4254                 :         } else {
    4255               5 :                 RETURN_FALSE;
    4256                 :         }
    4257                 : }
    4258                 : /* }}} */
    4259                 : 
    4260                 : /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class) U
    4261                 :    Returns whether this class is a subclass of another class */
    4262                 : ZEND_METHOD(reflection_class, isSubclassOf)
    4263             123 : {
    4264                 :         reflection_object *intern, *argument;
    4265                 :         zend_class_entry *ce, **pce, *class_ce;
    4266                 :         zval *class_name;
    4267                 : 
    4268             123 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4269             123 :         GET_REFLECTION_OBJECT_PTR(ce);
    4270                 : 
    4271             123 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &class_name) == FAILURE) {
    4272               8 :                 return;
    4273                 :         }
    4274                 :         
    4275             115 :         switch(class_name->type) {
    4276                 :                 case IS_STRING:
    4277                 :                 case IS_UNICODE:
    4278              49 :                         if (zend_u_lookup_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
    4279               4 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    4280                 :                                                 "Class %R does not exist", Z_TYPE_P(class_name), Z_UNIVAL_P(class_name));
    4281               4 :                                 return;
    4282                 :                         }
    4283              45 :                         class_ce = *pce;
    4284              45 :                         break;                  
    4285                 :                 case IS_OBJECT:
    4286              62 :                         if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr TSRMLS_CC)) {
    4287              62 :                                 argument = (reflection_object *) zend_object_store_get_object(class_name TSRMLS_CC);
    4288              62 :                                 if (argument == NULL || argument->ptr == NULL) {
    4289               0 :                                         zend_error(E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
    4290                 :                                         /* Bails out */
    4291                 :                                 }
    4292              62 :                                 class_ce = argument->ptr;
    4293              62 :                                 break;
    4294                 :                         }
    4295                 :                         /* no break */
    4296                 :                 default:
    4297               4 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    4298                 :                                         "Parameter one must either be a string or a ReflectionClass object");
    4299               4 :                         return;
    4300                 :         }
    4301                 : 
    4302             107 :         RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce TSRMLS_CC)));
    4303                 : }
    4304                 : /* }}} */
    4305                 : 
    4306                 : /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name) U
    4307                 :    Returns whether this class is a subclass of another class */
    4308                 : ZEND_METHOD(reflection_class, implementsInterface)
    4309              56 : {
    4310                 :         reflection_object *intern, *argument;
    4311                 :         zend_class_entry *ce, *interface_ce, **pce;
    4312                 :         zval *interface;
    4313                 : 
    4314              56 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4315              56 :         GET_REFLECTION_OBJECT_PTR(ce);
    4316                 : 
    4317              56 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &interface) == FAILURE) {
    4318               2 :                 return;
    4319                 :         }
    4320                 :         
    4321              54 :         switch(interface->type) {
    4322                 :                 case IS_STRING:
    4323                 :                 case IS_UNICODE:
    4324              27 :                         if (zend_u_lookup_class(Z_TYPE_P(interface), Z_UNIVAL_P(interface), Z_UNILEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
    4325               2 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    4326                 :                                                 "Interface %R does not exist", Z_TYPE_P(interface), Z_UNIVAL_P(interface));
    4327               2 :                                 return;
    4328                 :                         }
    4329              25 :                         interface_ce = *pce;
    4330              25 :                         break;                  
    4331                 :                 case IS_OBJECT:
    4332              25 :                         if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr TSRMLS_CC)) {
    4333              25 :                                 argument = (reflection_object *) zend_object_store_get_object(interface TSRMLS_CC);
    4334              25 :                                 if (argument == NULL || argument->ptr == NULL) {
    4335               0 :                                         zend_error(E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
    4336                 :                                         /* Bails out */
    4337                 :                                 }
    4338              25 :                                 interface_ce = argument->ptr;
    4339              25 :                                 break;
    4340                 :                         }
    4341                 :                         /* no break */
    4342                 :                 default:
    4343               2 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    4344                 :                                         "Parameter one must either be a string or a ReflectionClass object");
    4345               2 :                         return;
    4346                 :         }
    4347                 : 
    4348              50 :         if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
    4349              30 :                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
    4350                 :                                 "Interface %v is a Class", interface_ce->name);
    4351              30 :                 return;
    4352                 :         }
    4353              20 :         RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
    4354                 : }
    4355                 : /* }}} */
    4356                 : 
    4357                 : /* {{{ proto public bool ReflectionClass::isIterateable() U
    4358                 :    Returns whether this class is iterateable (can be used inside foreach) */
    4359                 : ZEND_METHOD(reflection_class, isIterateable)
    4360              27 : {
    4361                 :         reflection_object *intern;
    4362                 :         zend_class_entry *ce;
    4363                 : 
    4364              27 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4365              27 :         GET_REFLECTION_OBJECT_PTR(ce);
    4366                 : 
    4367              27 :         RETURN_BOOL(ce->get_iterator != NULL);
    4368                 : }
    4369                 : /* }}} */
    4370                 : 
    4371                 : /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension() U
    4372                 :    Returns NULL or the extension the class belongs to */
    4373                 : ZEND_METHOD(reflection_class, getExtension)
    4374               2 : {
    4375                 :         reflection_object *intern;
    4376                 :         zend_class_entry *ce;
    4377                 : 
    4378               2 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4379               2 :         GET_REFLECTION_OBJECT_PTR(ce);
    4380                 : 
    4381               2 :         if (ce->module) {
    4382               1 :                 reflection_extension_factory(return_value, ce->module->name TSRMLS_CC);
    4383                 :         }
    4384                 : }
    4385                 : /* }}} */
    4386                 : 
    4387                 : /* {{{ proto public string|false ReflectionClass::getExtensionName() U
    4388                 :    Returns false or the name of the extension the class belongs to */
    4389                 : ZEND_METHOD(reflection_class, getExtensionName)
    4390               6 : {
    4391                 :         reflection_object *intern;
    4392                 :         zend_class_entry *ce;
    4393                 : 
    4394               6 :         METHOD_NOTSTATIC(reflection_class_ptr);
    4395               6 :         GET_REFLECTION_OBJECT_PTR(ce);
    4396                 : 
    4397               6 :         if (ce->module) {
    4398               5 :                 RETURN_ASCII_STRING(ce->module->name, 1);
    4399                 :         } else {
    4400               1 :                 RETURN_FALSE;
    4401                 :         }
    4402                 : }
    4403                 : /* }}} */
    4404                 : 
    4405                 : /* {{{ proto public bool ReflectionClass::inNamespace()
    4406                 :    Returns whether this class is defined in namespace */
    4407                 : ZEND_METHOD(reflection_class, inNamespace)
    4408               2 : {
    4409                 :         zval **name;
    4410                 :         zstr colon;
    4411                 : 
    4412               2 :         if (zend_parse_parameters_none() == FAILURE) {
    4413               0 :                 return;
    4414                 :         }
    4415               2 :         if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
    4416               0 :                 RETURN_FALSE;
    4417                 :         }
    4418               2 :         if (Z_TYPE_PP(name) == IS_STRING
    4419                 :                 && (colon.s = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
    4420                 :                 && colon.s > Z_STRVAL_PP(name))
    4421                 :         {
    4422               0 :                 RETURN_TRUE;
    4423               2 :         } else if (Z_TYPE_PP(name) == IS_UNICODE
    4424                 :                 && (colon.u = u_memrchr(Z_USTRVAL_PP(name), '\\', Z_USTRLEN_PP(name)))
    4425                 :                 && colon.u > Z_USTRVAL_PP(name))
    4426                 :         {
    4427               1 :                 RETURN_TRUE;
    4428                 :         }
    4429               1 :         RETURN_FALSE;
    4430                 : }
    4431                 : /* }}} */
    4432                 : 
    4433                 : /* {{{ proto public string ReflectionClass::getNamespaceName()
    4434                 :    Returns the name of namespace where this class is defined */
    4435                 : ZEND_METHOD(reflection_class, getNamespaceName)
    4436               2 : {
    4437                 :         zval **name;
    4438                 :         zstr colon;
    4439                 : 
    4440               2 :         if (zend_parse_parameters_none() == FAILURE) {
    4441               0 :                 return;
    4442                 :         }
    4443               2 :         if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
    4444               0 :                 RETURN_FALSE;
    4445                 :         }
    4446               2 :         if (Z_TYPE_PP(name) == IS_STRING
    4447                 :                 && (colon.s = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
    4448                 :                 && colon.s > Z_STRVAL_PP(name))
    4449                 :         {
    4450               0 :                 RETURN_STRINGL(Z_STRVAL_PP(name), colon.s - Z_STRVAL_PP(name) - 1, 1);
    4451               2 :         } else if (Z_TYPE_PP(name) == IS_UNICODE
    4452                 :                 && (colon.u = u_memrchr(Z_USTRVAL_PP(name), '\\', Z_USTRLEN_PP(name)))
    4453                 :                 && colon.u > Z_USTRVAL_PP(name))
    4454                 :         {
    4455               1 :                 RETURN_UNICODEL(Z_USTRVAL_PP(name), colon.u - Z_USTRVAL_PP(name), 1);
    4456                 :         }
    4457               1 :         RETURN_EMPTY_UNICODE();
    4458                 : }
    4459                 : /* }}} */
    4460                 : 
    4461                 : /* {{{ proto public string ReflectionClass::getShortName()
    4462                 :    Returns the short name of the class (without namespace part) */
    4463                 : ZEND_METHOD(reflection_class, getShortName)
    4464               2 : {
    4465                 :         zval **name;
    4466                 :         zstr colon;
    4467                 : 
    4468               2 :         if (zend_parse_parameters_none() == FAILURE) {
    4469               0 :                 return;
    4470                 :         }
    4471               2 :         if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
    4472               0 :                 RETURN_FALSE;
    4473                 :         }
    4474               2 :         if (Z_TYPE_PP(name) == IS_STRING
    4475                 :                 && (colon.s = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
    4476                 :                 && colon.s > Z_STRVAL_PP(name))
    4477                 :         {
    4478               0 :                 RETURN_STRINGL(colon.s + 1, Z_STRLEN_PP(name) - (colon.s - Z_STRVAL_PP(name) + 1), 1);
    4479               2 :         } else if (Z_TYPE_PP(name) == IS_UNICODE
    4480                 :                 && (colon.u = u_memrchr(Z_USTRVAL_PP(name), '\\', Z_USTRLEN_PP(name)))
    4481                 :                 && colon.u > Z_USTRVAL_PP(name))
    4482                 :         {
    4483               1 :                 RETURN_UNICODEL(colon.u + 1, Z_USTRLEN_PP(name) - (colon.u - Z_USTRVAL_PP(name) + 1), 1);
    4484                 :         }
    4485               1 :         RETURN_ZVAL(*name, 1, 0);
    4486                 : }
    4487                 : /* }}} */
    4488                 : 
    4489                 : /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException U
    4490                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    4491                 : ZEND_METHOD(reflection_object, export)
    4492               4 : {
    4493               4 :         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
    4494               4 : }
    4495                 : /* }}} */
    4496                 : 
    4497                 : /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException U
    4498                 :    Constructor. Takes an instance as an argument */
    4499                 : ZEND_METHOD(reflection_object, __construct)
    4500              94 : {
    4501              94 :         reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    4502              94 : }
    4503                 : /* }}} */
    4504                 : 
    4505                 : /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException U
    4506                 :    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
    4507                 : ZEND_METHOD(reflection_property, export)
    4508              14 : {
    4509              14 :         _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
    4510              14 : }
    4511                 : /* }}} */
    4512                 : 
    4513                 : /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name) U
    4514                 :    Constructor. Throws an Exception in case the given property does not exist */
    4515                 : ZEND_METHOD(reflection_property, __construct)
    4516              86 : {
    4517                 :         zval *propname, *classname;
    4518                 :         zstr name_str, class_name, prop_name;
    4519              86 :         int name_len, dynam_prop = 0;
    4520                 :         zval *object;
    4521                 :         reflection_object *intern;
    4522                 :         zend_class_entry **pce;
    4523                 :         zend_class_entry *ce;
    4524              86 :         zend_property_info *property_info = NULL;
    4525                 :         property_reference *reference;
    4526                 :         zend_uchar name_type;
    4527                 : 
    4528              86 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zt", &classname, &name_str, &name_len, &name_type) == FAILURE) {
    4529               3 :                 return;
    4530                 :         }
    4531                 : 
    4532              83 :         object = getThis();
    4533              83 :         intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
    4534              83 :         if (intern == NULL) {
    4535               0 :                 return;
    4536                 :         }
    4537                 :         
    4538                 :         /* Find the class entry */
    4539              83 :         switch (Z_TYPE_P(classname)) {
    4540                 :                 case IS_STRING:
    4541                 :                 case IS_UNICODE:
    4542              72 :                         if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
    4543               3 :                                 zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
    4544                 :                                                 "Class %R does not exist", Z_TYPE_P(classname), Z_UNIVAL_P(classname)); 
    4545               3 :                                 return;
    4546                 :                         }
    4547              69 :                         ce = *pce;
    4548              69 :                         break;
    4549                 : 
    4550                 :                 case IS_OBJECT:
    4551               9 :                         ce = Z_OBJCE_P(classname);
    4552               9 :                         break;
    4553                 :                         
    4554                 :                 default:
    4555               2 :                         _DO_THROW("The parameter class is expected to be either a string or an object");
    4556                 :                         /* returns out of this function */
    4557                 :         }
    4558                 : 
    4559              78 :         if (zend_u_hash_find(&ce->properties_info, name_type, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
    4560                 :                 /* Check for dynamic properties */
    4561              10 :                 if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT && Z_OBJ_HT_P(classname)->get_properties) {
    4562               3 :                         if (zend_u_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname TSRMLS_CC), name_type, name_str, name_len+1)) {
    4563               2 :                                 dynam_prop = 1;
    4564                 :                         }
    4565                 :                 }
    4566              10 :                 if (dynam_prop == 0) {
    4567               8 :                         zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Property %v::$%v does not exist", ce->name, name_str);
    4568               8 :                         return;
    4569                 :                 }
    4570                 :         }
    4571                 :         
    4572              70 :         if (dynam_prop == 0 && !(property_info->flags & ZEND_ACC_PRIVATE)) {
    4573                 :                 /* we have to search the class hierarchy for this (implicit) public or protected property */
    4574              55 :                 zend_class_entry *tmp_ce = ce;
    4575                 :                 zend_property_info *tmp_info;
    4576                 :                 
    4577             110 :                 while (tmp_ce && zend_u_hash_find(&tmp_ce->properties_info, name_type, name_str, name_len + 1, (void **) &tmp_info) != SUCCESS) {
    4578               0 :                         ce = tmp_ce;
    4579               0 :                         property_info = tmp_info;
    4580               0 :                         tmp_ce = tmp_ce->parent;
    4581                 :                 }
    4582                 :         }
    4583                 : 
    4584              70 :         MAKE_STD_ZVAL(classname);
    4585              70 :         MAKE_STD_ZVAL(propname);
    4586                 : 
    4587              70 :         if (dynam_prop == 0) {
    4588              68 :                 zend_u_unmangle_property_name(IS_UNICODE, property_info->name, property_info->name_length, &class_name, &prop_name);
    4589              68 :                 ZVAL_UNICODEL(classname, property_info->ce->name.u, property_info->ce->name_length, 1);
    4590              68 :                 ZVAL_UNICODE(propname, prop_name.u, 1);
    4591                 :         } else {
    4592               2 :                 ZVAL_UNICODEL(classname, ce->name.u, ce->name_length, 1);
    4593               2 :                 ZVAL_UNICODEL(propname, name_str.u, name_len, 1);
    4594                 :         }
    4595              70 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
    4596              70 :         zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
    4597                 : 
    4598              70 :         reference = (property_reference*) emalloc(sizeof(property_reference));
    4599              70 :         if (dynam_prop) {
    4600               2 :                 reference->prop.flags = ZEND_ACC_IMPLICIT_PUBLIC;
    4601               2 :                 reference->prop.name = Z_UNIVAL_P(propname);
    4602               2 :                 reference->prop.name_length = Z_UNILEN_P(propname);
    4603               2 :                 reference->prop.h = zend_u_get_hash_value(name_type, name_str, name_len+1);
    4604               2 :                 reference->prop.doc_comment = NULL_ZSTR;
    4605               2 :                 reference->prop.ce = ce;
    4606                 :         } else {
    4607              68 :                 reference->prop = *property_info;
    4608                 :         }
    4609              70 :         reference->ce = ce;
    4610              70 :         intern->ptr = reference;
    4611              70 :         intern->ref_type = REF_TYPE_PROPERTY;
    4612              70 :         intern->ce = ce;
    4613              70 :         intern->ignore_visibility = 0;
    4614                 : }
    4615                 : /* }}} */
    4616                 : 
    4617                 : /* {{{ proto public string ReflectionProperty::__toString() U
    4618                 :    Returns a string representation */
    4619                 : ZEND_METHOD(reflection_property, __toString)
    4620              13 : {
    4621                 :         reflection_object *intern;
    4622                 :         property_reference *ref;
    4623                 :         string str;
    4624                 : 
    4625              13 :         if (zend_parse_parameters_none() == FAILURE) {
    4626               0 :                 return;
    4627                 :         }
    4628              13 :         GET_REFLECTION_OBJECT_PTR(ref);
    4629              13 :         string_init(&str);
    4630              13 :         _property_string(&str, &ref->prop, NULL_ZSTR, "" TSRMLS_CC);
    4631              13 :         RETURN_U_STRINGL(ZEND_U_CONVERTER(UG(output_encoding_conv)), str.string, str.len - 1, ZSTR_AUTOFREE);
    4632                 : }
    4633                 : /* }}} */
    4634                 : 
    4635                 : /* {{{ proto public string ReflectionProperty::getName() U
    4636                 :    Returns the class' name */
    4637                 : ZEND_METHOD(reflection_property, getName)
    4638              91 : {
    4639              91 :         if (zend_parse_parameters_none() == FAILURE) {
    4640               1 :                 return;
    4641                 :         }
    4642              90 :         _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
    4643                 : }
    4644                 : /* }}} */
    4645                 : 
    4646                 : static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
    4647             216 : {
    4648                 :         reflection_object *intern;
    4649                 :         property_reference *ref;
    4650                 : 
    4651             216 :         if (zend_parse_parameters_none() == FAILURE) {
    4652               6 :                 return;
    4653                 :         }
    4654             210 :         GET_REFLECTION_OBJECT_PTR(ref);
    4655             210 :         RETURN_BOOL(ref->prop.flags & mask);
    4656                 : }
    4657                 : /* }}} */
    4658                 : 
    4659                 : /* {{{ proto public bool ReflectionProperty::isPublic() U
    4660                 :    Returns whether this property is public */
    4661                 : ZEND_METHOD(reflection_property, isPublic)
    4662              47 : {
    4663              47 :         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
    4664              47 : }
    4665                 : /* }}} */
    4666                 : 
    4667                 : /* {{{ proto public bool ReflectionProperty::isPrivate() U
    4668                 :    Returns whether this property is private */
    4669                 : ZEND_METHOD(reflection_property, isPrivate)
    4670              41 : {
    4671              41 :         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
    4672              41 : }
    4673                 : /* }}} */
    4674                 : 
    4675                 : /* {{{ proto public bool ReflectionProperty::isProtected() U
    4676                 :    Returns whether this property is protected */
    4677                 : ZEND_METHOD(reflection_property, isProtected)
    4678              42 : {
    4679              42 :         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
    4680              42 : }
    4681                 : /* }}} */
    4682                 : 
    4683                 : /* {{{ proto public bool ReflectionProperty::isStatic() U
    4684                 :    Returns whether this property is static */
    4685                 : ZEND_METHOD(reflection_property, isStatic)
    4686              42 : {
    4687              42 :         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
    4688              42 : }
    4689                 : /* }}} */
    4690                 : 
    4691                 : /* {{{ proto public bool ReflectionProperty::isDefault() U
    4692                 :    Returns whether this property is default (declared at compilation time). */
    4693                 : ZEND_METHOD(reflection_property, isDefault)
    4694              44 : {
    4695              44 :         _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ~ZEND_ACC_IMPLICIT_PUBLIC);
    4696              44 : }
    4697                 : /* }}} */
    4698                 : 
    4699                 : /* {{{ proto public mixed ReflectionProperty::getDefaultValue() U
    4700                 :    Returns the default value of the property. */
    4701                 : ZEND_METHOD(reflection_property, getDefaultValue)
    4702              22 : {
    4703                 :         reflection_object *intern;
    4704