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

LTP GCOV extension - code coverage report
Current view: directory - reflection - php_reflection.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 2060
Code covered: 85.3 % Executed lines: 1757
Legend: not executed executed

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