LTP GCOV extension - code coverage report
Current view: directory - ext/reflection - php_reflection.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 1976
Code covered: 3.5 % Executed lines: 69
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5