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

LCOV - code coverage report
Current view: top level - ext/reflection - php_reflection.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 2159 2382 90.6 %
Date: 2014-07-13 Functions: 173 177 97.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 13 Jul 2014 23:57:55 +0000 (9 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.