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-21 Instrumented lines: 2297
Code covered: 90.6 % Executed lines: 2080
Legend: not executed executed

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