Back to index

php5  5.3.10
php_reflection.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Timm Friebe <thekid@thekid.de>                              |
00016    |          George Schlossnagle <george@omniti.com>                     |
00017    |          Andrei Zmievski <andrei@gravitonic.com>                     |
00018    |          Marcus Boerger <helly@php.net>                              |
00019    |          Johannes Schlueter <johannes@php.net>                       |
00020    +----------------------------------------------------------------------+
00021 */
00022 
00023 /* $Id: php_reflection.c 321634 2012-01-01 13:15:04Z felipe $ */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include "php.h"
00030 #include "php_ini.h"
00031 #include "php_reflection.h"
00032 #include "ext/standard/info.h"
00033 
00034 #include "zend.h"
00035 #include "zend_API.h"
00036 #include "zend_exceptions.h"
00037 #include "zend_operators.h"
00038 #include "zend_constants.h"
00039 #include "zend_ini.h"
00040 #include "zend_interfaces.h"
00041 #include "zend_closures.h"
00042 
00043 /* Undefine "getParameters" macro defined in "main/php3_compat.h" */
00044 #ifdef getParameters
00045 # undef getParameters
00046 #endif
00047 
00048 /* Class entry pointers */
00049 PHPAPI zend_class_entry *reflector_ptr;
00050 PHPAPI zend_class_entry *reflection_exception_ptr;
00051 PHPAPI zend_class_entry *reflection_ptr;
00052 PHPAPI zend_class_entry *reflection_function_abstract_ptr;
00053 PHPAPI zend_class_entry *reflection_function_ptr;
00054 PHPAPI zend_class_entry *reflection_parameter_ptr;
00055 PHPAPI zend_class_entry *reflection_class_ptr;
00056 PHPAPI zend_class_entry *reflection_object_ptr;
00057 PHPAPI zend_class_entry *reflection_method_ptr;
00058 PHPAPI zend_class_entry *reflection_property_ptr;
00059 PHPAPI zend_class_entry *reflection_extension_ptr;
00060 
00061 #if MBO_0
00062 ZEND_BEGIN_MODULE_GLOBALS(reflection)
00063        int dummy;
00064 ZEND_END_MODULE_GLOBALS(reflection)
00065 
00066 #ifdef ZTS
00067 # define REFLECTION_G(v) \
00068        TSRMG(reflection_globals_id, zend_reflection_globals*, v)
00069 extern int reflection_globals_id;
00070 #else
00071 # define REFLECTION_G(v) (reflection_globals.v)
00072 extern zend_reflection_globals reflectionglobals;
00073 #endif
00074 
00075 ZEND_DECLARE_MODULE_GLOBALS(reflection)
00076 #endif /* MBO_0 */
00077 
00078 /* Method macros */
00079 
00080 #define METHOD_NOTSTATIC(ce)                                                                                \
00081        if (!this_ptr || !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {                             \
00082               php_error_docref(NULL TSRMLS_CC, E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C));        \
00083               return;                                                                                             \
00084        }                                                                                                       \
00085 
00086 /* Exception throwing macro */
00087 #define _DO_THROW(msg)                                                                                      \
00088        zend_throw_exception(reflection_exception_ptr, msg, 0 TSRMLS_CC);                                       \
00089        return;                                                                                                 \
00090 
00091 #define RETURN_ON_EXCEPTION                                                                                 \
00092        if (EG(exception) && Z_OBJCE_P(EG(exception)) == reflection_exception_ptr) {                            \
00093               return;                                                                                             \
00094        }
00095 
00096 #define GET_REFLECTION_OBJECT_PTR(target)                                                                   \
00097        intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC);                       \
00098        if (intern == NULL || intern->ptr == NULL) {                                                            \
00099               RETURN_ON_EXCEPTION                                                                                 \
00100               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the reflection object");                    \
00101        }                                                                                                       \
00102        target = intern->ptr;                                                                                   \
00103 
00104 /* Class constants */
00105 #define REGISTER_REFLECTION_CLASS_CONST_LONG(class_name, const_name, value)                                        \
00106        zend_declare_class_constant_long(reflection_ ## class_name ## _ptr, const_name, sizeof(const_name)-1, (long)value TSRMLS_CC);
00107 
00108 /* {{{ Smart string functions */
00109 typedef struct _string {
00110        char *string;
00111        int len;
00112        int alloced;
00113 } string;
00114 
00115 static void string_init(string *str)
00116 {
00117        str->string = (char *) emalloc(1024);
00118        str->len = 1;
00119        str->alloced = 1024;
00120        *str->string = '\0';
00121 }
00122        
00123 static string *string_printf(string *str, const char *format, ...)
00124 {
00125        int len;
00126        va_list arg;
00127        char *s_tmp;
00128 
00129        va_start(arg, format);
00130        len = zend_vspprintf(&s_tmp, 0, format, arg);
00131        if (len) {
00132               register int nlen = (str->len + len + (1024 - 1)) & ~(1024 - 1);
00133               if (str->alloced < nlen) {
00134                      str->alloced = nlen;
00135                      str->string = erealloc(str->string, str->alloced);
00136               }
00137               memcpy(str->string + str->len - 1, s_tmp, len + 1);
00138               str->len += len;
00139        }
00140        efree(s_tmp);
00141        va_end(arg);
00142        return str;
00143 }
00144 
00145 static string *string_write(string *str, char *buf, int len)
00146 {
00147        register int nlen = (str->len + len + (1024 - 1)) & ~(1024 - 1);
00148        if (str->alloced < nlen) {
00149               str->alloced = nlen;
00150               str->string = erealloc(str->string, str->alloced);
00151        }
00152        memcpy(str->string + str->len - 1, buf, len);
00153        str->len += len;
00154        str->string[str->len - 1] = '\0';
00155        return str;
00156 }
00157 
00158 static string *string_append(string *str, string *append)
00159 {
00160        if (append->len > 1) {
00161               string_write(str, append->string, append->len - 1);
00162        }
00163        return str;
00164 }
00165 
00166 static void string_free(string *str)
00167 {
00168        efree(str->string);
00169        str->len = 0;
00170        str->alloced = 0;
00171        str->string = NULL;
00172 }
00173 /* }}} */
00174 
00175 /* Struct for properties */
00176 typedef struct _property_reference {
00177        zend_class_entry *ce;
00178        zend_property_info prop;
00179 } property_reference;
00180 
00181 /* Struct for parameters */
00182 typedef struct _parameter_reference {
00183        zend_uint offset;
00184        zend_uint required;
00185        struct _zend_arg_info *arg_info;
00186        zend_function *fptr;
00187 } parameter_reference;
00188 
00189 typedef enum {
00190        REF_TYPE_OTHER,      /* Must be 0 */
00191        REF_TYPE_FUNCTION,
00192        REF_TYPE_PARAMETER,
00193        REF_TYPE_PROPERTY,
00194        REF_TYPE_DYNAMIC_PROPERTY
00195 } reflection_type_t;
00196 
00197 /* Struct for reflection objects */
00198 typedef struct {
00199        zend_object zo;
00200        void *ptr;
00201        reflection_type_t ref_type;
00202        zval *obj;
00203        zend_class_entry *ce;
00204        unsigned int ignore_visibility:1;
00205 } reflection_object;
00206 
00207 static zend_object_handlers reflection_object_handlers;
00208 
00209 static void _default_get_entry(zval *object, char *name, int name_len, zval *return_value TSRMLS_DC)
00210 {
00211        zval **value;
00212 
00213        if (zend_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
00214               RETURN_FALSE;
00215        }
00216 
00217        MAKE_COPY_ZVAL(value, return_value);
00218 }
00219 
00220 #ifdef ilia_0
00221 static void _default_lookup_entry(zval *object, char *name, int name_len, zval **return_value TSRMLS_DC) /* {{{ */
00222 {
00223        zval **value;
00224 
00225        if (zend_hash_find(Z_OBJPROP_P(object), name, name_len, (void **) &value) == FAILURE) {
00226               *return_value = NULL;
00227        } else {
00228               *return_value = *value;
00229        }
00230 }
00231 /* }}} */
00232 #endif
00233 
00234 static void reflection_register_implement(zend_class_entry *class_entry, zend_class_entry *interface_entry TSRMLS_DC)
00235 {
00236        zend_uint num_interfaces = ++class_entry->num_interfaces;
00237 
00238        class_entry->interfaces = (zend_class_entry **) realloc(class_entry->interfaces, sizeof(zend_class_entry *) * num_interfaces);
00239        class_entry->interfaces[num_interfaces - 1] = interface_entry;
00240 }
00241 
00242 static zend_function *_copy_function(zend_function *fptr TSRMLS_DC) /* {{{ */
00243 {
00244        if (fptr
00245               && fptr->type == ZEND_INTERNAL_FUNCTION
00246               && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
00247        {
00248               zend_function *copy_fptr;
00249               copy_fptr = emalloc(sizeof(zend_function));
00250               memcpy(copy_fptr, fptr, sizeof(zend_function));
00251               copy_fptr->internal_function.function_name = estrdup(fptr->internal_function.function_name);
00252               return copy_fptr;
00253        } else {
00254               /* no copy needed */
00255               return fptr;
00256        }
00257 }
00258 /* }}} */
00259 
00260 static void _free_function(zend_function *fptr TSRMLS_DC) /* {{{ */
00261 {
00262        if (fptr
00263               && fptr->type == ZEND_INTERNAL_FUNCTION
00264               && (fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0)
00265        {
00266               efree(fptr->internal_function.function_name);
00267               efree(fptr);
00268        }
00269 }
00270 /* }}} */
00271 
00272 static void reflection_free_objects_storage(void *object TSRMLS_DC)
00273 {
00274        reflection_object *intern = (reflection_object *) object;
00275        parameter_reference *reference;
00276        property_reference *prop_reference;
00277 
00278        if (intern->ptr) {
00279               switch (intern->ref_type) {
00280               case REF_TYPE_PARAMETER:
00281                      reference = (parameter_reference*)intern->ptr;
00282                      _free_function(reference->fptr TSRMLS_CC);
00283                      efree(intern->ptr);
00284                      break;
00285               case REF_TYPE_FUNCTION:
00286                      _free_function(intern->ptr TSRMLS_CC);
00287                      break;
00288               case REF_TYPE_PROPERTY:
00289                      efree(intern->ptr);
00290                      break;
00291               case REF_TYPE_DYNAMIC_PROPERTY:
00292                      prop_reference = (property_reference*)intern->ptr;
00293                      efree(prop_reference->prop.name);
00294                      efree(intern->ptr);
00295                      break;
00296               case REF_TYPE_OTHER:
00297                      break;
00298               }
00299        }
00300        intern->ptr = NULL;
00301        if (intern->obj) {
00302               zval_ptr_dtor(&intern->obj);
00303        }
00304        zend_objects_free_object_storage(object TSRMLS_CC);
00305 }
00306 
00307 static zend_object_value reflection_objects_new(zend_class_entry *class_type TSRMLS_DC)
00308 {
00309        zval tmp;
00310        zend_object_value retval;
00311        reflection_object *intern;
00312 
00313        intern = ecalloc(1, sizeof(reflection_object));
00314        intern->zo.ce = class_type;
00315 
00316        zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
00317        zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
00318        retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, NULL TSRMLS_CC);
00319        retval.handlers = &reflection_object_handlers;
00320        return retval;
00321 }
00322 
00323 static zval * reflection_instantiate(zend_class_entry *pce, zval *object TSRMLS_DC)
00324 {
00325        if (!object) {
00326               ALLOC_ZVAL(object);
00327        }
00328        Z_TYPE_P(object) = IS_OBJECT;
00329        object_init_ex(object, pce);
00330        Z_SET_REFCOUNT_P(object, 1);
00331        Z_SET_ISREF_P(object);
00332        return object;
00333 }
00334 
00335 static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC);
00336 static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char *indent TSRMLS_DC);
00337 static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC);
00338 static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC);
00339 static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC);
00340 
00341 /* {{{ _class_string */
00342 static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent TSRMLS_DC)
00343 {
00344        int count, count_static_props = 0, count_static_funcs = 0, count_shadow_props = 0;
00345        string sub_indent;
00346        
00347        string_init(&sub_indent);
00348        string_printf(&sub_indent, "%s    ", indent);
00349 
00350        /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */
00351        if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
00352               string_printf(str, "%s%s", indent, ce->doc_comment);
00353               string_write(str, "\n", 1);
00354        }
00355 
00356        if (obj) {
00357               string_printf(str, "%sObject of class [ ", indent);
00358        } else {
00359               string_printf(str, "%s%s [ ", indent, (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : "Class");
00360        }
00361        string_printf(str, (ce->type == ZEND_USER_CLASS) ? "<user" : "<internal");
00362        if (ce->module) {
00363               string_printf(str, ":%s", ce->module->name);
00364        }
00365        string_printf(str, "> ");
00366        if (ce->get_iterator != NULL) {
00367               string_printf(str, "<iterateable> ");
00368        }
00369        if (ce->ce_flags & ZEND_ACC_INTERFACE) {
00370               string_printf(str, "interface ");
00371        } else {
00372               if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
00373                      string_printf(str, "abstract ");
00374               }
00375               if (ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
00376                      string_printf(str, "final ");
00377               } 
00378               string_printf(str, "class ");
00379        }
00380        string_printf(str, "%s", ce->name);
00381        if (ce->parent) {
00382               string_printf(str, " extends %s", ce->parent->name);
00383        }
00384 
00385        if (ce->num_interfaces) {
00386               zend_uint i;
00387 
00388               if (ce->ce_flags & ZEND_ACC_INTERFACE) {
00389                      string_printf(str, " extends %s", ce->interfaces[0]->name);
00390               } else {
00391                      string_printf(str, " implements %s", ce->interfaces[0]->name);
00392               }
00393               for (i = 1; i < ce->num_interfaces; ++i) {
00394                      string_printf(str, ", %s", ce->interfaces[i]->name);
00395               }
00396        }
00397        string_printf(str, " ] {\n");
00398 
00399        /* The information where a class is declared is only available for user classes */
00400        if (ce->type == ZEND_USER_CLASS) {
00401               string_printf(str, "%s  @@ %s %d-%d\n", indent, ce->filename,
00402                                           ce->line_start, ce->line_end);
00403        }
00404 
00405        /* Constants */
00406        if (&ce->constants_table) {
00407               zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
00408               string_printf(str, "\n");
00409               count = zend_hash_num_elements(&ce->constants_table);
00410               string_printf(str, "%s  - Constants [%d] {\n", indent, count);
00411               if (count > 0) {
00412                      HashPosition pos;
00413                      zval **value;
00414                      char *key;
00415                      uint key_len;
00416                      ulong num_index;
00417 
00418                      zend_hash_internal_pointer_reset_ex(&ce->constants_table, &pos);
00419 
00420                      while (zend_hash_get_current_data_ex(&ce->constants_table, (void **) &value, &pos) == SUCCESS) {
00421                             zend_hash_get_current_key_ex(&ce->constants_table, &key, &key_len, &num_index, 0, &pos);
00422 
00423                             _const_string(str, key, *value, indent TSRMLS_CC);
00424                             zend_hash_move_forward_ex(&ce->constants_table, &pos);
00425                      }
00426               }
00427               string_printf(str, "%s  }\n", indent);
00428        }
00429 
00430        /* Static properties */
00431        if (&ce->properties_info) {
00432               /* counting static properties */          
00433               count = zend_hash_num_elements(&ce->properties_info);
00434               if (count > 0) {
00435                      HashPosition pos;
00436                      zend_property_info *prop;
00437 
00438                      zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
00439 
00440                      while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
00441                             if(prop->flags & ZEND_ACC_SHADOW) {
00442                                    count_shadow_props++;
00443                             } else if (prop->flags & ZEND_ACC_STATIC) {
00444                                    count_static_props++;
00445                             }
00446                             zend_hash_move_forward_ex(&ce->properties_info, &pos);
00447                      }
00448               }
00449 
00450               /* static properties */            
00451               string_printf(str, "\n%s  - Static properties [%d] {\n", indent, count_static_props);
00452               if (count_static_props > 0) {
00453                      HashPosition pos;
00454                      zend_property_info *prop;
00455 
00456                      zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
00457 
00458                      while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
00459                             if ((prop->flags & ZEND_ACC_STATIC) && !(prop->flags & ZEND_ACC_SHADOW)) {
00460                                    _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
00461                             }
00462 
00463                             zend_hash_move_forward_ex(&ce->properties_info, &pos);
00464                      }
00465               }
00466               string_printf(str, "%s  }\n", indent);
00467        }
00468        
00469        /* Static methods */
00470        if (&ce->function_table) {
00471               /* counting static methods */             
00472               count = zend_hash_num_elements(&ce->function_table);
00473               if (count > 0) {
00474                      HashPosition pos;
00475                      zend_function *mptr;
00476 
00477                      zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
00478 
00479                      while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
00480                             if (mptr->common.fn_flags & ZEND_ACC_STATIC
00481                                    && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
00482                             {
00483                                    count_static_funcs++;
00484                             }
00485                             zend_hash_move_forward_ex(&ce->function_table, &pos);
00486                      }
00487               }
00488 
00489               /* static methods */        
00490               string_printf(str, "\n%s  - Static methods [%d] {", indent, count_static_funcs);
00491               if (count_static_funcs > 0) {
00492                      HashPosition pos;
00493                      zend_function *mptr;
00494 
00495                      zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
00496 
00497                      while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
00498                             if (mptr->common.fn_flags & ZEND_ACC_STATIC
00499                                    && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
00500                             {
00501                                    string_printf(str, "\n");
00502                                    _function_string(str, mptr, ce, sub_indent.string TSRMLS_CC);
00503                             }
00504                             zend_hash_move_forward_ex(&ce->function_table, &pos);
00505                      }
00506               } else {
00507                      string_printf(str, "\n");
00508               }
00509               string_printf(str, "%s  }\n", indent);
00510        }
00511 
00512        /* Default/Implicit properties */
00513        if (&ce->properties_info) {
00514               count = zend_hash_num_elements(&ce->properties_info) - count_static_props - count_shadow_props;
00515               string_printf(str, "\n%s  - Properties [%d] {\n", indent, count);
00516               if (count > 0) {
00517                      HashPosition pos;
00518                      zend_property_info *prop;
00519 
00520                      zend_hash_internal_pointer_reset_ex(&ce->properties_info, &pos);
00521 
00522                      while (zend_hash_get_current_data_ex(&ce->properties_info, (void **) &prop, &pos) == SUCCESS) {
00523                             if (!(prop->flags & (ZEND_ACC_STATIC|ZEND_ACC_SHADOW))) {
00524                                    _property_string(str, prop, NULL, sub_indent.string TSRMLS_CC);
00525                             }
00526                             zend_hash_move_forward_ex(&ce->properties_info, &pos);
00527                      }
00528               }
00529               string_printf(str, "%s  }\n", indent);
00530        }
00531 
00532        if (obj && Z_OBJ_HT_P(obj)->get_properties) {
00533               string       dyn;
00534               HashTable    *properties = Z_OBJ_HT_P(obj)->get_properties(obj TSRMLS_CC);
00535               HashPosition pos;
00536               zval         **prop;
00537 
00538               string_init(&dyn);
00539               count = 0;
00540 
00541               if (properties && zend_hash_num_elements(properties)) {
00542                      zend_hash_internal_pointer_reset_ex(properties, &pos);
00543 
00544                      while (zend_hash_get_current_data_ex(properties, (void **) &prop, &pos) == SUCCESS) {
00545                             char  *prop_name;
00546                             uint  prop_name_size;
00547                             ulong index;
00548 
00549                             if (zend_hash_get_current_key_ex(properties, &prop_name, &prop_name_size, &index, 1, &pos) == HASH_KEY_IS_STRING) {
00550                                    if (prop_name_size && prop_name[0]) { /* skip all private and protected properties */
00551                                           if (!zend_hash_quick_exists(&ce->properties_info, prop_name, prop_name_size, zend_get_hash_value(prop_name, prop_name_size))) {
00552                                                  count++;
00553                                                  _property_string(&dyn, NULL, prop_name, sub_indent.string TSRMLS_CC); 
00554                                           }
00555                                    }
00556                                    efree(prop_name);
00557                             }
00558                             zend_hash_move_forward_ex(properties, &pos);
00559                      }
00560               }
00561 
00562               string_printf(str, "\n%s  - Dynamic properties [%d] {\n", indent, count);
00563               string_append(str, &dyn);
00564               string_printf(str, "%s  }\n", indent);
00565               string_free(&dyn);
00566        }
00567 
00568        /* Non static methods */
00569        if (&ce->function_table) {
00570               count = zend_hash_num_elements(&ce->function_table) - count_static_funcs;
00571               if (count > 0) {
00572                      HashPosition pos;
00573                      zend_function *mptr;
00574                      string dyn;
00575 
00576                      count = 0;
00577                      string_init(&dyn);
00578                      zend_hash_internal_pointer_reset_ex(&ce->function_table, &pos);
00579 
00580                      while (zend_hash_get_current_data_ex(&ce->function_table, (void **) &mptr, &pos) == SUCCESS) {
00581                             if ((mptr->common.fn_flags & ZEND_ACC_STATIC) == 0
00582                                    && ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) == 0 || mptr->common.scope == ce))
00583                             {
00584                                    char *key;
00585                                    uint key_len;
00586                                    ulong num_index;
00587                                    uint len = strlen(mptr->common.function_name);
00588 
00589                                    /* Do not display old-style inherited constructors */
00590                                    if ((mptr->common.fn_flags & ZEND_ACC_CTOR) == 0
00591                                           || mptr->common.scope == ce
00592                                           || zend_hash_get_current_key_ex(&ce->function_table, &key, &key_len, &num_index, 0, &pos) != HASH_KEY_IS_STRING
00593                                           || zend_binary_strcasecmp(key, key_len-1, mptr->common.function_name, len) == 0)
00594                                    {
00595                                           zend_function *closure;
00596                                           /* see if this is a closure */
00597                                           if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
00598                                                  && memcmp(mptr->common.function_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
00599                                                  && (closure = zend_get_closure_invoke_method(obj TSRMLS_CC)) != NULL)
00600                                           {
00601                                                  mptr = closure;
00602                                           } else {
00603                                                  closure = NULL;
00604                                           }
00605                                           string_printf(&dyn, "\n");
00606                                           _function_string(&dyn, mptr, ce, sub_indent.string TSRMLS_CC);
00607                                           count++;
00608                                           _free_function(closure TSRMLS_CC);
00609                                    }
00610                             }
00611                             zend_hash_move_forward_ex(&ce->function_table, &pos);
00612                      }
00613                      string_printf(str, "\n%s  - Methods [%d] {", indent, count);
00614                      if (!count) {
00615                             string_printf(str, "\n");
00616                      }
00617                      string_append(str, &dyn);
00618                      string_free(&dyn);
00619               } else {
00620                      string_printf(str, "\n%s  - Methods [0] {\n", indent);
00621               }
00622               string_printf(str, "%s  }\n", indent);
00623        }
00624        
00625        string_printf(str, "%s}\n", indent);
00626        string_free(&sub_indent);
00627 }
00628 /* }}} */
00629 
00630 /* {{{ _const_string */
00631 static void _const_string(string *str, char *name, zval *value, char *indent TSRMLS_DC)
00632 {
00633        char *type;
00634        zval value_copy;
00635        int use_copy;
00636 
00637        type = zend_zval_type_name(value);
00638 
00639        zend_make_printable_zval(value, &value_copy, &use_copy);
00640        if (use_copy) {
00641               value = &value_copy;
00642        }
00643 
00644        string_printf(str, "%s    Constant [ %s %s ] { %s }\n",
00645                                    indent, type, name, Z_STRVAL_P(value));
00646 
00647        if (use_copy) {
00648               zval_dtor(value);
00649        }
00650 }
00651 /* }}} */
00652 
00653 /* {{{ _get_recv_opcode */
00654 static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
00655 {
00656        zend_op *op = op_array->opcodes;
00657        zend_op *end = op + op_array->last;
00658 
00659        ++offset;
00660        while (op < end) {
00661               if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
00662                      && op->op1.u.constant.value.lval == (long)offset)
00663               {
00664                      return op;
00665               }
00666               ++op;
00667        }
00668        return NULL;
00669 }
00670 /* }}} */
00671 
00672 /* {{{ _parameter_string */
00673 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)
00674 {
00675        string_printf(str, "Parameter #%d [ ", offset);
00676        if (offset >= required) {
00677               string_printf(str, "<optional> ");
00678        } else {
00679               string_printf(str, "<required> ");
00680        }
00681        if (arg_info->class_name) {
00682               string_printf(str, "%s ", arg_info->class_name);
00683               if (arg_info->allow_null) {
00684                      string_printf(str, "or NULL ");
00685               }
00686        } else if (arg_info->array_type_hint) {
00687               string_printf(str, "array ");
00688               if (arg_info->allow_null) {
00689                      string_printf(str, "or NULL ");
00690               }
00691        }
00692        if (arg_info->pass_by_reference) {
00693               string_write(str, "&", sizeof("&")-1);
00694        }
00695        if (arg_info->name) {
00696               string_printf(str, "$%s", arg_info->name);
00697        } else {
00698               string_printf(str, "$param%d", offset);
00699        }
00700        if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
00701               zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
00702               if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
00703                      zval *zv, zv_copy;
00704                      int use_copy;
00705                      string_write(str, " = ", sizeof(" = ")-1);
00706                      ALLOC_ZVAL(zv);
00707                      *zv = precv->op2.u.constant;
00708                      zval_copy_ctor(zv);
00709                      INIT_PZVAL(zv);
00710                      zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
00711                      if (Z_TYPE_P(zv) == IS_BOOL) {
00712                             if (Z_LVAL_P(zv)) {
00713                                    string_write(str, "true", sizeof("true")-1);
00714                             } else {
00715                                    string_write(str, "false", sizeof("false")-1);
00716                             }
00717                      } else if (Z_TYPE_P(zv) == IS_NULL) {
00718                             string_write(str, "NULL", sizeof("NULL")-1);
00719                      } else if (Z_TYPE_P(zv) == IS_STRING) {
00720                             string_write(str, "'", sizeof("'")-1);
00721                             string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15));
00722                             if (Z_STRLEN_P(zv) > 15) {
00723                                    string_write(str, "...", sizeof("...")-1);
00724                             }
00725                             string_write(str, "'", sizeof("'")-1);
00726                      } else {
00727                             zend_make_printable_zval(zv, &zv_copy, &use_copy);
00728                             string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
00729                             if (use_copy) {
00730                                    zval_dtor(&zv_copy);
00731                             }
00732                      }
00733                      zval_ptr_dtor(&zv);
00734               }
00735        }
00736        string_write(str, " ]", sizeof(" ]")-1);
00737 }
00738 /* }}} */
00739 
00740 /* {{{ _function_parameter_string */
00741 static void _function_parameter_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
00742 {
00743        struct _zend_arg_info *arg_info = fptr->common.arg_info;
00744        zend_uint i, required = fptr->common.required_num_args;
00745 
00746        if (!arg_info) {
00747               return;
00748        }
00749 
00750        string_printf(str, "\n");
00751        string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
00752        for (i = 0; i < fptr->common.num_args; i++) {
00753               string_printf(str, "%s  ", indent);
00754               _parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC);
00755               string_write(str, "\n", sizeof("\n")-1);
00756               arg_info++;
00757        }
00758        string_printf(str, "%s}\n", indent);
00759 }
00760 /* }}} */
00761 
00762 /* {{{ _function_closure_string */
00763 static void _function_closure_string(string *str, zend_function *fptr, char* indent TSRMLS_DC)
00764 {
00765        zend_uint i, count;
00766        ulong num_index;
00767        char *key;
00768        uint key_len;
00769        HashTable *static_variables;
00770        HashPosition pos;
00771 
00772        if (fptr->type != ZEND_USER_FUNCTION || !fptr->op_array.static_variables) {
00773               return;
00774        }
00775 
00776        static_variables = fptr->op_array.static_variables;
00777        count = zend_hash_num_elements(static_variables);
00778 
00779        if (!count) {
00780               return;
00781        }
00782 
00783        string_printf(str, "\n");
00784        string_printf(str, "%s- Bound Variables [%d] {\n", indent, zend_hash_num_elements(static_variables));
00785        zend_hash_internal_pointer_reset_ex(static_variables, &pos);
00786        i = 0;
00787        while (i < count) {
00788               zend_hash_get_current_key_ex(static_variables, &key, &key_len, &num_index, 0, &pos);
00789               string_printf(str, "%s    Variable #%d [ $%s ]\n", indent, i++, key);
00790               zend_hash_move_forward_ex(static_variables, &pos);
00791        }
00792        string_printf(str, "%s}\n", indent);
00793 }
00794 /* }}} */
00795 
00796 /* {{{ _function_string */
00797 static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent TSRMLS_DC)
00798 {
00799        string param_indent;
00800        zend_function *overwrites;
00801        char *lc_name;
00802        unsigned int lc_name_len;
00803 
00804        /* TBD: Repair indenting of doc comment (or is this to be done in the parser?)
00805         * What's "wrong" is that any whitespace before the doc comment start is 
00806         * swallowed, leading to an unaligned comment.
00807         */
00808        if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
00809               string_printf(str, "%s%s\n", indent, fptr->op_array.doc_comment);
00810        }
00811 
00812        string_write(str, indent, strlen(indent));
00813        string_printf(str, fptr->common.fn_flags & ZEND_ACC_CLOSURE ? "Closure [ " : (fptr->common.scope ? "Method [ " : "Function [ "));
00814        string_printf(str, (fptr->type == ZEND_USER_FUNCTION) ? "<user" : "<internal");
00815        if (fptr->common.fn_flags & ZEND_ACC_DEPRECATED) {
00816               string_printf(str, ", deprecated");
00817        }
00818        if (fptr->type == ZEND_INTERNAL_FUNCTION && ((zend_internal_function*)fptr)->module) {
00819               string_printf(str, ":%s", ((zend_internal_function*)fptr)->module->name);
00820        }
00821 
00822        if (scope && fptr->common.scope) {
00823               if (fptr->common.scope != scope) {
00824                      string_printf(str, ", inherits %s", fptr->common.scope->name);
00825               } else if (fptr->common.scope->parent) {
00826                      lc_name_len = strlen(fptr->common.function_name);
00827                      lc_name = zend_str_tolower_dup(fptr->common.function_name, lc_name_len);
00828                      if (zend_hash_find(&fptr->common.scope->parent->function_table, lc_name, lc_name_len + 1, (void**) &overwrites) == SUCCESS) {
00829                             if (fptr->common.scope != overwrites->common.scope) {
00830                                    string_printf(str, ", overwrites %s", overwrites->common.scope->name);
00831                             }
00832                      }
00833                      efree(lc_name);
00834               }
00835        }
00836        if (fptr->common.prototype && fptr->common.prototype->common.scope) {
00837               string_printf(str, ", prototype %s", fptr->common.prototype->common.scope->name);
00838        }
00839        if (fptr->common.fn_flags & ZEND_ACC_CTOR) {
00840               string_printf(str, ", ctor");
00841        }
00842        if (fptr->common.fn_flags & ZEND_ACC_DTOR) {
00843               string_printf(str, ", dtor");
00844        }
00845        string_printf(str, "> ");
00846 
00847        if (fptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
00848               string_printf(str, "abstract ");
00849        }
00850        if (fptr->common.fn_flags & ZEND_ACC_FINAL) {
00851               string_printf(str, "final ");
00852        }
00853        if (fptr->common.fn_flags & ZEND_ACC_STATIC) {
00854               string_printf(str, "static ");
00855        }
00856 
00857        if (fptr->common.scope) {
00858               /* These are mutually exclusive */
00859               switch (fptr->common.fn_flags & ZEND_ACC_PPP_MASK) {
00860                      case ZEND_ACC_PUBLIC:
00861                             string_printf(str, "public ");
00862                             break;
00863                      case ZEND_ACC_PRIVATE:
00864                             string_printf(str, "private ");
00865                             break;
00866                      case ZEND_ACC_PROTECTED:
00867                             string_printf(str, "protected ");
00868                             break;
00869                      default:
00870                             string_printf(str, "<visibility error> ");
00871                             break;
00872               }
00873               string_printf(str, "method ");
00874        } else {
00875               string_printf(str, "function ");
00876        }
00877 
00878        if (fptr->op_array.return_reference) {
00879               string_printf(str, "&");
00880        }
00881        string_printf(str, "%s ] {\n", fptr->common.function_name);
00882        /* The information where a function is declared is only available for user classes */
00883        if (fptr->type == ZEND_USER_FUNCTION) {
00884               string_printf(str, "%s  @@ %s %d - %d\n", indent, 
00885                                           fptr->op_array.filename,
00886                                           fptr->op_array.line_start,
00887                                           fptr->op_array.line_end);
00888        }
00889        string_init(&param_indent);
00890        string_printf(&param_indent, "%s  ", indent);
00891        if (fptr->common.fn_flags & ZEND_ACC_CLOSURE) {
00892               _function_closure_string(str, fptr, param_indent.string TSRMLS_CC);
00893        }
00894        _function_parameter_string(str, fptr, param_indent.string TSRMLS_CC);
00895        string_free(&param_indent);
00896        string_printf(str, "%s}\n", indent);
00897 }
00898 /* }}} */
00899 
00900 /* {{{ _property_string */
00901 static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent TSRMLS_DC)
00902 {
00903        char *class_name;
00904 
00905        string_printf(str, "%sProperty [ ", indent);
00906        if (!prop) {
00907               string_printf(str, "<dynamic> public $%s", prop_name);
00908        } else {
00909               if (!(prop->flags & ZEND_ACC_STATIC)) {
00910                      if (prop->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
00911                             string_write(str, "<implicit> ", sizeof("<implicit> ") - 1);
00912                      } else {
00913                             string_write(str, "<default> ", sizeof("<default> ") - 1);
00914                      }
00915               }
00916        
00917               /* These are mutually exclusive */
00918               switch (prop->flags & ZEND_ACC_PPP_MASK) {
00919                      case ZEND_ACC_PUBLIC:
00920                             string_printf(str, "public ");
00921                             break;
00922                      case ZEND_ACC_PRIVATE:
00923                             string_printf(str, "private ");
00924                             break;
00925                      case ZEND_ACC_PROTECTED:
00926                             string_printf(str, "protected ");
00927                             break;
00928               }
00929               if(prop->flags & ZEND_ACC_STATIC) {
00930                      string_printf(str, "static ");
00931               }
00932 
00933               zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
00934               string_printf(str, "$%s", prop_name);
00935        }
00936 
00937        string_printf(str, " ]\n");
00938 }
00939 /* }}} */
00940 
00941 static int _extension_ini_string(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
00942 {
00943        string *str = va_arg(args, string *);
00944        char *indent = va_arg(args, char *);
00945        int number = va_arg(args, int);
00946        char *comma = "";
00947 
00948        if (number == ini_entry->module_number) {
00949               string_printf(str, "    %sEntry [ %s <", indent, ini_entry->name);
00950               if (ini_entry->modifiable == ZEND_INI_ALL) {
00951                      string_printf(str, "ALL");
00952               } else {
00953                      if (ini_entry->modifiable & ZEND_INI_USER) {
00954                             string_printf(str, "USER");
00955                             comma = ",";
00956                      }
00957                      if (ini_entry->modifiable & ZEND_INI_PERDIR) {
00958                             string_printf(str, "%sPERDIR", comma);
00959                             comma = ",";
00960                      }
00961                      if (ini_entry->modifiable & ZEND_INI_SYSTEM) {
00962                             string_printf(str, "%sSYSTEM", comma);
00963                      }
00964               }
00965 
00966               string_printf(str, "> ]\n");
00967               string_printf(str, "    %s  Current = '%s'\n", indent, ini_entry->value ? ini_entry->value : "");
00968               if (ini_entry->modified) {
00969                      string_printf(str, "    %s  Default = '%s'\n", indent, ini_entry->orig_value ? ini_entry->orig_value : "");
00970               }
00971               string_printf(str, "    %s}\n", indent);
00972        }
00973        return ZEND_HASH_APPLY_KEEP;
00974 }
00975 
00976 static int _extension_class_string(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
00977 {
00978        string *str = va_arg(args, string *);
00979        char *indent = va_arg(args, char *);
00980        struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
00981        int *num_classes = va_arg(args, int*);
00982 
00983        if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
00984               string_printf(str, "\n");
00985               _class_string(str, *pce, NULL, indent TSRMLS_CC);
00986               (*num_classes)++;
00987        }
00988        return ZEND_HASH_APPLY_KEEP;
00989 }
00990 
00991 static int _extension_const_string(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
00992 {
00993        string *str = va_arg(args, string *);
00994        char *indent = va_arg(args, char *);
00995        struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
00996        int *num_classes = va_arg(args, int*);
00997 
00998        if (constant->module_number  == module->module_number) {
00999               _const_string(str, constant->name, &constant->value, indent TSRMLS_CC);
01000               (*num_classes)++;
01001        }
01002        return ZEND_HASH_APPLY_KEEP;
01003 }
01004 
01005 /* {{{ _extension_string */
01006 static void _extension_string(string *str, zend_module_entry *module, char *indent TSRMLS_DC)
01007 {
01008        string_printf(str, "%sExtension [ ", indent);
01009        if (module->type == MODULE_PERSISTENT) {
01010               string_printf(str, "<persistent>");
01011        }
01012        if (module->type == MODULE_TEMPORARY) {
01013               string_printf(str, "<temporary>" );
01014        }
01015        string_printf(str, " extension #%d %s version %s ] {\n",
01016                                    module->module_number, module->name,
01017                                    (module->version == NO_VERSION_YET) ? "<no_version>" : module->version);
01018 
01019        if (module->deps) {
01020               const zend_module_dep* dep = module->deps;
01021 
01022               string_printf(str, "\n  - Dependencies {\n");
01023 
01024               while(dep->name) {
01025                      string_printf(str, "%s    Dependency [ %s (", indent, dep->name);
01026                      
01027                      switch(dep->type) {
01028                      case MODULE_DEP_REQUIRED:
01029                             string_write(str, "Required", sizeof("Required") - 1);
01030                             break;
01031                      case MODULE_DEP_CONFLICTS:
01032                             string_write(str, "Conflicts", sizeof("Conflicts") - 1);
01033                             break;
01034                      case MODULE_DEP_OPTIONAL:
01035                             string_write(str, "Optional", sizeof("Optional") - 1);
01036                             break;
01037                      default:
01038                             string_write(str, "Error", sizeof("Error") - 1); /* shouldn't happen */
01039                             break;
01040                      }
01041 
01042                      if (dep->rel) {      
01043                             string_printf(str, " %s", dep->rel);
01044                      }
01045                      if (dep->version) {  
01046                             string_printf(str, " %s", dep->version);
01047                      }
01048                      string_write(str, ") ]\n", sizeof(") ]\n") - 1);
01049                      dep++;
01050               }
01051               string_printf(str, "%s  }\n", indent);
01052        }
01053 
01054        {
01055               string str_ini;
01056               string_init(&str_ini);
01057               zend_hash_apply_with_arguments(EG(ini_directives) TSRMLS_CC, (apply_func_args_t) _extension_ini_string, 3, &str_ini, indent, module->module_number);
01058               if (str_ini.len > 1) {
01059                      string_printf(str, "\n  - INI {\n");
01060                      string_append(str, &str_ini);
01061                      string_printf(str, "%s  }\n", indent);
01062               }
01063               string_free(&str_ini);
01064        }
01065 
01066        {
01067               string str_constants;
01068               int num_constants = 0;
01069               
01070               string_init(&str_constants);
01071               zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _extension_const_string, 4, &str_constants, indent, module, &num_constants);
01072               if (num_constants) {
01073                      string_printf(str, "\n  - Constants [%d] {\n", num_constants);
01074                      string_append(str, &str_constants);
01075                      string_printf(str, "%s  }\n", indent);
01076               }
01077               string_free(&str_constants);
01078        }
01079 
01080        if (module->functions && module->functions->fname) {
01081               zend_function *fptr;
01082               const zend_function_entry *func = module->functions;
01083 
01084               string_printf(str, "\n  - Functions {\n");
01085 
01086               /* Is there a better way of doing this? */
01087               while (func->fname) {
01088                      int fname_len = strlen(func->fname);
01089                      char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
01090                      
01091                      if (zend_hash_find(EG(function_table), lc_name, fname_len+1, (void**) &fptr) == FAILURE) {
01092                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
01093                             func++;
01094                             efree(lc_name);
01095                             continue;
01096                      }
01097                      
01098                      _function_string(str, fptr, NULL, "    " TSRMLS_CC);
01099                      efree(lc_name);
01100                      func++;
01101               }
01102               string_printf(str, "%s  }\n", indent);
01103        }
01104        
01105        {
01106               string str_classes;
01107               string sub_indent;
01108               int num_classes = 0;
01109               
01110               string_init(&sub_indent);
01111               string_printf(&sub_indent, "%s    ", indent);
01112               string_init(&str_classes);
01113               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);
01114               if (num_classes) {
01115                      string_printf(str, "\n  - Classes [%d] {", num_classes);
01116                      string_append(str, &str_classes);
01117                      string_printf(str, "%s  }\n", indent);
01118               }
01119               string_free(&str_classes);
01120               string_free(&sub_indent);
01121        }
01122 
01123        string_printf(str, "%s}\n", indent);
01124 }
01125 /* }}} */
01126 
01127 /* {{{ _function_check_flag */
01128 static void _function_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
01129 {
01130        reflection_object *intern;
01131        zend_function *mptr;
01132 
01133        if (zend_parse_parameters_none() == FAILURE) {
01134               return;
01135        }
01136        GET_REFLECTION_OBJECT_PTR(mptr);
01137        RETURN_BOOL(mptr->common.fn_flags & mask);
01138 }
01139 /* }}} */
01140 
01141 /* {{{ zend_reflection_class_factory */
01142 PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC)
01143 {
01144        reflection_object *intern;
01145        zval *name;
01146 
01147        MAKE_STD_ZVAL(name);
01148        ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
01149        reflection_instantiate(reflection_class_ptr, object TSRMLS_CC);
01150        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01151        intern->ptr = ce;
01152        intern->ref_type = REF_TYPE_OTHER;
01153        intern->ce = ce;
01154        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01155 }
01156 /* }}} */
01157 
01158 /* {{{ reflection_extension_factory */
01159 static void reflection_extension_factory(zval *object, const char *name_str TSRMLS_DC)
01160 {
01161        reflection_object *intern;
01162        zval *name;
01163        int name_len = strlen(name_str);
01164        char *lcname;
01165        struct _zend_module_entry *module;
01166        ALLOCA_FLAG(use_heap)
01167 
01168        lcname = do_alloca(name_len + 1, use_heap);
01169        zend_str_tolower_copy(lcname, name_str, name_len);
01170        if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
01171               free_alloca(lcname, use_heap);
01172               return;
01173        }
01174        free_alloca(lcname, use_heap);
01175 
01176        reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC);
01177        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01178        MAKE_STD_ZVAL(name);
01179        ZVAL_STRINGL(name, module->name, name_len, 1);
01180        intern->ptr = module;
01181        intern->ref_type = REF_TYPE_OTHER;
01182        intern->ce = NULL;
01183        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01184 }
01185 /* }}} */
01186 
01187 /* {{{ reflection_parameter_factory */
01188 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)
01189 {
01190        reflection_object *intern;
01191        parameter_reference *reference;
01192        zval *name;
01193 
01194        if (closure_object) {
01195               Z_ADDREF_P(closure_object);
01196        }
01197        MAKE_STD_ZVAL(name);
01198        if (arg_info->name) {
01199               ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
01200        } else {
01201               ZVAL_NULL(name);
01202        }
01203        reflection_instantiate(reflection_parameter_ptr, object TSRMLS_CC);
01204        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01205        reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
01206        reference->arg_info = arg_info;
01207        reference->offset = offset;
01208        reference->required = required;
01209        reference->fptr = fptr;
01210        intern->ptr = reference;
01211        intern->ref_type = REF_TYPE_PARAMETER;
01212        intern->ce = fptr->common.scope;
01213        intern->obj = closure_object;
01214        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01215 }
01216 /* }}} */
01217 
01218 /* {{{ reflection_function_factory */
01219 static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object TSRMLS_DC)
01220 {
01221        reflection_object *intern;
01222        zval *name;
01223 
01224        if (closure_object) {
01225               Z_ADDREF_P(closure_object);
01226        }
01227        MAKE_STD_ZVAL(name);
01228        ZVAL_STRING(name, function->common.function_name, 1);
01229 
01230        reflection_instantiate(reflection_function_ptr, object TSRMLS_CC);
01231        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01232        intern->ptr = function;
01233        intern->ref_type = REF_TYPE_FUNCTION;
01234        intern->ce = NULL;
01235        intern->obj = closure_object;
01236        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01237 }
01238 /* }}} */
01239 
01240 /* {{{ reflection_method_factory */
01241 static void reflection_method_factory(zend_class_entry *ce, zend_function *method, zval *closure_object, zval *object TSRMLS_DC)
01242 {
01243        reflection_object *intern;
01244        zval *name;
01245        zval *classname;
01246 
01247        if (closure_object) {
01248               Z_ADDREF_P(closure_object);
01249        }
01250        MAKE_STD_ZVAL(name);
01251        MAKE_STD_ZVAL(classname);
01252        ZVAL_STRING(name, method->common.function_name, 1);
01253        ZVAL_STRINGL(classname, method->common.scope->name, method->common.scope->name_length, 1);
01254        reflection_instantiate(reflection_method_ptr, object TSRMLS_CC);
01255        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01256        intern->ptr = method;
01257        intern->ref_type = REF_TYPE_FUNCTION;
01258        intern->ce = ce;
01259        intern->obj = closure_object;
01260        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01261        zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
01262 }
01263 /* }}} */
01264 
01265 /* {{{ reflection_property_factory */
01266 static void reflection_property_factory(zend_class_entry *ce, zend_property_info *prop, zval *object TSRMLS_DC)
01267 {
01268        reflection_object *intern;
01269        zval *name;
01270        zval *classname;
01271        property_reference *reference;
01272        char *class_name, *prop_name;
01273 
01274        zend_unmangle_property_name(prop->name, prop->name_length, &class_name, &prop_name);
01275 
01276        if (!(prop->flags & ZEND_ACC_PRIVATE)) {
01277               /* we have to search the class hierarchy for this (implicit) public or protected property */
01278               zend_class_entry *tmp_ce = ce, *store_ce = ce;
01279               zend_property_info *tmp_info = NULL;
01280 
01281               while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, strlen(prop_name) + 1, (void **) &tmp_info) != SUCCESS) {
01282                      ce = tmp_ce;
01283                      tmp_ce = tmp_ce->parent;
01284               }
01285 
01286               if (tmp_info && !(tmp_info->flags & ZEND_ACC_SHADOW)) { /* found something and it's not a parent's private */
01287                      prop = tmp_info;
01288               } else { /* not found, use initial value */
01289                      ce = store_ce;
01290               }
01291        }
01292 
01293        MAKE_STD_ZVAL(name);
01294        MAKE_STD_ZVAL(classname);
01295        ZVAL_STRING(name, prop_name, 1);
01296        ZVAL_STRINGL(classname, prop->ce->name, prop->ce->name_length, 1);
01297 
01298        reflection_instantiate(reflection_property_ptr, object TSRMLS_CC);
01299        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01300        reference = (property_reference*) emalloc(sizeof(property_reference));
01301        reference->ce = ce;
01302        reference->prop = *prop;
01303        intern->ptr = reference;
01304        intern->ref_type = REF_TYPE_PROPERTY;
01305        intern->ce = ce;
01306        intern->ignore_visibility = 0;
01307        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01308        zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
01309 }
01310 /* }}} */
01311 
01312 /* {{{ _reflection_export */
01313 static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
01314 {
01315        zval *reflector_ptr;
01316        zval output, *output_ptr = &output;
01317        zval *argument_ptr, *argument2_ptr;
01318        zval *retval_ptr, **params[2];
01319        int result;
01320        int return_output = 0;
01321        zend_fcall_info fci;
01322        zend_fcall_info_cache fcc;
01323        zval fname;
01324 
01325        if (ctor_argc == 1) {
01326               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &argument_ptr, &return_output) == FAILURE) {
01327                      return;
01328               }
01329        } else {
01330               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &argument_ptr, &argument2_ptr, &return_output) == FAILURE) {
01331                      return;
01332               }
01333        }
01334 
01335        INIT_PZVAL(&output);
01336 
01337        /* Create object */
01338        MAKE_STD_ZVAL(reflector_ptr);
01339        if (object_and_properties_init(reflector_ptr, ce_ptr, NULL) == FAILURE) {
01340               _DO_THROW("Could not create reflector");
01341        }
01342 
01343        /* Call __construct() */
01344        params[0] = &argument_ptr;
01345        params[1] = &argument2_ptr;
01346 
01347        fci.size = sizeof(fci);
01348        fci.function_table = NULL;
01349        fci.function_name = NULL;
01350        fci.symbol_table = NULL;
01351        fci.object_ptr = reflector_ptr;
01352        fci.retval_ptr_ptr = &retval_ptr;
01353        fci.param_count = ctor_argc;
01354        fci.params = params;
01355        fci.no_separation = 1;
01356 
01357        fcc.initialized = 1;
01358        fcc.function_handler = ce_ptr->constructor;
01359        fcc.calling_scope = ce_ptr;
01360        fcc.called_scope = Z_OBJCE_P(reflector_ptr);
01361        fcc.object_ptr = reflector_ptr;
01362 
01363        result = zend_call_function(&fci, &fcc TSRMLS_CC);
01364        
01365        if (retval_ptr) {
01366               zval_ptr_dtor(&retval_ptr);
01367        }
01368 
01369        if (EG(exception)) {
01370               zval_ptr_dtor(&reflector_ptr);
01371               return;
01372        }
01373        if (result == FAILURE) {
01374               zval_ptr_dtor(&reflector_ptr);
01375               _DO_THROW("Could not create reflector");
01376        }
01377 
01378        /* Call static reflection::export */
01379        ZVAL_BOOL(&output, return_output);
01380        params[0] = &reflector_ptr;
01381        params[1] = &output_ptr;
01382 
01383        ZVAL_STRINGL(&fname, "reflection::export", sizeof("reflection::export") - 1, 0);
01384        fci.function_table = &reflection_ptr->function_table;
01385        fci.function_name = &fname;
01386        fci.object_ptr = NULL;
01387        fci.retval_ptr_ptr = &retval_ptr;
01388        fci.param_count = 2;
01389        fci.params = params;
01390        fci.no_separation = 1;
01391 
01392        result = zend_call_function(&fci, NULL TSRMLS_CC);
01393 
01394        if (result == FAILURE && EG(exception) == NULL) {
01395               zval_ptr_dtor(&reflector_ptr);
01396               zval_ptr_dtor(&retval_ptr);
01397               _DO_THROW("Could not execute reflection::export()");
01398        }
01399 
01400        if (return_output) {
01401               COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
01402        } else {
01403               zval_ptr_dtor(&retval_ptr);
01404        }
01405 
01406        /* Destruct reflector which is no longer needed */
01407        zval_ptr_dtor(&reflector_ptr);
01408 }
01409 /* }}} */
01410 
01411 /* {{{ Preventing __clone from being called */
01412 ZEND_METHOD(reflection, __clone)
01413 {
01414        /* Should never be executable */
01415        _DO_THROW("Cannot clone object using __clone()");
01416 }
01417 /* }}} */
01418 
01419 /* {{{ proto public static mixed Reflection::export(Reflector r [, bool return])
01420    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
01421 ZEND_METHOD(reflection, export)
01422 {
01423        zval *object, fname, *retval_ptr;
01424        int result;
01425        zend_bool return_output = 0;
01426 
01427        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &object, reflector_ptr, &return_output) == FAILURE) {
01428               return;
01429        }
01430 
01431        /* Invoke the __toString() method */
01432        ZVAL_STRINGL(&fname, "__tostring", sizeof("__tostring") - 1, 1);
01433        result= call_user_function_ex(NULL, &object, &fname, &retval_ptr, 0, NULL, 0, NULL TSRMLS_CC);
01434        zval_dtor(&fname);
01435 
01436        if (result == FAILURE) {
01437               _DO_THROW("Invocation of method __toString() failed");
01438               /* Returns from this function */
01439        }
01440 
01441        if (!retval_ptr) {
01442               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name);
01443               RETURN_FALSE;
01444        }
01445 
01446        if (return_output) {
01447               COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
01448        } else {
01449               /* No need for _r variant, return of __toString should always be a string */
01450               zend_print_zval(retval_ptr, 0);
01451               zend_printf("\n");
01452               zval_ptr_dtor(&retval_ptr);
01453        }
01454 }
01455 /* }}} */
01456 
01457 /* {{{ proto public static array Reflection::getModifierNames(int modifiers)
01458    Returns an array of modifier names */
01459 ZEND_METHOD(reflection, getModifierNames)
01460 {
01461        long modifiers;
01462 
01463        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &modifiers) == FAILURE) {
01464               return;
01465        }
01466 
01467        array_init(return_value);
01468 
01469        if (modifiers & (ZEND_ACC_ABSTRACT | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
01470               add_next_index_stringl(return_value, "abstract", sizeof("abstract")-1, 1);
01471        }
01472        if (modifiers & (ZEND_ACC_FINAL | ZEND_ACC_FINAL_CLASS)) {
01473               add_next_index_stringl(return_value, "final", sizeof("final")-1, 1);
01474        }
01475        if (modifiers & ZEND_ACC_IMPLICIT_PUBLIC) {
01476               add_next_index_stringl(return_value, "public", sizeof("public")-1, 1);
01477        }
01478 
01479        /* These are mutually exclusive */
01480        switch (modifiers & ZEND_ACC_PPP_MASK) {
01481               case ZEND_ACC_PUBLIC:
01482                      add_next_index_stringl(return_value, "public", sizeof("public")-1, 1);
01483                      break;
01484               case ZEND_ACC_PRIVATE:
01485                      add_next_index_stringl(return_value, "private", sizeof("private")-1, 1);
01486                      break;
01487               case ZEND_ACC_PROTECTED:
01488                      add_next_index_stringl(return_value, "protected", sizeof("protected")-1, 1);
01489                      break;
01490        }
01491 
01492        if (modifiers & ZEND_ACC_STATIC) {
01493               add_next_index_stringl(return_value, "static", sizeof("static")-1, 1);
01494        }
01495 }
01496 /* }}} */
01497 
01498 /* {{{ proto public static mixed ReflectionFunction::export(string name [, bool return])
01499    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
01500 ZEND_METHOD(reflection_function, export)
01501 {
01502        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_function_ptr, 1);
01503 }
01504 /* }}} */
01505 
01506 /* {{{ proto public void ReflectionFunction::__construct(string name)
01507    Constructor. Throws an Exception in case the given function does not exist */
01508 ZEND_METHOD(reflection_function, __construct)
01509 {
01510        zval *name;
01511        zval *object;
01512        zval *closure = NULL;
01513        char *lcname;
01514        reflection_object *intern;
01515        zend_function *fptr;
01516        char *name_str;
01517        int name_len;
01518 
01519        object = getThis();
01520        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
01521        if (intern == NULL) {
01522               return;
01523        }
01524 
01525        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "O", &closure, zend_ce_closure) == SUCCESS) {
01526               fptr = (zend_function*)zend_get_closure_method_def(closure TSRMLS_CC);
01527               Z_ADDREF_P(closure);
01528        } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == SUCCESS) {
01529               char *nsname;
01530 
01531               lcname = zend_str_tolower_dup(name_str, name_len);
01532 
01533               /* Ignore leading "\" */
01534               nsname = lcname;
01535               if (lcname[0] == '\\') {
01536                      nsname = &lcname[1];
01537                      name_len--;
01538               }
01539               
01540               if (zend_hash_find(EG(function_table), nsname, name_len + 1, (void **)&fptr) == FAILURE) {
01541                      efree(lcname);
01542                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
01543                             "Function %s() does not exist", name_str);
01544                      return;
01545               }
01546               efree(lcname);
01547        } else {
01548               return;
01549        }
01550 
01551        MAKE_STD_ZVAL(name);
01552        ZVAL_STRING(name, fptr->common.function_name, 1);
01553        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
01554        intern->ptr = fptr;
01555        intern->ref_type = REF_TYPE_FUNCTION;
01556        intern->obj = closure;
01557        intern->ce = NULL;
01558 }
01559 /* }}} */
01560 
01561 /* {{{ proto public string ReflectionFunction::__toString()
01562    Returns a string representation */
01563 ZEND_METHOD(reflection_function, __toString)
01564 {
01565        reflection_object *intern;
01566        zend_function *fptr;
01567        string str;
01568 
01569        if (zend_parse_parameters_none() == FAILURE) {
01570               return;
01571        }
01572        GET_REFLECTION_OBJECT_PTR(fptr);
01573        string_init(&str);
01574        _function_string(&str, fptr, intern->ce, "" TSRMLS_CC);
01575        RETURN_STRINGL(str.string, str.len - 1, 0);
01576 }
01577 /* }}} */
01578 
01579 /* {{{ proto public string ReflectionFunction::getName()
01580    Returns this function's name */
01581 ZEND_METHOD(reflection_function, getName)
01582 {
01583        if (zend_parse_parameters_none() == FAILURE) {
01584               return;
01585        }
01586        _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
01587 }
01588 /* }}} */
01589 
01590 /* {{{ proto public bool ReflectionFunction::isClosure()
01591    Returns whether this is a closure */
01592 ZEND_METHOD(reflection_function, isClosure)
01593 {
01594        reflection_object *intern;
01595        zend_function *fptr;
01596 
01597        if (zend_parse_parameters_none() == FAILURE) {
01598               return;
01599        }
01600        GET_REFLECTION_OBJECT_PTR(fptr);
01601        RETURN_BOOL(fptr->common.fn_flags & ZEND_ACC_CLOSURE);
01602 }
01603 /* }}} */
01604 
01605 /* {{{ proto public bool ReflectionFunction::isInternal()
01606    Returns whether this is an internal function */
01607 ZEND_METHOD(reflection_function, isInternal)
01608 {
01609        reflection_object *intern;
01610        zend_function *fptr;
01611 
01612        if (zend_parse_parameters_none() == FAILURE) {
01613               return;
01614        }
01615        GET_REFLECTION_OBJECT_PTR(fptr);
01616        RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION);
01617 }
01618 /* }}} */
01619 
01620 /* {{{ proto public bool ReflectionFunction::isUserDefined()
01621    Returns whether this is an user-defined function */
01622 ZEND_METHOD(reflection_function, isUserDefined)
01623 {
01624        reflection_object *intern;
01625        zend_function *fptr;
01626 
01627        if (zend_parse_parameters_none() == FAILURE) {
01628               return;
01629        }
01630        GET_REFLECTION_OBJECT_PTR(fptr);
01631        RETURN_BOOL(fptr->type == ZEND_USER_FUNCTION);
01632 }
01633 /* }}} */
01634 
01635 /* {{{ proto public bool ReflectionFunction::isDisabled()
01636    Returns whether this function has been disabled or not */
01637 ZEND_METHOD(reflection_function, isDisabled)
01638 {
01639        reflection_object *intern;
01640        zend_function *fptr;
01641 
01642        METHOD_NOTSTATIC(reflection_function_ptr);
01643        GET_REFLECTION_OBJECT_PTR(fptr);
01644        RETURN_BOOL(fptr->type == ZEND_INTERNAL_FUNCTION && fptr->internal_function.handler == zif_display_disabled_function);
01645 }
01646 /* }}} */
01647 
01648 /* {{{ proto public string ReflectionFunction::getFileName()
01649    Returns the filename of the file this function was declared in */
01650 ZEND_METHOD(reflection_function, getFileName)
01651 {
01652        reflection_object *intern;
01653        zend_function *fptr;
01654 
01655        if (zend_parse_parameters_none() == FAILURE) {
01656               return;
01657        }
01658        GET_REFLECTION_OBJECT_PTR(fptr);
01659        if (fptr->type == ZEND_USER_FUNCTION) {
01660               RETURN_STRING(fptr->op_array.filename, 1);
01661        }
01662        RETURN_FALSE;
01663 }
01664 /* }}} */
01665 
01666 /* {{{ proto public int ReflectionFunction::getStartLine()
01667    Returns the line this function's declaration starts at */
01668 ZEND_METHOD(reflection_function, getStartLine)
01669 {
01670        reflection_object *intern;
01671        zend_function *fptr;
01672 
01673        if (zend_parse_parameters_none() == FAILURE) {
01674               return;
01675        }
01676        GET_REFLECTION_OBJECT_PTR(fptr);
01677        if (fptr->type == ZEND_USER_FUNCTION) {
01678               RETURN_LONG(fptr->op_array.line_start);
01679        }
01680        RETURN_FALSE;
01681 }
01682 /* }}} */
01683 
01684 /* {{{ proto public int ReflectionFunction::getEndLine()
01685    Returns the line this function's declaration ends at */
01686 ZEND_METHOD(reflection_function, getEndLine)
01687 {
01688        reflection_object *intern;
01689        zend_function *fptr;
01690 
01691        if (zend_parse_parameters_none() == FAILURE) {
01692               return;
01693        }
01694        GET_REFLECTION_OBJECT_PTR(fptr);
01695        if (fptr->type == ZEND_USER_FUNCTION) {
01696               RETURN_LONG(fptr->op_array.line_end);
01697        }
01698        RETURN_FALSE;
01699 }
01700 /* }}} */
01701 
01702 /* {{{ proto public string ReflectionFunction::getDocComment()
01703    Returns the doc comment for this function */
01704 ZEND_METHOD(reflection_function, getDocComment)
01705 {
01706        reflection_object *intern;
01707        zend_function *fptr;
01708 
01709        if (zend_parse_parameters_none() == FAILURE) {
01710               return;
01711        }
01712        GET_REFLECTION_OBJECT_PTR(fptr);
01713        if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.doc_comment) {
01714               RETURN_STRINGL(fptr->op_array.doc_comment, fptr->op_array.doc_comment_len, 1);
01715        }
01716        RETURN_FALSE;
01717 }
01718 /* }}} */
01719 
01720 /* {{{ proto public array ReflectionFunction::getStaticVariables()
01721    Returns an associative array containing this function's static variables and their values */
01722 ZEND_METHOD(reflection_function, getStaticVariables)
01723 {
01724        zval *tmp_copy;
01725        reflection_object *intern;
01726        zend_function *fptr;
01727        
01728        if (zend_parse_parameters_none() == FAILURE) {
01729               return;
01730        }
01731        GET_REFLECTION_OBJECT_PTR(fptr);
01732 
01733        /* Return an empty array in case no static variables exist */
01734        array_init(return_value);
01735        if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.static_variables != NULL) {
01736               zend_hash_apply_with_argument(fptr->op_array.static_variables, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
01737               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 *));
01738        }
01739 }
01740 /* }}} */
01741 
01742 /* {{{ proto public mixed ReflectionFunction::invoke([mixed* args])
01743    Invokes the function */
01744 ZEND_METHOD(reflection_function, invoke)
01745 {
01746        zval *retval_ptr;
01747        zval ***params = NULL;
01748        int result, num_args = 0;
01749        zend_fcall_info fci;
01750        zend_fcall_info_cache fcc;
01751        reflection_object *intern;
01752        zend_function *fptr;
01753        
01754        METHOD_NOTSTATIC(reflection_function_ptr);
01755        GET_REFLECTION_OBJECT_PTR(fptr);
01756 
01757        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &params, &num_args) == FAILURE) {
01758               return;
01759        }
01760 
01761        fci.size = sizeof(fci);
01762        fci.function_table = NULL;
01763        fci.function_name = NULL;
01764        fci.symbol_table = NULL;
01765        fci.object_ptr = NULL;
01766        fci.retval_ptr_ptr = &retval_ptr;
01767        fci.param_count = num_args;
01768        fci.params = params;
01769        fci.no_separation = 1;
01770 
01771        fcc.initialized = 1;
01772        fcc.function_handler = fptr;
01773        fcc.calling_scope = EG(scope);
01774        fcc.called_scope = NULL;
01775        fcc.object_ptr = NULL;
01776 
01777        result = zend_call_function(&fci, &fcc TSRMLS_CC);
01778 
01779        if (num_args) {
01780               efree(params);
01781        }
01782 
01783        if (result == FAILURE) {
01784               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
01785                      "Invocation of function %s() failed", fptr->common.function_name);
01786               return;
01787        }
01788 
01789        if (retval_ptr) {
01790               COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
01791        }
01792 }
01793 /* }}} */
01794 
01795 static int _zval_array_to_c_array(zval **arg, zval ****params TSRMLS_DC) /* {{{ */
01796 {
01797        *(*params)++ = arg;
01798        return ZEND_HASH_APPLY_KEEP;
01799 } /* }}} */
01800 
01801 /* {{{ proto public mixed ReflectionFunction::invokeArgs(array args)
01802    Invokes the function and pass its arguments as array. */
01803 ZEND_METHOD(reflection_function, invokeArgs)
01804 {
01805        zval *retval_ptr;
01806        zval ***params;
01807        int result;
01808        int argc;
01809        zend_fcall_info fci;
01810        zend_fcall_info_cache fcc;
01811        reflection_object *intern;
01812        zend_function *fptr;
01813        zval *param_array;
01814        
01815        METHOD_NOTSTATIC(reflection_function_ptr);
01816        GET_REFLECTION_OBJECT_PTR(fptr);
01817 
01818        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &param_array) == FAILURE) {
01819               return;
01820        }
01821 
01822        argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
01823        
01824        params = safe_emalloc(sizeof(zval **), argc, 0);
01825        zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);   
01826        params -= argc;
01827 
01828        fci.size = sizeof(fci);
01829        fci.function_table = NULL;
01830        fci.function_name = NULL;
01831        fci.symbol_table = NULL;
01832        fci.object_ptr = NULL;
01833        fci.retval_ptr_ptr = &retval_ptr;
01834        fci.param_count = argc;
01835        fci.params = params;
01836        fci.no_separation = 1;
01837 
01838        fcc.initialized = 1;
01839        fcc.function_handler = fptr;
01840        fcc.calling_scope = EG(scope);
01841        fcc.called_scope = NULL;
01842        fcc.object_ptr = NULL;
01843 
01844        result = zend_call_function(&fci, &fcc TSRMLS_CC);
01845 
01846        efree(params);
01847 
01848        if (result == FAILURE) {
01849               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
01850                      "Invocation of function %s() failed", fptr->common.function_name);
01851               return;
01852        }
01853 
01854        if (retval_ptr) {
01855               COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
01856        }
01857 }
01858 /* }}} */
01859 
01860 /* {{{ proto public bool ReflectionFunction::returnsReference()
01861    Gets whether this function returns a reference */
01862 ZEND_METHOD(reflection_function, returnsReference)
01863 {
01864        reflection_object *intern;
01865        zend_function *fptr;
01866 
01867        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
01868        GET_REFLECTION_OBJECT_PTR(fptr);
01869 
01870        RETURN_BOOL(fptr->op_array.return_reference);
01871 }
01872 /* }}} */
01873 
01874 /* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
01875    Gets the number of required parameters */
01876 ZEND_METHOD(reflection_function, getNumberOfParameters)
01877 {
01878        reflection_object *intern;
01879        zend_function *fptr;
01880 
01881        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
01882        GET_REFLECTION_OBJECT_PTR(fptr);
01883 
01884        RETURN_LONG(fptr->common.num_args);
01885 }
01886 /* }}} */
01887 
01888 /* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
01889    Gets the number of required parameters */
01890 ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
01891 {
01892        reflection_object *intern;
01893        zend_function *fptr;
01894 
01895        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
01896        GET_REFLECTION_OBJECT_PTR(fptr);
01897 
01898        RETURN_LONG(fptr->common.required_num_args);
01899 }
01900 /* }}} */
01901 
01902 /* {{{ proto public ReflectionParameter[] ReflectionFunction::getParameters()
01903    Returns an array of parameter objects for this function */
01904 ZEND_METHOD(reflection_function, getParameters)
01905 {
01906        reflection_object *intern;
01907        zend_function *fptr;
01908        zend_uint i;
01909        struct _zend_arg_info *arg_info;
01910 
01911        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
01912        GET_REFLECTION_OBJECT_PTR(fptr);
01913 
01914        arg_info= fptr->common.arg_info;
01915 
01916        array_init(return_value);
01917        for (i = 0; i < fptr->common.num_args; i++) {
01918               zval *parameter;   
01919 
01920               ALLOC_ZVAL(parameter);
01921               reflection_parameter_factory(_copy_function(fptr TSRMLS_CC), intern->obj, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
01922               add_next_index_zval(return_value, parameter);
01923 
01924               arg_info++;
01925        }
01926 }
01927 /* }}} */
01928 
01929 /* {{{ proto public ReflectionExtension|NULL ReflectionFunction::getExtension()
01930    Returns NULL or the extension the function belongs to */
01931 ZEND_METHOD(reflection_function, getExtension)
01932 {
01933        reflection_object *intern;
01934        zend_function *fptr;
01935        zend_internal_function *internal;
01936 
01937        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
01938        GET_REFLECTION_OBJECT_PTR(fptr);
01939 
01940        if (fptr->type != ZEND_INTERNAL_FUNCTION) {
01941               RETURN_NULL();
01942        }
01943 
01944        internal = (zend_internal_function *)fptr;
01945        if (internal->module) {
01946               reflection_extension_factory(return_value, internal->module->name TSRMLS_CC);
01947        } else {
01948               RETURN_NULL();
01949        }
01950 }
01951 /* }}} */
01952 
01953 /* {{{ proto public string|false ReflectionFunction::getExtensionName()
01954    Returns false or the name of the extension the function belongs to */
01955 ZEND_METHOD(reflection_function, getExtensionName)
01956 {
01957        reflection_object *intern;
01958        zend_function *fptr;
01959        zend_internal_function *internal;
01960 
01961        METHOD_NOTSTATIC(reflection_function_abstract_ptr);
01962        GET_REFLECTION_OBJECT_PTR(fptr);
01963 
01964        if (fptr->type != ZEND_INTERNAL_FUNCTION) {
01965               RETURN_FALSE;
01966        }
01967 
01968        internal = (zend_internal_function *)fptr;
01969        if (internal->module) {
01970               RETURN_STRING(internal->module->name, 1);
01971        } else {
01972               RETURN_FALSE;
01973        }
01974 }
01975 /* }}} */
01976 
01977 /* {{{ proto public static mixed ReflectionParameter::export(mixed function, mixed parameter [, bool return]) throws ReflectionException
01978    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
01979 ZEND_METHOD(reflection_parameter, export)
01980 {
01981        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_parameter_ptr, 2);
01982 }
01983 /* }}} */
01984 
01985 /* {{{ proto public void ReflectionParameter::__construct(mixed function, mixed parameter)
01986    Constructor. Throws an Exception in case the given method does not exist */
01987 ZEND_METHOD(reflection_parameter, __construct)
01988 {
01989        parameter_reference *ref;
01990        zval *reference, **parameter;
01991        zval *object;
01992        zval *name;
01993        reflection_object *intern;
01994        zend_function *fptr;
01995        struct _zend_arg_info *arg_info;
01996        int position;
01997        zend_class_entry *ce = NULL;
01998        zend_bool is_closure = 0;
01999 
02000        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zZ", &reference, &parameter) == FAILURE) {
02001               return;
02002        }
02003 
02004        object = getThis();
02005        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
02006        if (intern == NULL) {
02007               return;
02008        }
02009        
02010        /* First, find the function */
02011        switch (Z_TYPE_P(reference)) {
02012               case IS_STRING: {
02013                             unsigned int lcname_len;
02014                             char *lcname;
02015 
02016                             lcname_len = Z_STRLEN_P(reference);
02017                             lcname = zend_str_tolower_dup(Z_STRVAL_P(reference), lcname_len);
02018                             if (zend_hash_find(EG(function_table), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
02019                                    efree(lcname);
02020                                    zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02021                                           "Function %s() does not exist", Z_STRVAL_P(reference));
02022                                    return;
02023                             }
02024                             efree(lcname);
02025                      }
02026                      ce = fptr->common.scope;
02027                      break;
02028 
02029               case IS_ARRAY: {
02030                             zval **classref;
02031                             zval **method;
02032                             zend_class_entry **pce;
02033                             unsigned int lcname_len;
02034                             char *lcname;
02035                             
02036                             if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
02037                                    || (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE))
02038                             {
02039                                    _DO_THROW("Expected array($object, $method) or array($classname, $method)");
02040                                    /* returns out of this function */
02041                             }
02042 
02043                             if (Z_TYPE_PP(classref) == IS_OBJECT) {
02044                                    ce = Z_OBJCE_PP(classref);
02045                             } else {
02046                                    convert_to_string_ex(classref);
02047                                    if (zend_lookup_class(Z_STRVAL_PP(classref), Z_STRLEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
02048                                           zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
02049                                                         "Class %s does not exist", Z_STRVAL_PP(classref));
02050                                           return;
02051                                    }
02052                                    ce = *pce;
02053                             }
02054                             
02055                             convert_to_string_ex(method);
02056                             lcname_len = Z_STRLEN_PP(method);
02057                             lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), lcname_len);
02058                             if (ce == zend_ce_closure && Z_TYPE_PP(classref) == IS_OBJECT
02059                                    && (lcname_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
02060                                    && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
02061                                    && (fptr = zend_get_closure_invoke_method(*classref TSRMLS_CC)) != NULL)
02062                             {
02063                                    /* nothign to do. don't set is_closure since is the invoke handler,
02064                                       not the closure itself */
02065                             } else if (zend_hash_find(&ce->function_table, lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
02066                                    efree(lcname);
02067                                    zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02068                                           "Method %s::%s() does not exist", ce->name, Z_STRVAL_PP(method));
02069                                    return;
02070                             }
02071                             efree(lcname);
02072                      }
02073                      break;
02074               
02075               case IS_OBJECT: {
02076                             ce = Z_OBJCE_P(reference);
02077                             
02078                             if (instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
02079                                    fptr = (zend_function *)zend_get_closure_method_def(reference TSRMLS_CC);
02080                                    Z_ADDREF_P(reference);
02081                                    is_closure = 1;
02082                             } else if (zend_hash_find(&ce->function_table, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME), (void **)&fptr) == FAILURE) {
02083                                    zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
02084                                           "Method %s::%s() does not exist", ce->name, ZEND_INVOKE_FUNC_NAME);
02085                                    return;
02086                             }
02087                      }
02088                      break;
02089                      
02090               default:
02091                      _DO_THROW("The parameter class is expected to be either a string, an array(class, method) or a callable object");
02092                      /* returns out of this function */
02093        }
02094        
02095        /* Now, search for the parameter */
02096        arg_info = fptr->common.arg_info;
02097        if (Z_TYPE_PP(parameter) == IS_LONG) {
02098               position= Z_LVAL_PP(parameter);
02099               if (position < 0 || (zend_uint)position >= fptr->common.num_args) {
02100                      if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
02101                             if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
02102                                    efree(fptr->common.function_name);
02103                             }
02104                             efree(fptr);
02105                      }
02106                      if (is_closure) {
02107                             zval_ptr_dtor(&reference);
02108                      }
02109                      _DO_THROW("The parameter specified by its offset could not be found");
02110                      /* returns out of this function */
02111               }
02112        } else {
02113               zend_uint i;
02114 
02115               position= -1;
02116               convert_to_string_ex(parameter);
02117               for (i = 0; i < fptr->common.num_args; i++) {
02118                      if (arg_info[i].name && strcmp(arg_info[i].name, Z_STRVAL_PP(parameter)) == 0) {
02119                             position= i;
02120                             break;
02121                      }
02122               }
02123               if (position == -1) {
02124                      if (fptr->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) {
02125                             if (fptr->type != ZEND_OVERLOADED_FUNCTION) {
02126                                    efree(fptr->common.function_name);
02127                             }
02128                             efree(fptr);
02129                      }
02130                      if (is_closure) {
02131                             zval_ptr_dtor(&reference);
02132                      }
02133                      _DO_THROW("The parameter specified by its name could not be found");
02134                      /* returns out of this function */
02135               }
02136        }
02137        
02138        MAKE_STD_ZVAL(name);
02139        if (arg_info[position].name) {
02140               ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
02141        } else {
02142               ZVAL_NULL(name);
02143        }
02144        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
02145 
02146        ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
02147        ref->arg_info = &arg_info[position];
02148        ref->offset = (zend_uint)position;
02149        ref->required = fptr->common.required_num_args;
02150        ref->fptr = fptr;
02151        /* TODO: copy fptr */
02152        intern->ptr = ref;
02153        intern->ref_type = REF_TYPE_PARAMETER;
02154        intern->ce = ce;
02155        if (reference && is_closure) {
02156               intern->obj = reference;
02157        }
02158 }
02159 /* }}} */
02160 
02161 /* {{{ proto public string ReflectionParameter::__toString()
02162    Returns a string representation */
02163 ZEND_METHOD(reflection_parameter, __toString)
02164 {
02165        reflection_object *intern;
02166        parameter_reference *param;
02167        string str;
02168 
02169        if (zend_parse_parameters_none() == FAILURE) {
02170               return;
02171        }
02172        GET_REFLECTION_OBJECT_PTR(param);
02173        string_init(&str);
02174        _parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC);
02175        RETURN_STRINGL(str.string, str.len - 1, 0);
02176 }
02177 /* }}} */
02178 
02179 /* {{{ proto public string ReflectionParameter::getName()
02180    Returns this parameters's name */
02181 ZEND_METHOD(reflection_parameter, getName)
02182 {
02183        if (zend_parse_parameters_none() == FAILURE) {
02184               return;
02185        }
02186        _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
02187 }
02188 /* }}} */
02189 
02190 /* {{{ proto public ReflectionFunction ReflectionParameter::getDeclaringFunction()
02191    Returns the ReflectionFunction for the function of this parameter */
02192 ZEND_METHOD(reflection_parameter, getDeclaringFunction)
02193 {
02194        reflection_object *intern;
02195        parameter_reference *param;
02196 
02197        if (zend_parse_parameters_none() == FAILURE) {
02198               return;
02199        }
02200        GET_REFLECTION_OBJECT_PTR(param);
02201 
02202        if (!param->fptr->common.scope) {
02203               reflection_function_factory(_copy_function(param->fptr TSRMLS_CC), intern->obj, return_value TSRMLS_CC);
02204        } else {
02205               reflection_method_factory(param->fptr->common.scope, _copy_function(param->fptr TSRMLS_CC), intern->obj, return_value TSRMLS_CC);
02206        }
02207 }
02208 /* }}} */
02209 
02210 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
02211    Returns in which class this parameter is defined (not the typehint of the parameter) */
02212 ZEND_METHOD(reflection_parameter, getDeclaringClass)
02213 {
02214        reflection_object *intern;
02215        parameter_reference *param;
02216 
02217        if (zend_parse_parameters_none() == FAILURE) {
02218               return;
02219        }
02220        GET_REFLECTION_OBJECT_PTR(param);
02221 
02222        if (param->fptr->common.scope) {
02223               zend_reflection_class_factory(param->fptr->common.scope, return_value TSRMLS_CC);
02224        }      
02225 }
02226 /* }}} */
02227 
02228 /* {{{ proto public ReflectionClass|NULL ReflectionParameter::getClass()
02229    Returns this parameters's class hint or NULL if there is none */
02230 ZEND_METHOD(reflection_parameter, getClass)
02231 {
02232        reflection_object *intern;
02233        parameter_reference *param;
02234        zend_class_entry **pce, *ce;
02235 
02236        if (zend_parse_parameters_none() == FAILURE) {
02237               return;
02238        }
02239        GET_REFLECTION_OBJECT_PTR(param);
02240 
02241        if (param->arg_info->class_name) {
02242               /* Class name is stored as a string, we might also get "self" or "parent"
02243                * - For "self", simply use the function scope. If scope is NULL then
02244                *   the function is global and thus self does not make any sense
02245                *
02246                * - For "parent", use the function scope's parent. If scope is NULL then
02247                *   the function is global and thus parent does not make any sense.
02248                *   If the parent is NULL then the class does not extend anything and
02249                *   thus parent does not make any sense, either.
02250                *
02251                * TODO: Think about moving these checks to the compiler or some sort of
02252                * lint-mode.
02253                */
02254               if (0 == strncmp(param->arg_info->class_name, "self", sizeof("self")- 1)) {
02255                      ce = param->fptr->common.scope;
02256                      if (!ce) {
02257                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02258                                    "Parameter uses 'self' as type hint but function is not a class member!");
02259                             return;
02260                      }
02261                      pce= &ce;
02262               } else if (0 == strncmp(param->arg_info->class_name, "parent", sizeof("parent")- 1)) {
02263                      ce = param->fptr->common.scope;
02264                      if (!ce) {
02265                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02266                                    "Parameter uses 'parent' as type hint but function is not a class member!");
02267                             return;
02268                      }
02269                      if (!ce->parent) {
02270                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02271                                    "Parameter uses 'parent' as type hint although class does not have a parent!");
02272                             return;
02273                      }
02274                      pce= &ce->parent;
02275               } else if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
02276                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02277                             "Class %s does not exist", param->arg_info->class_name);
02278                      return;
02279               }
02280               zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
02281        }
02282 }
02283 /* }}} */
02284 
02285 /* {{{ proto public bool ReflectionParameter::isArray()
02286    Returns whether parameter MUST be an array */
02287 ZEND_METHOD(reflection_parameter, isArray)
02288 {
02289        reflection_object *intern;
02290        parameter_reference *param;
02291 
02292        if (zend_parse_parameters_none() == FAILURE) {
02293               return;
02294        }
02295        GET_REFLECTION_OBJECT_PTR(param);
02296 
02297        RETVAL_BOOL(param->arg_info->array_type_hint);
02298 }
02299 /* }}} */
02300 
02301 /* {{{ proto public bool ReflectionParameter::allowsNull()
02302    Returns whether NULL is allowed as this parameters's value */
02303 ZEND_METHOD(reflection_parameter, allowsNull)
02304 {
02305        reflection_object *intern;
02306        parameter_reference *param;
02307 
02308        if (zend_parse_parameters_none() == FAILURE) {
02309               return;
02310        }
02311        GET_REFLECTION_OBJECT_PTR(param);
02312 
02313        RETVAL_BOOL(param->arg_info->allow_null);
02314 }
02315 /* }}} */
02316 
02317 /* {{{ proto public bool ReflectionParameter::isPassedByReference()
02318    Returns whether this parameters is passed to by reference */
02319 ZEND_METHOD(reflection_parameter, isPassedByReference)
02320 {
02321        reflection_object *intern;
02322        parameter_reference *param;
02323 
02324        if (zend_parse_parameters_none() == FAILURE) {
02325               return;
02326        }
02327        GET_REFLECTION_OBJECT_PTR(param);
02328 
02329        RETVAL_BOOL(param->arg_info->pass_by_reference);
02330 }
02331 /* }}} */
02332 
02333 /* {{{ proto public bool ReflectionParameter::getPosition()
02334    Returns whether this parameter is an optional parameter */
02335 ZEND_METHOD(reflection_parameter, getPosition)
02336 {
02337        reflection_object *intern;
02338        parameter_reference *param;
02339 
02340        if (zend_parse_parameters_none() == FAILURE) {
02341               return;
02342        }
02343        GET_REFLECTION_OBJECT_PTR(param);
02344 
02345        RETVAL_LONG(param->offset);
02346 }
02347 /* }}} */
02348 
02349 /* {{{ proto public bool ReflectionParameter::isOptional()
02350    Returns whether this parameter is an optional parameter */
02351 ZEND_METHOD(reflection_parameter, isOptional)
02352 {
02353        reflection_object *intern;
02354        parameter_reference *param;
02355 
02356        if (zend_parse_parameters_none() == FAILURE) {
02357               return;
02358        }
02359        GET_REFLECTION_OBJECT_PTR(param);
02360 
02361        RETVAL_BOOL(param->offset >= param->required);
02362 }
02363 /* }}} */
02364 
02365 /* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
02366    Returns whether the default value of this parameter is available */
02367 ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
02368 {
02369        reflection_object *intern;
02370        parameter_reference *param;
02371        zend_op *precv;
02372 
02373        if (zend_parse_parameters_none() == FAILURE) {
02374               return;
02375        }
02376        GET_REFLECTION_OBJECT_PTR(param);
02377 
02378        if (param->fptr->type != ZEND_USER_FUNCTION)
02379        {
02380               RETURN_FALSE;
02381        }
02382        if (param->offset < param->required) {
02383               RETURN_FALSE;
02384        }
02385        precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
02386        if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
02387               RETURN_FALSE;
02388        }
02389        RETURN_TRUE;
02390 }
02391 /* }}} */
02392 
02393 /* {{{ proto public bool ReflectionParameter::getDefaultValue()
02394    Returns the default value of this parameter or throws an exception */
02395 ZEND_METHOD(reflection_parameter, getDefaultValue)
02396 {
02397        reflection_object *intern;
02398        parameter_reference *param;
02399        zend_op *precv;
02400 
02401        if (zend_parse_parameters_none() == FAILURE) {
02402               return;
02403        }
02404        GET_REFLECTION_OBJECT_PTR(param);
02405 
02406        if (param->fptr->type != ZEND_USER_FUNCTION)
02407        {
02408               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
02409               return;
02410        }
02411        if (param->offset < param->required) {
02412               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); 
02413               return;
02414        }
02415        precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
02416        if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
02417               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); 
02418               return;
02419        }
02420 
02421        *return_value = precv->op2.u.constant;
02422        INIT_PZVAL(return_value);
02423        if (Z_TYPE_P(return_value) != IS_CONSTANT && Z_TYPE_P(return_value) != IS_CONSTANT_ARRAY) {
02424               zval_copy_ctor(return_value);
02425        }
02426        zval_update_constant_ex(&return_value, (void*)0, param->fptr->common.scope TSRMLS_CC);
02427 }
02428 /* }}} */
02429 
02430 /* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
02431    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
02432 ZEND_METHOD(reflection_method, export)
02433 {
02434        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_method_ptr, 2);
02435 }
02436 /* }}} */
02437 
02438 /* {{{ proto public void ReflectionMethod::__construct(mixed class_or_method [, string name])
02439    Constructor. Throws an Exception in case the given method does not exist */
02440 ZEND_METHOD(reflection_method, __construct)
02441 {
02442        zval *name, *classname;
02443        zval *object, *orig_obj;
02444        reflection_object *intern;
02445        char *lcname;
02446        zend_class_entry **pce;
02447        zend_class_entry *ce;
02448        zend_function *mptr;
02449        char *name_str, *tmp;
02450        int name_len, tmp_len;
02451        zval ztmp;
02452 
02453        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
02454               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
02455                      return;
02456               }
02457               if ((tmp = strstr(name_str, "::")) == NULL) {
02458                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Invalid method name %s", name_str); 
02459                      return;
02460               }
02461               classname = &ztmp;
02462               tmp_len = tmp - name_str;
02463               ZVAL_STRINGL(classname, name_str, tmp_len, 1);
02464               name_len = name_len - (tmp_len + 2);
02465               name_str = tmp + 2;
02466               orig_obj = NULL;
02467        } else if (Z_TYPE_P(classname) == IS_OBJECT) {
02468               orig_obj = classname;
02469        } else {
02470               orig_obj = NULL;
02471        }
02472 
02473        object = getThis();
02474        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
02475        if (intern == NULL) {
02476               return;
02477        }
02478        
02479        /* Find the class entry */
02480        switch (Z_TYPE_P(classname)) {
02481               case IS_STRING:
02482                      if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
02483                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
02484                                           "Class %s does not exist", Z_STRVAL_P(classname)); 
02485                             if (classname == &ztmp) {
02486                                    zval_dtor(&ztmp);
02487                             }
02488                             return;
02489                      }
02490                      ce = *pce;
02491                      break;
02492 
02493               case IS_OBJECT:
02494                      ce = Z_OBJCE_P(classname);
02495                      break;
02496 
02497               default:
02498                      if (classname == &ztmp) {
02499                             zval_dtor(&ztmp);
02500                      }
02501                      _DO_THROW("The parameter class is expected to be either a string or an object");
02502                      /* returns out of this function */
02503        }
02504 
02505        if (classname == &ztmp) {
02506               zval_dtor(&ztmp);
02507        }
02508 
02509        lcname = zend_str_tolower_dup(name_str, name_len);
02510 
02511        if (ce == zend_ce_closure && orig_obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
02512               && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
02513               && (mptr = zend_get_closure_invoke_method(orig_obj TSRMLS_CC)) != NULL)
02514        {
02515               /* do nothing, mptr already set */
02516        } else if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
02517               efree(lcname);
02518               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02519                      "Method %s::%s() does not exist", ce->name, name_str);
02520               return;
02521        }
02522        efree(lcname);
02523 
02524        MAKE_STD_ZVAL(classname);
02525        ZVAL_STRINGL(classname, mptr->common.scope->name, mptr->common.scope->name_length, 1);
02526 
02527        zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
02528        
02529        MAKE_STD_ZVAL(name);
02530        ZVAL_STRING(name, mptr->common.function_name, 1);
02531        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
02532        intern->ptr = mptr;
02533        intern->ref_type = REF_TYPE_FUNCTION;
02534        intern->ce = ce;
02535 }
02536 /* }}} */
02537 
02538 /* {{{ proto public string ReflectionMethod::__toString()
02539    Returns a string representation */
02540 ZEND_METHOD(reflection_method, __toString)
02541 {
02542        reflection_object *intern;
02543        zend_function *mptr;
02544        string str;
02545 
02546        if (zend_parse_parameters_none() == FAILURE) {
02547               return;
02548        }
02549        GET_REFLECTION_OBJECT_PTR(mptr);
02550        string_init(&str);
02551        _function_string(&str, mptr, intern->ce, "" TSRMLS_CC);
02552        RETURN_STRINGL(str.string, str.len - 1, 0);
02553 }
02554 /* }}} */
02555 
02556 /* {{{ proto public mixed ReflectionMethod::invoke(mixed object, mixed* args)
02557    Invokes the method. */
02558 ZEND_METHOD(reflection_method, invoke)
02559 {
02560        zval *retval_ptr;
02561        zval ***params = NULL;
02562        zval *object_ptr;
02563        reflection_object *intern;
02564        zend_function *mptr;
02565        int result, num_args = 0;
02566        zend_fcall_info fci;
02567        zend_fcall_info_cache fcc;
02568        zend_class_entry *obj_ce;
02569        
02570        METHOD_NOTSTATIC(reflection_method_ptr);
02571 
02572        GET_REFLECTION_OBJECT_PTR(mptr);
02573 
02574        if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
02575                || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
02576                && intern->ignore_visibility == 0)
02577        {
02578               if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
02579                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02580                             "Trying to invoke abstract method %s::%s()", 
02581                             mptr->common.scope->name, mptr->common.function_name);
02582               } else {
02583                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
02584                             "Trying to invoke %s method %s::%s() from scope %s", 
02585                             mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
02586                             mptr->common.scope->name, mptr->common.function_name,
02587                             Z_OBJCE_P(getThis())->name);
02588               }
02589               return;
02590        }
02591 
02592        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &params, &num_args) == FAILURE) {
02593               return;
02594        }
02595        
02596        /* In case this is a static method, we should'nt pass an object_ptr
02597         * (which is used as calling context aka $this). We can thus ignore the
02598         * first parameter.
02599         *
02600         * Else, we verify that the given object is an instance of the class.
02601         */
02602        if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
02603               object_ptr = NULL;
02604               obj_ce = mptr->common.scope;
02605        } else {
02606               if (Z_TYPE_PP(params[0]) != IS_OBJECT) {
02607                      efree(params);
02608                      _DO_THROW("Non-object passed to Invoke()");
02609                      /* Returns from this function */
02610               }
02611 
02612               obj_ce = Z_OBJCE_PP(params[0]);
02613 
02614               if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
02615                      if (params) {
02616                             efree(params);
02617                      }
02618                      _DO_THROW("Given object is not an instance of the class this method was declared in");
02619                      /* Returns from this function */
02620               }
02621        
02622               object_ptr = *params[0];
02623        }
02624        
02625        fci.size = sizeof(fci);
02626        fci.function_table = NULL;
02627        fci.function_name = NULL;
02628        fci.symbol_table = NULL;
02629        fci.object_ptr = object_ptr;
02630        fci.retval_ptr_ptr = &retval_ptr;
02631        fci.param_count = num_args - 1;
02632        fci.params = params + 1;
02633        fci.no_separation = 1;
02634 
02635        fcc.initialized = 1;
02636        fcc.function_handler = mptr;
02637        fcc.calling_scope = obj_ce;
02638        fcc.called_scope = intern->ce;
02639        fcc.object_ptr = object_ptr;
02640 
02641        result = zend_call_function(&fci, &fcc TSRMLS_CC);
02642        
02643        if (params) {
02644               efree(params);
02645        }
02646 
02647        if (result == FAILURE) {
02648               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02649                      "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
02650               return;
02651        }
02652 
02653        if (retval_ptr) {
02654               COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
02655        }
02656 }
02657 /* }}} */
02658 
02659 /* {{{ proto public mixed ReflectionMethod::invokeArgs(mixed object, array args)
02660    Invokes the function and pass its arguments as array. */
02661 ZEND_METHOD(reflection_method, invokeArgs)
02662 {
02663        zval *retval_ptr;
02664        zval ***params;
02665        zval *object;
02666        reflection_object *intern;
02667        zend_function *mptr;
02668        int argc;
02669        int result;
02670        zend_fcall_info fci;
02671        zend_fcall_info_cache fcc;
02672        zend_class_entry *obj_ce;
02673        zval *param_array;
02674        
02675        METHOD_NOTSTATIC(reflection_method_ptr);
02676 
02677        GET_REFLECTION_OBJECT_PTR(mptr);
02678 
02679        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a", &object, &param_array) == FAILURE) {
02680               return;
02681        }
02682 
02683        if ((!(mptr->common.fn_flags & ZEND_ACC_PUBLIC)
02684                || (mptr->common.fn_flags & ZEND_ACC_ABSTRACT))
02685                && intern->ignore_visibility == 0)
02686        {
02687               if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
02688                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02689                             "Trying to invoke abstract method %s::%s()", 
02690                             mptr->common.scope->name, mptr->common.function_name);
02691               } else {
02692                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
02693                             "Trying to invoke %s method %s::%s() from scope %s", 
02694                             mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
02695                             mptr->common.scope->name, mptr->common.function_name,
02696                             Z_OBJCE_P(getThis())->name);
02697               }
02698               return;
02699        }
02700 
02701        argc = zend_hash_num_elements(Z_ARRVAL_P(param_array));
02702        
02703        params = safe_emalloc(sizeof(zval **), argc, 0);
02704        zend_hash_apply_with_argument(Z_ARRVAL_P(param_array), (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC);   
02705        params -= argc;
02706        
02707        /* In case this is a static method, we should'nt pass an object_ptr
02708         * (which is used as calling context aka $this). We can thus ignore the
02709         * first parameter.
02710         *
02711         * Else, we verify that the given object is an instance of the class.
02712         */
02713        if (mptr->common.fn_flags & ZEND_ACC_STATIC) {
02714               object = NULL;
02715               obj_ce = mptr->common.scope;
02716        } else {
02717               if (!object) {
02718                      efree(params);
02719                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
02720                             "Trying to invoke non static method %s::%s() without an object", 
02721                             mptr->common.scope->name, mptr->common.function_name);
02722                      return;
02723               }
02724               
02725               obj_ce = Z_OBJCE_P(object);
02726 
02727               if (!instanceof_function(obj_ce, mptr->common.scope TSRMLS_CC)) {
02728                      efree(params);
02729                      _DO_THROW("Given object is not an instance of the class this method was declared in");
02730                      /* Returns from this function */
02731               }
02732        }
02733        
02734        fci.size = sizeof(fci);
02735        fci.function_table = NULL;
02736        fci.function_name = NULL;
02737        fci.symbol_table = NULL;
02738        fci.object_ptr = object;
02739        fci.retval_ptr_ptr = &retval_ptr;
02740        fci.param_count = argc;
02741        fci.params = params;
02742        fci.no_separation = 1;
02743 
02744        fcc.initialized = 1;
02745        fcc.function_handler = mptr;
02746        fcc.calling_scope = obj_ce;
02747        fcc.called_scope = obj_ce;
02748        fcc.object_ptr = object;
02749 
02750        result = zend_call_function(&fci, &fcc TSRMLS_CC);
02751        
02752        efree(params);
02753 
02754        if (result == FAILURE) {
02755               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02756                      "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
02757               return;
02758        }
02759 
02760        if (retval_ptr) {
02761               COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
02762        }
02763 }
02764 /* }}} */
02765 
02766 /* {{{ proto public bool ReflectionMethod::isFinal()
02767    Returns whether this method is final */
02768 ZEND_METHOD(reflection_method, isFinal)
02769 {
02770        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
02771 }
02772 /* }}} */
02773 
02774 /* {{{ proto public bool ReflectionMethod::isAbstract()
02775    Returns whether this method is abstract */
02776 ZEND_METHOD(reflection_method, isAbstract)
02777 {
02778        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ABSTRACT);
02779 }
02780 /* }}} */
02781 
02782 /* {{{ proto public bool ReflectionMethod::isPublic()
02783    Returns whether this method is public */
02784 ZEND_METHOD(reflection_method, isPublic)
02785 {
02786        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC);
02787 }
02788 /* }}} */
02789 
02790 /* {{{ proto public bool ReflectionMethod::isPrivate()
02791    Returns whether this method is private */
02792 ZEND_METHOD(reflection_method, isPrivate)
02793 {
02794        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
02795 }
02796 /* }}} */
02797 
02798 /* {{{ proto public bool ReflectionMethod::isProtected()
02799    Returns whether this method is protected */
02800 ZEND_METHOD(reflection_method, isProtected)
02801 {
02802        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
02803 }
02804 /* }}} */
02805 
02806 /* {{{ proto public bool ReflectionMethod::isStatic()
02807    Returns whether this method is static */
02808 ZEND_METHOD(reflection_method, isStatic)
02809 {
02810        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
02811 }
02812 /* }}} */
02813 
02814 /* {{{ proto public bool ReflectionFunction::isDeprecated()
02815    Returns whether this function is deprecated */
02816 ZEND_METHOD(reflection_function, isDeprecated)
02817 {
02818        _function_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_DEPRECATED);
02819 }
02820 /* }}} */
02821 
02822 /* {{{ proto public bool ReflectionFunction::inNamespace()
02823    Returns whether this function is defined in namespace */
02824 ZEND_METHOD(reflection_function, inNamespace)
02825 {
02826        zval **name;
02827        char *colon;
02828 
02829        if (zend_parse_parameters_none() == FAILURE) {
02830               return;
02831        }
02832        if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
02833               RETURN_FALSE;
02834        }
02835        if (Z_TYPE_PP(name) == IS_STRING
02836               && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
02837               && colon > Z_STRVAL_PP(name))
02838        {
02839               RETURN_TRUE;
02840        }
02841        RETURN_FALSE;
02842 }
02843 /* }}} */
02844 
02845 /* {{{ proto public string ReflectionFunction::getNamespaceName()
02846    Returns the name of namespace where this function is defined */
02847 ZEND_METHOD(reflection_function, getNamespaceName)
02848 {
02849        zval **name;
02850        char *backslash;
02851 
02852        if (zend_parse_parameters_none() == FAILURE) {
02853               return;
02854        }
02855        if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
02856               RETURN_FALSE;
02857        }
02858        if (Z_TYPE_PP(name) == IS_STRING
02859               && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
02860               && backslash > Z_STRVAL_PP(name))
02861        {
02862               RETURN_STRINGL(Z_STRVAL_PP(name), backslash - Z_STRVAL_PP(name), 1);
02863        }
02864        RETURN_EMPTY_STRING();
02865 }
02866 /* }}} */
02867 
02868 /* {{{ proto public string ReflectionFunction::getShortName()
02869    Returns the short name of the function (without namespace part) */
02870 ZEND_METHOD(reflection_function, getShortName)
02871 {
02872        zval **name;
02873        char *backslash;
02874 
02875        if (zend_parse_parameters_none() == FAILURE) {
02876               return;
02877        }
02878        if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
02879               RETURN_FALSE;
02880        }
02881        if (Z_TYPE_PP(name) == IS_STRING
02882               && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
02883               && backslash > Z_STRVAL_PP(name))
02884        {
02885               RETURN_STRINGL(backslash + 1, Z_STRLEN_PP(name) - (backslash - Z_STRVAL_PP(name) + 1), 1);
02886        }
02887        RETURN_ZVAL(*name, 1, 0);
02888 }
02889 /* }}} */
02890 
02891 /* {{{ proto public bool ReflectionMethod::isConstructor()
02892    Returns whether this method is the constructor */
02893 ZEND_METHOD(reflection_method, isConstructor)
02894 {
02895        reflection_object *intern;
02896        zend_function *mptr;
02897 
02898        if (zend_parse_parameters_none() == FAILURE) {
02899               return;
02900        }
02901        GET_REFLECTION_OBJECT_PTR(mptr);
02902        /* we need to check if the ctor is the ctor of the class level we we 
02903         * looking at since we might be looking at an inherited old style ctor
02904         * defined in base class. */
02905        RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_CTOR && intern->ce->constructor && intern->ce->constructor->common.scope == mptr->common.scope);
02906 }
02907 /* }}} */
02908 
02909 /* {{{ proto public bool ReflectionMethod::isDestructor()
02910    Returns whether this method is static */
02911 ZEND_METHOD(reflection_method, isDestructor)
02912 {
02913        reflection_object *intern;
02914        zend_function *mptr;
02915 
02916        if (zend_parse_parameters_none() == FAILURE) {
02917               return;
02918        }
02919        GET_REFLECTION_OBJECT_PTR(mptr);
02920        RETURN_BOOL(mptr->common.fn_flags & ZEND_ACC_DTOR);
02921 }
02922 /* }}} */
02923 
02924 /* {{{ proto public int ReflectionMethod::getModifiers()
02925    Returns a bitfield of the access modifiers for this method */
02926 ZEND_METHOD(reflection_method, getModifiers)
02927 {
02928        reflection_object *intern;
02929        zend_function *mptr;
02930 
02931        if (zend_parse_parameters_none() == FAILURE) {
02932               return;
02933        }
02934        GET_REFLECTION_OBJECT_PTR(mptr);
02935 
02936        RETURN_LONG(mptr->common.fn_flags);
02937 }
02938 /* }}} */
02939 
02940 /* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
02941    Get the declaring class */
02942 ZEND_METHOD(reflection_method, getDeclaringClass)
02943 {
02944        reflection_object *intern;
02945        zend_function *mptr;
02946 
02947        METHOD_NOTSTATIC(reflection_method_ptr);
02948        GET_REFLECTION_OBJECT_PTR(mptr);
02949        
02950        if (zend_parse_parameters_none() == FAILURE) {
02951               return;
02952        }
02953 
02954        zend_reflection_class_factory(mptr->common.scope, return_value TSRMLS_CC);
02955 }
02956 /* }}} */
02957 
02958 /* {{{ proto public ReflectionClass ReflectionMethod::getPrototype()
02959    Get the prototype */
02960 ZEND_METHOD(reflection_method, getPrototype)
02961 {
02962        reflection_object *intern;
02963        zend_function *mptr;
02964 
02965        METHOD_NOTSTATIC(reflection_method_ptr);
02966        GET_REFLECTION_OBJECT_PTR(mptr);
02967        
02968        if (zend_parse_parameters_none() == FAILURE) {
02969               return;
02970        }
02971        
02972        if (!mptr->common.prototype) {
02973               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
02974                      "Method %s::%s does not have a prototype", intern->ce->name, mptr->common.function_name);
02975               return;
02976        }
02977 
02978        reflection_method_factory(mptr->common.prototype->common.scope, mptr->common.prototype, NULL, return_value TSRMLS_CC);
02979 }
02980 /* }}} */
02981 
02982 /* {{{ proto public void ReflectionMethod::setAccessible(bool visible)
02983    Sets whether non-public methods can be invoked */
02984 ZEND_METHOD(reflection_method, setAccessible)
02985 {
02986        reflection_object *intern;
02987        zend_bool visible;
02988 
02989        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == FAILURE) {
02990               return;
02991        }
02992 
02993        intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
02994 
02995        if (intern == NULL) {
02996               return;
02997        }
02998 
02999        intern->ignore_visibility = visible;
03000 }
03001 /* }}} */
03002 
03003 /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
03004    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
03005 ZEND_METHOD(reflection_class, export)
03006 {
03007        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_ptr, 1);
03008 }
03009 /* }}} */
03010 
03011 /* {{{ reflection_class_object_ctor */
03012 static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
03013 {
03014        zval *argument;
03015        zval *object;
03016        zval *classname;
03017        reflection_object *intern;
03018        zend_class_entry **ce;
03019 
03020        if (is_object) {
03021               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &argument) == FAILURE) {
03022                      return;
03023               }
03024        } else {
03025               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &argument) == FAILURE) {
03026                      return;
03027               }
03028        }
03029 
03030        object = getThis();
03031        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
03032        if (intern == NULL) {
03033               return;
03034        }
03035        
03036        if (Z_TYPE_P(argument) == IS_OBJECT) {
03037               MAKE_STD_ZVAL(classname);
03038               ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
03039               zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
03040               intern->ptr = Z_OBJCE_P(argument);
03041               if (is_object) {
03042                      intern->obj = argument;
03043                      zval_add_ref(&argument);
03044               }
03045        } else { 
03046               convert_to_string_ex(&argument);
03047               if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
03048                      if (!EG(exception)) {
03049                             zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", Z_STRVAL_P(argument));
03050                      }
03051                      return;
03052               }
03053 
03054               MAKE_STD_ZVAL(classname);
03055               ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
03056               zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
03057 
03058               intern->ptr = *ce;
03059        }
03060        intern->ref_type = REF_TYPE_OTHER;
03061 }
03062 /* }}} */
03063 
03064 /* {{{ proto public void ReflectionClass::__construct(mixed argument) throws ReflectionException
03065    Constructor. Takes a string or an instance as an argument */
03066 ZEND_METHOD(reflection_class, __construct)
03067 {
03068        reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
03069 }
03070 /* }}} */
03071 
03072 /* {{{ proto public array ReflectionClass::getStaticProperties()
03073    Returns an associative array containing all static property values of the class */
03074 ZEND_METHOD(reflection_class, getStaticProperties)
03075 {
03076        reflection_object *intern;
03077        zend_class_entry *ce;
03078        HashPosition pos;
03079        zval **value;
03080 
03081        if (zend_parse_parameters_none() == FAILURE) {
03082               return;
03083        }
03084        
03085        GET_REFLECTION_OBJECT_PTR(ce);
03086 
03087        zend_update_class_constants(ce TSRMLS_CC);
03088 
03089        array_init(return_value);
03090 
03091        zend_hash_internal_pointer_reset_ex(CE_STATIC_MEMBERS(ce), &pos);
03092 
03093        while (zend_hash_get_current_data_ex(CE_STATIC_MEMBERS(ce), (void **) &value, &pos) == SUCCESS) {
03094               uint key_len;
03095               char *key;
03096               ulong num_index;
03097 
03098               if (zend_hash_get_current_key_ex(CE_STATIC_MEMBERS(ce), &key, &key_len, &num_index, 0, &pos) != FAILURE && key) {
03099                      char *prop_name, *class_name;
03100                      zval *prop_copy;
03101 
03102                      zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
03103 
03104                      /* filter privates from base classes */
03105                      if (!(class_name && class_name[0] != '*' && strcmp(class_name, ce->name))) {
03106                             /* copy: enforce read only access */
03107                             ALLOC_ZVAL(prop_copy);
03108                             MAKE_COPY_ZVAL(value, prop_copy);
03109 
03110                             add_assoc_zval(return_value, prop_name, prop_copy);
03111                      }
03112               }
03113               zend_hash_move_forward_ex(CE_STATIC_MEMBERS(ce), &pos);
03114        }
03115 }
03116 /* }}} */
03117 
03118 /* {{{ proto public mixed ReflectionClass::getStaticPropertyValue(string name [, mixed default])
03119    Returns the value of a static property */
03120 ZEND_METHOD(reflection_class, getStaticPropertyValue)
03121 {
03122        reflection_object *intern;
03123        zend_class_entry *ce;
03124        char *name;
03125        int name_len;
03126        zval **prop, *def_value = NULL;
03127        
03128        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &name, &name_len, &def_value) == FAILURE) {
03129               return;
03130        }
03131 
03132        GET_REFLECTION_OBJECT_PTR(ce);
03133 
03134        zend_update_class_constants(ce TSRMLS_CC);
03135        prop = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
03136        if (!prop) {
03137               if (def_value) {
03138                      RETURN_ZVAL(def_value, 1, 0);
03139               } else {
03140                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
03141                             "Class %s does not have a property named %s", ce->name, name);
03142               }
03143               return;
03144        } else {
03145               RETURN_ZVAL(*prop, 1, 0);
03146        }
03147 }
03148 /* }}} */
03149 
03150 /* {{{ proto public void ReflectionClass::setStaticPropertyValue($name, $value)
03151    Sets the value of a static property */
03152 ZEND_METHOD(reflection_class, setStaticPropertyValue)
03153 {
03154        reflection_object *intern;
03155        zend_class_entry *ce;
03156        char *name;
03157        int name_len;
03158        zval **variable_ptr, *value;
03159        int refcount;
03160        zend_uchar is_ref;
03161        
03162        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &value) == FAILURE) {
03163               return;
03164        }
03165 
03166        GET_REFLECTION_OBJECT_PTR(ce);
03167 
03168        zend_update_class_constants(ce TSRMLS_CC);
03169        variable_ptr = zend_std_get_static_property(ce, name, name_len, 1 TSRMLS_CC);
03170        if (!variable_ptr) {
03171               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
03172                             "Class %s does not have a property named %s", ce->name, name);
03173               return;
03174        }      
03175        refcount = Z_REFCOUNT_PP(variable_ptr);
03176        is_ref = Z_ISREF_PP(variable_ptr);
03177        zval_dtor(*variable_ptr);
03178        **variable_ptr = *value;
03179        zval_copy_ctor(*variable_ptr);
03180        Z_SET_REFCOUNT_PP(variable_ptr, refcount);
03181        Z_SET_ISREF_TO_PP(variable_ptr, is_ref);
03182 
03183 }
03184 /* }}} */
03185 
03186 /* {{{ proto public array ReflectionClass::getDefaultProperties()
03187    Returns an associative array containing copies of all default property values of the class */
03188 ZEND_METHOD(reflection_class, getDefaultProperties)
03189 {
03190        reflection_object *intern;
03191        zend_class_entry *ce;
03192        int count, i;
03193        HashTable *ht_list[3];
03194        
03195        if (zend_parse_parameters_none() == FAILURE) {
03196               return;
03197        }
03198        GET_REFLECTION_OBJECT_PTR(ce);
03199        array_init(return_value);
03200 
03201        zend_update_class_constants(ce TSRMLS_CC);
03202 
03203        ht_list[0] = CE_STATIC_MEMBERS(ce);
03204        ht_list[1] = &ce->default_properties;
03205        ht_list[2] = NULL;
03206 
03207        for (i = 0; ht_list[i] != NULL; i++) {
03208 
03209               count = zend_hash_num_elements(ht_list[i]);
03210               if (count > 0) {
03211                      HashPosition pos;
03212                      zval **prop;
03213 
03214                      zend_hash_internal_pointer_reset_ex(ht_list[i], &pos);
03215                      while (zend_hash_get_current_data_ex(ht_list[i], (void **) &prop, &pos) == SUCCESS) {
03216                             char *key, *class_name, *prop_name;
03217                             uint key_len;
03218                             ulong num_index;
03219                             zval *prop_copy;
03220 
03221                             zend_hash_get_current_key_ex(ht_list[i], &key, &key_len, &num_index, 0, &pos);
03222                             zend_hash_move_forward_ex(ht_list[i], &pos);
03223                             zend_unmangle_property_name(key, key_len-1, &class_name, &prop_name);
03224                             if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
03225                                    /* filter privates from base classes */
03226                                    continue;
03227                             }
03228 
03229                             /* copy: enforce read only access */
03230                             ALLOC_ZVAL(prop_copy);
03231                             MAKE_COPY_ZVAL(prop, prop_copy);
03232 
03233                             add_assoc_zval(return_value, prop_name, prop_copy);
03234                      }
03235               }
03236        }
03237 }
03238 /* }}} */
03239 
03240 /* {{{ proto public string ReflectionClass::__toString()
03241    Returns a string representation */
03242 ZEND_METHOD(reflection_class, __toString)
03243 {
03244        reflection_object *intern;
03245        zend_class_entry *ce;
03246        string str;
03247 
03248        if (zend_parse_parameters_none() == FAILURE) {
03249               return;
03250        }
03251        GET_REFLECTION_OBJECT_PTR(ce);
03252        string_init(&str);
03253        _class_string(&str, ce, intern->obj, "" TSRMLS_CC);
03254        RETURN_STRINGL(str.string, str.len - 1, 0);
03255 }
03256 /* }}} */
03257 
03258 /* {{{ proto public string ReflectionClass::getName()
03259    Returns the class' name */
03260 ZEND_METHOD(reflection_class, getName)
03261 {
03262        if (zend_parse_parameters_none() == FAILURE) {
03263               return;
03264        }
03265        _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
03266 }
03267 /* }}} */
03268 
03269 /* {{{ proto public bool ReflectionClass::isInternal()
03270    Returns whether this class is an internal class */
03271 ZEND_METHOD(reflection_class, isInternal)
03272 {
03273        reflection_object *intern;
03274        zend_class_entry *ce;
03275 
03276        if (zend_parse_parameters_none() == FAILURE) {
03277               return;
03278        }
03279        GET_REFLECTION_OBJECT_PTR(ce);
03280        RETURN_BOOL(ce->type == ZEND_INTERNAL_CLASS);
03281 }
03282 /* }}} */
03283 
03284 /* {{{ proto public bool ReflectionClass::isUserDefined()
03285    Returns whether this class is user-defined */
03286 ZEND_METHOD(reflection_class, isUserDefined)
03287 {
03288        reflection_object *intern;
03289        zend_class_entry *ce;
03290 
03291        if (zend_parse_parameters_none() == FAILURE) {
03292               return;
03293        }
03294        GET_REFLECTION_OBJECT_PTR(ce);
03295        RETURN_BOOL(ce->type == ZEND_USER_CLASS);
03296 }
03297 /* }}} */
03298 
03299 /* {{{ proto public string ReflectionClass::getFileName()
03300    Returns the filename of the file this class was declared in */
03301 ZEND_METHOD(reflection_class, getFileName)
03302 {
03303        reflection_object *intern;
03304        zend_class_entry *ce;
03305 
03306        if (zend_parse_parameters_none() == FAILURE) {
03307               return;
03308        }
03309        GET_REFLECTION_OBJECT_PTR(ce);
03310        if (ce->type == ZEND_USER_CLASS) {
03311               RETURN_STRING(ce->filename, 1);
03312        }
03313        RETURN_FALSE;
03314 }
03315 /* }}} */
03316 
03317 /* {{{ proto public int ReflectionClass::getStartLine()
03318    Returns the line this class' declaration starts at */
03319 ZEND_METHOD(reflection_class, getStartLine)
03320 {
03321        reflection_object *intern;
03322        zend_class_entry *ce;
03323 
03324        if (zend_parse_parameters_none() == FAILURE) {
03325               return;
03326        }
03327        GET_REFLECTION_OBJECT_PTR(ce);
03328        if (ce->type == ZEND_USER_FUNCTION) {
03329               RETURN_LONG(ce->line_start);
03330        }
03331        RETURN_FALSE;
03332 }
03333 /* }}} */
03334 
03335 /* {{{ proto public int ReflectionClass::getEndLine()
03336    Returns the line this class' declaration ends at */
03337 ZEND_METHOD(reflection_class, getEndLine)
03338 {
03339        reflection_object *intern;
03340        zend_class_entry *ce;
03341 
03342        if (zend_parse_parameters_none() == FAILURE) {
03343               return;
03344        }
03345        GET_REFLECTION_OBJECT_PTR(ce);
03346        if (ce->type == ZEND_USER_CLASS) {
03347               RETURN_LONG(ce->line_end);
03348        }
03349        RETURN_FALSE;
03350 }
03351 /* }}} */
03352 
03353 /* {{{ proto public string ReflectionClass::getDocComment()
03354    Returns the doc comment for this class */
03355 ZEND_METHOD(reflection_class, getDocComment)
03356 {
03357        reflection_object *intern;
03358        zend_class_entry *ce;
03359 
03360        if (zend_parse_parameters_none() == FAILURE) {
03361               return;
03362        }
03363        GET_REFLECTION_OBJECT_PTR(ce);
03364        if (ce->type == ZEND_USER_CLASS && ce->doc_comment) {
03365               RETURN_STRINGL(ce->doc_comment, ce->doc_comment_len, 1);
03366        }
03367        RETURN_FALSE;
03368 }
03369 /* }}} */
03370 
03371 /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
03372    Returns the class' constructor if there is one, NULL otherwise */
03373 ZEND_METHOD(reflection_class, getConstructor)
03374 {
03375        reflection_object *intern;
03376        zend_class_entry *ce;
03377 
03378        if (zend_parse_parameters_none() == FAILURE) {
03379               return;
03380        }
03381        GET_REFLECTION_OBJECT_PTR(ce);
03382 
03383        if (ce->constructor) {
03384               reflection_method_factory(ce, ce->constructor, NULL, return_value TSRMLS_CC);
03385        } else {
03386               RETURN_NULL();
03387        }
03388 }
03389 /* }}} */
03390 
03391 /* {{{ proto public bool ReflectionClass::hasMethod(string name)
03392    Returns whether a method exists or not */
03393 ZEND_METHOD(reflection_class, hasMethod)
03394 {
03395        reflection_object *intern;
03396        zend_class_entry *ce;
03397        char *name, *lc_name; 
03398        int name_len;
03399 
03400        METHOD_NOTSTATIC(reflection_class_ptr);
03401        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
03402               return;
03403        }
03404 
03405        GET_REFLECTION_OBJECT_PTR(ce);
03406        lc_name = zend_str_tolower_dup(name, name_len);
03407        if ((ce == zend_ce_closure && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
03408               && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0)
03409               || zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
03410               efree(lc_name);
03411               RETURN_TRUE;
03412        } else {
03413               efree(lc_name);
03414               RETURN_FALSE;
03415        }
03416 }
03417 /* }}} */
03418 
03419 /* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
03420    Returns the class' method specified by its name */
03421 ZEND_METHOD(reflection_class, getMethod)
03422 {
03423        reflection_object *intern;
03424        zend_class_entry *ce;
03425        zend_function *mptr;
03426        zval obj_tmp;
03427        char *name, *lc_name; 
03428        int name_len;
03429 
03430        METHOD_NOTSTATIC(reflection_class_ptr);
03431        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
03432               return;
03433        }
03434 
03435        GET_REFLECTION_OBJECT_PTR(ce);
03436        lc_name = zend_str_tolower_dup(name, name_len);
03437        if (ce == zend_ce_closure && intern->obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
03438               && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
03439               && (mptr = zend_get_closure_invoke_method(intern->obj TSRMLS_CC)) != NULL)
03440        {
03441               /* don't assign closure_object since we only reflect the invoke handler
03442                  method and not the closure definition itself */
03443               reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
03444               efree(lc_name);
03445        } else if (ce == zend_ce_closure && !intern->obj && (name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
03446               && memcmp(lc_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
03447               && object_init_ex(&obj_tmp, ce) == SUCCESS && (mptr = zend_get_closure_invoke_method(&obj_tmp TSRMLS_CC)) != NULL) {
03448               /* don't assign closure_object since we only reflect the invoke handler
03449                  method and not the closure definition itself */
03450               reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
03451               zval_dtor(&obj_tmp);
03452               efree(lc_name);
03453        } else if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
03454               reflection_method_factory(ce, mptr, NULL, return_value TSRMLS_CC);
03455               efree(lc_name);
03456        } else {
03457               efree(lc_name);
03458               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
03459                             "Method %s does not exist", name);
03460               return;
03461        }
03462 }
03463 /* }}} */
03464 
03465 /* {{{ _addmethod */
03466 static void _addmethod(zend_function *mptr, zend_class_entry *ce, zval *retval, long filter, zval *obj TSRMLS_DC)
03467 {
03468        zval *method;
03469        uint len = strlen(mptr->common.function_name);
03470        zend_function *closure;
03471 
03472        if (mptr->common.fn_flags & filter) {
03473               ALLOC_ZVAL(method);
03474               if (ce == zend_ce_closure && obj && (len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
03475                      && memcmp(mptr->common.function_name, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0
03476                      && (closure = zend_get_closure_invoke_method(obj TSRMLS_CC)) != NULL)
03477               {
03478                      mptr = closure;
03479               }
03480               /* don't assign closure_object since we only reflect the invoke handler
03481                  method and not the closure definition itself, even if we have a
03482                  closure */
03483               reflection_method_factory(ce, mptr, NULL, method TSRMLS_CC);
03484               add_next_index_zval(retval, method);
03485        }
03486 }
03487 /* }}} */
03488 
03489 /* {{{ _addmethod */
03490 static int _addmethod_va(zend_function *mptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
03491 {
03492        zend_class_entry *ce = *va_arg(args, zend_class_entry**);
03493        zval *retval = va_arg(args, zval*);
03494        long filter = va_arg(args, long);
03495        zval *obj = va_arg(args, zval *);
03496        
03497        _addmethod(mptr, ce, retval, filter, obj TSRMLS_CC);
03498        return ZEND_HASH_APPLY_KEEP;
03499 }
03500 /* }}} */
03501 
03502 /* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods([long $filter])
03503    Returns an array of this class' methods */
03504 ZEND_METHOD(reflection_class, getMethods)
03505 {
03506        reflection_object *intern;
03507        zend_class_entry *ce;
03508        long filter = 0;
03509        int argc = ZEND_NUM_ARGS();
03510 
03511        METHOD_NOTSTATIC(reflection_class_ptr);
03512        if (argc) {
03513               if (zend_parse_parameters(argc TSRMLS_CC, "|l", &filter) == FAILURE) {
03514                      return;
03515               }
03516        } else {
03517               /* No parameters given, default to "return all" */
03518               filter = ZEND_ACC_PPP_MASK | ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL | ZEND_ACC_STATIC;
03519        }
03520 
03521        GET_REFLECTION_OBJECT_PTR(ce);
03522 
03523        array_init(return_value);
03524        zend_hash_apply_with_arguments(&ce->function_table TSRMLS_CC, (apply_func_args_t) _addmethod_va, 4, &ce, return_value, filter, intern->obj);
03525        if (intern->obj && instanceof_function(ce, zend_ce_closure TSRMLS_CC)) {
03526               zend_function *closure = zend_get_closure_invoke_method(intern->obj TSRMLS_CC);
03527               if (closure) {
03528                      _addmethod(closure, ce, return_value, filter, intern->obj TSRMLS_CC);
03529                      _free_function(closure TSRMLS_CC);
03530               }
03531        }
03532 }
03533 /* }}} */
03534 
03535 /* {{{ proto public bool ReflectionClass::hasProperty(string name)
03536    Returns whether a property exists or not */
03537 ZEND_METHOD(reflection_class, hasProperty)
03538 {
03539        reflection_object *intern;
03540        zend_property_info *property_info;
03541        zend_class_entry *ce;
03542        char *name; 
03543        int name_len;
03544        zval *property;
03545 
03546        METHOD_NOTSTATIC(reflection_class_ptr);
03547        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
03548               return;
03549        }
03550 
03551        GET_REFLECTION_OBJECT_PTR(ce);
03552        if (zend_hash_find(&ce->properties_info, name, name_len+1, (void **) &property_info) == SUCCESS) {
03553               if (property_info->flags & ZEND_ACC_SHADOW) {
03554                      RETURN_FALSE;
03555               }
03556               RETURN_TRUE;
03557        } else {
03558               if (intern->obj && Z_OBJ_HANDLER_P(intern->obj, has_property)) {
03559                      MAKE_STD_ZVAL(property);
03560                      ZVAL_STRINGL(property, name, name_len, 1);
03561                      if (Z_OBJ_HANDLER_P(intern->obj, has_property)(intern->obj, property, 2 TSRMLS_CC)) {
03562                             zval_ptr_dtor(&property);
03563                             RETURN_TRUE;
03564                      }
03565                      zval_ptr_dtor(&property);
03566               }
03567               RETURN_FALSE;
03568        }
03569 }
03570 /* }}} */
03571 
03572 /* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
03573    Returns the class' property specified by its name */
03574 ZEND_METHOD(reflection_class, getProperty)
03575 {
03576        reflection_object *intern;
03577        zend_class_entry *ce, **pce;
03578        zend_property_info *property_info;
03579        char *name, *tmp, *classname; 
03580        int name_len, classname_len;
03581 
03582        METHOD_NOTSTATIC(reflection_class_ptr);
03583        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
03584               return;
03585        }
03586 
03587        GET_REFLECTION_OBJECT_PTR(ce);
03588        if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) {
03589               if ((property_info->flags & ZEND_ACC_SHADOW) == 0) {
03590                      reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
03591                      return;
03592               }
03593        } else if (intern->obj) {
03594               /* Check for dynamic properties */
03595               if (zend_hash_exists(Z_OBJ_HT_P(intern->obj)->get_properties(intern->obj TSRMLS_CC), name, name_len+1)) {
03596                      zend_property_info property_info_tmp;
03597                      property_info_tmp.flags = ZEND_ACC_IMPLICIT_PUBLIC;
03598                      property_info_tmp.name = estrndup(name, name_len);
03599                      property_info_tmp.name_length = name_len;
03600                      property_info_tmp.h = zend_get_hash_value(name, name_len+1);
03601                      property_info_tmp.doc_comment = NULL;
03602                      property_info_tmp.ce = ce;
03603 
03604                      reflection_property_factory(ce, &property_info_tmp, return_value TSRMLS_CC);
03605                      intern = (reflection_object *) zend_object_store_get_object(return_value TSRMLS_CC);
03606                      intern->ref_type = REF_TYPE_DYNAMIC_PROPERTY;
03607                      return;
03608               }
03609        }
03610        if ((tmp = strstr(name, "::")) != NULL) {
03611               classname_len = tmp - name;
03612               classname = zend_str_tolower_dup(name, classname_len);
03613               classname[classname_len] = '\0';
03614               name_len = name_len - (classname_len + 2);
03615               name = tmp + 2;
03616 
03617               if (zend_lookup_class(classname, classname_len, &pce TSRMLS_CC) == FAILURE) {
03618                      if (!EG(exception)) {
03619                             zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", classname);
03620                      }
03621                      efree(classname);
03622                      return;
03623               }
03624               efree(classname);
03625 
03626               if (!instanceof_function(ce, *pce TSRMLS_CC)) {
03627                      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);
03628                      return;
03629               }
03630               ce = *pce;
03631 
03632               if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS && (property_info->flags & ZEND_ACC_SHADOW) == 0) {
03633                      reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
03634                      return;
03635               }             
03636        }
03637        zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
03638                      "Property %s does not exist", name);
03639 }
03640 /* }}} */
03641 
03642 /* {{{ _addproperty */
03643 static int _addproperty(zend_property_info *pptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
03644 {
03645        zval *property;
03646        zend_class_entry *ce = *va_arg(args, zend_class_entry**);
03647        zval *retval = va_arg(args, zval*);
03648        long filter = va_arg(args, long);
03649 
03650        if (pptr->flags      & ZEND_ACC_SHADOW) {
03651               return 0;
03652        }
03653        
03654        if (pptr->flags      & filter) {
03655               ALLOC_ZVAL(property);
03656               reflection_property_factory(ce, pptr, property TSRMLS_CC);
03657               add_next_index_zval(retval, property);
03658        }
03659        return 0;
03660 }
03661 /* }}} */
03662 
03663 /* {{{ _adddynproperty */
03664 static int _adddynproperty(zval **pptr TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
03665 {
03666        zval *property;
03667        zend_class_entry *ce = *va_arg(args, zend_class_entry**);
03668        zval *retval = va_arg(args, zval*), member;
03669 
03670        if (hash_key->arKey[0] == '\0') {
03671               return 0; /* non public cannot be dynamic */
03672        }
03673 
03674        ZVAL_STRINGL(&member, hash_key->arKey, hash_key->nKeyLength-1, 0);
03675        if (zend_get_property_info(ce, &member, 1 TSRMLS_CC) == &EG(std_property_info)) {
03676               MAKE_STD_ZVAL(property);
03677               EG(std_property_info).flags = ZEND_ACC_IMPLICIT_PUBLIC;
03678               reflection_property_factory(ce, &EG(std_property_info), property TSRMLS_CC);
03679               add_next_index_zval(retval, property);
03680        }
03681        return 0;
03682 }
03683 /* }}} */
03684 
03685 /* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties([long $filter])
03686    Returns an array of this class' properties */
03687 ZEND_METHOD(reflection_class, getProperties)
03688 {
03689        reflection_object *intern;
03690        zend_class_entry *ce;
03691        long filter = 0;
03692        int argc = ZEND_NUM_ARGS();
03693 
03694        METHOD_NOTSTATIC(reflection_class_ptr);
03695        if (argc) {
03696               if (zend_parse_parameters(argc TSRMLS_CC, "|l", &filter) == FAILURE) {
03697                      return;
03698               }
03699        } else {
03700               /* No parameters given, default to "return all" */
03701               filter = ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC;
03702        }
03703 
03704        GET_REFLECTION_OBJECT_PTR(ce);
03705 
03706        array_init(return_value);
03707        zend_hash_apply_with_arguments(&ce->properties_info TSRMLS_CC, (apply_func_args_t) _addproperty, 3, &ce, return_value, filter);
03708 
03709        if (intern->obj && (filter & ZEND_ACC_PUBLIC) != 0 && Z_OBJ_HT_P(intern->obj)->get_properties) {
03710               HashTable *properties = Z_OBJ_HT_P(intern->obj)->get_properties(intern->obj TSRMLS_CC);
03711               zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t) _adddynproperty, 2, &ce, return_value);
03712        }
03713 }
03714 /* }}} */
03715 
03716 /* {{{ proto public bool ReflectionClass::hasConstant(string name)
03717    Returns whether a constant exists or not */
03718 ZEND_METHOD(reflection_class, hasConstant)
03719 {
03720        reflection_object *intern;
03721        zend_class_entry *ce;
03722        char *name;
03723        int name_len;
03724 
03725        METHOD_NOTSTATIC(reflection_class_ptr);
03726        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
03727               return;
03728        }
03729 
03730        GET_REFLECTION_OBJECT_PTR(ce);
03731        if (zend_hash_exists(&ce->constants_table, name, name_len + 1)) {
03732               RETURN_TRUE;
03733        } else {
03734               RETURN_FALSE;
03735        }
03736 }
03737 /* }}} */
03738 
03739 /* {{{ proto public array ReflectionClass::getConstants()
03740    Returns an associative array containing this class' constants and their values */
03741 ZEND_METHOD(reflection_class, getConstants)
03742 {
03743        zval *tmp_copy;
03744        reflection_object *intern;
03745        zend_class_entry *ce;
03746 
03747        if (zend_parse_parameters_none() == FAILURE) {
03748               return;
03749        }
03750        GET_REFLECTION_OBJECT_PTR(ce);
03751        array_init(return_value);
03752        zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t)zval_update_constant_inline_change, ce TSRMLS_CC);
03753        zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
03754 }
03755 /* }}} */
03756 
03757 /* {{{ proto public mixed ReflectionClass::getConstant(string name)
03758    Returns the class' constant specified by its name */
03759 ZEND_METHOD(reflection_class, getConstant)
03760 {
03761        reflection_object *intern;
03762        zend_class_entry *ce;
03763        zval **value;
03764        char *name; 
03765        int name_len;
03766 
03767        METHOD_NOTSTATIC(reflection_class_ptr);
03768        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
03769               return;
03770        }
03771 
03772        GET_REFLECTION_OBJECT_PTR(ce);
03773        zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t)zval_update_constant_inline_change, ce TSRMLS_CC);
03774        if (zend_hash_find(&ce->constants_table, name, name_len + 1, (void **) &value) == FAILURE) {
03775               RETURN_FALSE;
03776        }
03777        MAKE_COPY_ZVAL(value, return_value);
03778 }
03779 /* }}} */
03780 
03781 /* {{{ _class_check_flag */
03782 static void _class_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
03783 {
03784        reflection_object *intern;
03785        zend_class_entry *ce;
03786 
03787        if (zend_parse_parameters_none() == FAILURE) {
03788               return;
03789        }
03790        GET_REFLECTION_OBJECT_PTR(ce);
03791        RETVAL_BOOL(ce->ce_flags & mask);
03792 }
03793 /* }}} */
03794 
03795 /* {{{ proto public bool ReflectionClass::isInstantiable()
03796    Returns whether this class is instantiable */
03797 ZEND_METHOD(reflection_class, isInstantiable)
03798 {
03799        reflection_object *intern;
03800        zend_class_entry *ce;
03801 
03802        if (zend_parse_parameters_none() == FAILURE) {
03803               return;
03804        }
03805        GET_REFLECTION_OBJECT_PTR(ce);
03806        if (ce->ce_flags & (ZEND_ACC_INTERFACE | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS)) {
03807               RETURN_FALSE;
03808        }
03809 
03810        /* Basically, the class is instantiable. Though, if there is a constructor
03811         * and it is not publicly accessible, it isn't! */
03812        if (!ce->constructor) {
03813               RETURN_TRUE;
03814        }
03815 
03816        RETURN_BOOL(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC);
03817 }
03818 /* }}} */
03819 
03820 /* {{{ proto public bool ReflectionClass::isInterface()
03821    Returns whether this is an interface or a class */
03822 ZEND_METHOD(reflection_class, isInterface)
03823 {
03824        _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_INTERFACE);
03825 }
03826 /* }}} */
03827 
03828 /* {{{ proto public bool ReflectionClass::isFinal()
03829    Returns whether this class is final */
03830 ZEND_METHOD(reflection_class, isFinal)
03831 {
03832        _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL_CLASS);
03833 }
03834 /* }}} */
03835 
03836 /* {{{ proto public bool ReflectionClass::isAbstract()
03837    Returns whether this class is abstract */
03838 ZEND_METHOD(reflection_class, isAbstract)
03839 {
03840        _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
03841 }
03842 /* }}} */
03843 
03844 /* {{{ proto public int ReflectionClass::getModifiers()
03845    Returns a bitfield of the access modifiers for this class */
03846 ZEND_METHOD(reflection_class, getModifiers)
03847 {
03848        reflection_object *intern;
03849        zend_class_entry *ce;
03850 
03851        if (zend_parse_parameters_none() == FAILURE) {
03852               return;
03853        }
03854        GET_REFLECTION_OBJECT_PTR(ce);
03855 
03856        RETURN_LONG(ce->ce_flags);
03857 }
03858 /* }}} */
03859 
03860 /* {{{ proto public bool ReflectionClass::isInstance(stdclass object)
03861    Returns whether the given object is an instance of this class */
03862 ZEND_METHOD(reflection_class, isInstance)
03863 {
03864        reflection_object *intern;
03865        zend_class_entry *ce;
03866        zval *object;
03867 
03868        METHOD_NOTSTATIC(reflection_class_ptr);
03869        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
03870               return;
03871        }
03872        GET_REFLECTION_OBJECT_PTR(ce);     
03873        RETURN_BOOL(HAS_CLASS_ENTRY(*object) && instanceof_function(Z_OBJCE_P(object), ce TSRMLS_CC));
03874 }
03875 /* }}} */
03876 
03877 /* {{{ proto public stdclass ReflectionClass::newInstance(mixed* args, ...)
03878    Returns an instance of this class */
03879 ZEND_METHOD(reflection_class, newInstance)
03880 {
03881        zval *retval_ptr = NULL;
03882        reflection_object *intern;
03883        zend_class_entry *ce;
03884        
03885        METHOD_NOTSTATIC(reflection_class_ptr);
03886        GET_REFLECTION_OBJECT_PTR(ce);
03887 
03888        /* Run the constructor if there is one */
03889        if (ce->constructor) {
03890               zval ***params = NULL;
03891               int num_args = 0;
03892               zend_fcall_info fci;
03893               zend_fcall_info_cache fcc;
03894 
03895               if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
03896                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
03897                      return;
03898               }
03899 
03900               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &params, &num_args) == FAILURE) {
03901                      if (params) {
03902                             efree(params);
03903                      }
03904                      RETURN_FALSE;
03905               }
03906 
03907               object_init_ex(return_value, ce);
03908 
03909               fci.size = sizeof(fci);
03910               fci.function_table = EG(function_table);
03911               fci.function_name = NULL;
03912               fci.symbol_table = NULL;
03913               fci.object_ptr = return_value;
03914               fci.retval_ptr_ptr = &retval_ptr;
03915               fci.param_count = num_args;
03916               fci.params = params;
03917               fci.no_separation = 1;
03918 
03919               fcc.initialized = 1;
03920               fcc.function_handler = ce->constructor;
03921               fcc.calling_scope = EG(scope);
03922               fcc.called_scope = Z_OBJCE_P(return_value);
03923               fcc.object_ptr = return_value;
03924 
03925               if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
03926                      if (params) {
03927                             efree(params);
03928                      }
03929                      if (retval_ptr) {
03930                             zval_ptr_dtor(&retval_ptr);
03931                      }
03932                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invocation of %s's constructor failed", ce->name);
03933                      RETURN_NULL();
03934               }
03935               if (retval_ptr) {
03936                      zval_ptr_dtor(&retval_ptr);
03937               }
03938               if (params) {
03939                      efree(params);
03940               }
03941        } else if (!ZEND_NUM_ARGS()) {
03942               object_init_ex(return_value, ce);
03943        } else {
03944               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);
03945        }
03946 }
03947 /* }}} */
03948 
03949 /* {{{ proto public stdclass ReflectionClass::newInstanceArgs([array args])
03950    Returns an instance of this class */
03951 ZEND_METHOD(reflection_class, newInstanceArgs)
03952 {
03953        zval *retval_ptr = NULL;
03954        reflection_object *intern;
03955        zend_class_entry *ce;
03956        int argc = 0;
03957        HashTable *args;
03958        
03959        
03960        METHOD_NOTSTATIC(reflection_class_ptr);
03961        GET_REFLECTION_OBJECT_PTR(ce);
03962 
03963        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|h", &args) == FAILURE) {
03964               return;
03965        }
03966        if (ZEND_NUM_ARGS() > 0) {
03967               argc = args->nNumOfElements;
03968        }
03969        
03970        /* Run the constructor if there is one */
03971        if (ce->constructor) {
03972               zval ***params = NULL;
03973               zend_fcall_info fci;
03974               zend_fcall_info_cache fcc;
03975 
03976               if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
03977                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
03978                      return;
03979               }
03980               
03981               if (argc) {
03982                      params = safe_emalloc(sizeof(zval **), argc, 0);
03983                      zend_hash_apply_with_argument(args, (apply_func_arg_t)_zval_array_to_c_array, &params TSRMLS_CC); 
03984                      params -= argc;
03985               }
03986 
03987               object_init_ex(return_value, ce);
03988 
03989               fci.size = sizeof(fci);
03990               fci.function_table = EG(function_table);
03991               fci.function_name = NULL;
03992               fci.symbol_table = NULL;
03993               fci.object_ptr = return_value;
03994               fci.retval_ptr_ptr = &retval_ptr;
03995               fci.param_count = argc;
03996               fci.params = params;
03997               fci.no_separation = 1;
03998 
03999               fcc.initialized = 1;
04000               fcc.function_handler = ce->constructor;
04001               fcc.calling_scope = EG(scope);
04002               fcc.called_scope = Z_OBJCE_P(return_value);
04003               fcc.object_ptr = return_value;
04004 
04005               if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
04006                      if (params) {
04007                             efree(params);
04008                      }
04009                      if (retval_ptr) {
04010                             zval_ptr_dtor(&retval_ptr);
04011                      }
04012                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invocation of %s's constructor failed", ce->name);
04013                      RETURN_NULL();
04014               }
04015               if (retval_ptr) {
04016                      zval_ptr_dtor(&retval_ptr);
04017               }
04018               if (params) {
04019                      efree(params);
04020               }
04021        } else if (!ZEND_NUM_ARGS() || !argc) {
04022               object_init_ex(return_value, ce);
04023        } else {
04024               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);
04025        }
04026 }
04027 /* }}} */
04028 
04029 /* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
04030    Returns an array of interfaces this class implements */
04031 ZEND_METHOD(reflection_class, getInterfaces)
04032 {
04033        reflection_object *intern;
04034        zend_class_entry *ce;
04035 
04036        if (zend_parse_parameters_none() == FAILURE) {
04037               return;
04038        }
04039        GET_REFLECTION_OBJECT_PTR(ce);
04040 
04041        /* Return an empty array if this class implements no interfaces */
04042        array_init(return_value);
04043 
04044        if (ce->num_interfaces) {
04045               zend_uint i;
04046 
04047               for (i=0; i < ce->num_interfaces; i++) {
04048                      zval *interface;
04049                      ALLOC_ZVAL(interface);
04050                      zend_reflection_class_factory(ce->interfaces[i], interface TSRMLS_CC);
04051                      add_assoc_zval_ex(return_value, ce->interfaces[i]->name, ce->interfaces[i]->name_length + 1, interface);
04052               }
04053        }
04054 }
04055 /* }}} */
04056 
04057 /* {{{ proto public String[] ReflectionClass::getInterfaceNames()
04058    Returns an array of names of interfaces this class implements */
04059 ZEND_METHOD(reflection_class, getInterfaceNames)
04060 {
04061        reflection_object *intern;
04062        zend_class_entry *ce;
04063        zend_uint i;
04064 
04065        if (zend_parse_parameters_none() == FAILURE) {
04066               return;
04067        }
04068        GET_REFLECTION_OBJECT_PTR(ce);
04069 
04070        /* Return an empty array if this class implements no interfaces */
04071        array_init(return_value);
04072 
04073        for (i=0; i < ce->num_interfaces; i++) {
04074               add_next_index_stringl(return_value, ce->interfaces[i]->name, ce->interfaces[i]->name_length, 1);
04075        }
04076 }
04077 /* }}} */
04078 
04079 /* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
04080    Returns the class' parent class, or, if none exists, FALSE */
04081 ZEND_METHOD(reflection_class, getParentClass)
04082 {
04083        reflection_object *intern;
04084        zend_class_entry *ce;
04085 
04086        if (zend_parse_parameters_none() == FAILURE) {
04087               return;
04088        }
04089        GET_REFLECTION_OBJECT_PTR(ce);
04090        
04091        if (ce->parent) {
04092               zend_reflection_class_factory(ce->parent, return_value TSRMLS_CC);
04093        } else {
04094               RETURN_FALSE;
04095        }
04096 }
04097 /* }}} */
04098 
04099 /* {{{ proto public bool ReflectionClass::isSubclassOf(string|ReflectionClass class)
04100    Returns whether this class is a subclass of another class */
04101 ZEND_METHOD(reflection_class, isSubclassOf)
04102 {
04103        reflection_object *intern, *argument;
04104        zend_class_entry *ce, **pce, *class_ce;
04105        zval *class_name;
04106 
04107        METHOD_NOTSTATIC(reflection_class_ptr);
04108        GET_REFLECTION_OBJECT_PTR(ce);
04109 
04110        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &class_name) == FAILURE) {
04111               return;
04112        }
04113        
04114        switch(class_name->type) {
04115               case IS_STRING:
04116                      if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
04117                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04118                                           "Class %s does not exist", Z_STRVAL_P(class_name));
04119                             return;
04120                      }
04121                      class_ce = *pce;
04122                      break;               
04123               case IS_OBJECT:
04124                      if (instanceof_function(Z_OBJCE_P(class_name), reflection_class_ptr TSRMLS_CC)) {
04125                             argument = (reflection_object *) zend_object_store_get_object(class_name TSRMLS_CC);
04126                             if (argument == NULL || argument->ptr == NULL) {
04127                                    php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
04128                                    /* Bails out */
04129                             }
04130                             class_ce = argument->ptr;
04131                             break;
04132                      }
04133                      /* no break */
04134               default:
04135                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04136                                    "Parameter one must either be a string or a ReflectionClass object");
04137                      return;
04138        }
04139 
04140        RETURN_BOOL((ce != class_ce && instanceof_function(ce, class_ce TSRMLS_CC)));
04141 }
04142 /* }}} */
04143 
04144 /* {{{ proto public bool ReflectionClass::implementsInterface(string|ReflectionClass interface_name)
04145    Returns whether this class is a subclass of another class */
04146 ZEND_METHOD(reflection_class, implementsInterface)
04147 {
04148        reflection_object *intern, *argument;
04149        zend_class_entry *ce, *interface_ce, **pce;
04150        zval *interface;
04151 
04152        METHOD_NOTSTATIC(reflection_class_ptr);
04153        GET_REFLECTION_OBJECT_PTR(ce);
04154 
04155        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &interface) == FAILURE) {
04156               return;
04157        }
04158        
04159        switch(interface->type) {
04160               case IS_STRING:
04161                      if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
04162                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04163                                           "Interface %s does not exist", Z_STRVAL_P(interface));
04164                             return;
04165                      }
04166                      interface_ce = *pce;
04167                      break;               
04168               case IS_OBJECT:
04169                      if (instanceof_function(Z_OBJCE_P(interface), reflection_class_ptr TSRMLS_CC)) {
04170                             argument = (reflection_object *) zend_object_store_get_object(interface TSRMLS_CC);
04171                             if (argument == NULL || argument->ptr == NULL) {
04172                                    php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Failed to retrieve the argument's reflection object");
04173                                    /* Bails out */
04174                             }
04175                             interface_ce = argument->ptr;
04176                             break;
04177                      }
04178                      /* no break */
04179               default:
04180                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04181                                    "Parameter one must either be a string or a ReflectionClass object");
04182                      return;
04183        }
04184 
04185        if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
04186               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04187                             "Interface %s is a Class", interface_ce->name);
04188               return;
04189        }
04190        RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
04191 }
04192 /* }}} */
04193 
04194 /* {{{ proto public bool ReflectionClass::isIterateable()
04195    Returns whether this class is iterateable (can be used inside foreach) */
04196 ZEND_METHOD(reflection_class, isIterateable)
04197 {
04198        reflection_object *intern;
04199        zend_class_entry *ce;
04200        
04201        if (zend_parse_parameters_none() == FAILURE) {
04202               return;
04203        }
04204 
04205        METHOD_NOTSTATIC(reflection_class_ptr);
04206        GET_REFLECTION_OBJECT_PTR(ce);
04207 
04208        RETURN_BOOL(ce->get_iterator != NULL);
04209 }
04210 /* }}} */
04211 
04212 /* {{{ proto public ReflectionExtension|NULL ReflectionClass::getExtension()
04213    Returns NULL or the extension the class belongs to */
04214 ZEND_METHOD(reflection_class, getExtension)
04215 {
04216        reflection_object *intern;
04217        zend_class_entry *ce;
04218        
04219        if (zend_parse_parameters_none() == FAILURE) {
04220               return;
04221        }
04222 
04223        METHOD_NOTSTATIC(reflection_class_ptr);
04224        GET_REFLECTION_OBJECT_PTR(ce);
04225 
04226        if (ce->module) {
04227               reflection_extension_factory(return_value, ce->module->name TSRMLS_CC);
04228        }
04229 }
04230 /* }}} */
04231 
04232 /* {{{ proto public string|false ReflectionClass::getExtensionName()
04233    Returns false or the name of the extension the class belongs to */
04234 ZEND_METHOD(reflection_class, getExtensionName)
04235 {
04236        reflection_object *intern;
04237        zend_class_entry *ce;
04238        
04239        if (zend_parse_parameters_none() == FAILURE) {
04240               return;
04241        }
04242 
04243        METHOD_NOTSTATIC(reflection_class_ptr);
04244        GET_REFLECTION_OBJECT_PTR(ce);
04245 
04246        if (ce->module) {
04247               RETURN_STRING(ce->module->name, 1);
04248        } else {
04249               RETURN_FALSE;
04250        }
04251 }
04252 /* }}} */
04253 
04254 /* {{{ proto public bool ReflectionClass::inNamespace()
04255    Returns whether this class is defined in namespace */
04256 ZEND_METHOD(reflection_class, inNamespace)
04257 {
04258        zval **name;
04259        char *colon;
04260 
04261        if (zend_parse_parameters_none() == FAILURE) {
04262               return;
04263        }
04264        if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
04265               RETURN_FALSE;
04266        }
04267        if (Z_TYPE_PP(name) == IS_STRING
04268               && (colon = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
04269               && colon > Z_STRVAL_PP(name))
04270        {
04271               RETURN_TRUE;
04272        }
04273        RETURN_FALSE;
04274 }
04275 /* }}} */
04276 
04277 /* {{{ proto public string ReflectionClass::getNamespaceName()
04278    Returns the name of namespace where this class is defined */
04279 ZEND_METHOD(reflection_class, getNamespaceName)
04280 {
04281        zval **name;
04282        char *backslash;
04283 
04284        if (zend_parse_parameters_none() == FAILURE) {
04285               return;
04286        }
04287        if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
04288               RETURN_FALSE;
04289        }
04290        if (Z_TYPE_PP(name) == IS_STRING
04291               && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
04292               && backslash > Z_STRVAL_PP(name))
04293        {
04294               RETURN_STRINGL(Z_STRVAL_PP(name), backslash - Z_STRVAL_PP(name), 1);
04295        }
04296        RETURN_EMPTY_STRING();
04297 }
04298 /* }}} */
04299 
04300 /* {{{ proto public string ReflectionClass::getShortName()
04301    Returns the short name of the class (without namespace part) */
04302 ZEND_METHOD(reflection_class, getShortName)
04303 {
04304        zval **name;
04305        char *backslash;
04306 
04307        if (zend_parse_parameters_none() == FAILURE) {
04308               return;
04309        }
04310        if (zend_hash_find(Z_OBJPROP_P(getThis()), "name", sizeof("name"), (void **) &name) == FAILURE) {
04311               RETURN_FALSE;
04312        }
04313        if (Z_TYPE_PP(name) == IS_STRING
04314               && (backslash = zend_memrchr(Z_STRVAL_PP(name), '\\', Z_STRLEN_PP(name)))
04315               && backslash > Z_STRVAL_PP(name))
04316        {
04317               RETURN_STRINGL(backslash + 1, Z_STRLEN_PP(name) - (backslash - Z_STRVAL_PP(name) + 1), 1);
04318        }
04319        RETURN_ZVAL(*name, 1, 0);
04320 }
04321 /* }}} */
04322 
04323 /* {{{ proto public static mixed ReflectionObject::export(mixed argument [, bool return]) throws ReflectionException
04324    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
04325 ZEND_METHOD(reflection_object, export)
04326 {
04327        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_object_ptr, 1);
04328 }
04329 /* }}} */
04330 
04331 /* {{{ proto public void ReflectionObject::__construct(mixed argument) throws ReflectionException
04332    Constructor. Takes an instance as an argument */
04333 ZEND_METHOD(reflection_object, __construct)
04334 {
04335        reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
04336 }
04337 /* }}} */
04338 
04339 /* {{{ proto public static mixed ReflectionProperty::export(mixed class, string name [, bool return]) throws ReflectionException
04340    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
04341 ZEND_METHOD(reflection_property, export)
04342 {
04343        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_property_ptr, 2);
04344 }
04345 /* }}} */
04346 
04347 /* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
04348    Constructor. Throws an Exception in case the given property does not exist */
04349 ZEND_METHOD(reflection_property, __construct)
04350 {
04351        zval *propname, *classname;
04352        char *name_str, *class_name, *prop_name;
04353        int name_len, dynam_prop = 0;
04354        zval *object;
04355        reflection_object *intern;
04356        zend_class_entry **pce;
04357        zend_class_entry *ce;
04358        zend_property_info *property_info = NULL;
04359        property_reference *reference;
04360 
04361        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
04362               return;
04363        }
04364 
04365        object = getThis();
04366        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
04367        if (intern == NULL) {
04368               return;
04369        }
04370        
04371        /* Find the class entry */
04372        switch (Z_TYPE_P(classname)) {
04373               case IS_STRING:
04374                      if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
04375                             zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
04376                                           "Class %s does not exist", Z_STRVAL_P(classname)); 
04377                             return;
04378                      }
04379                      ce = *pce;
04380                      break;
04381 
04382               case IS_OBJECT:
04383                      ce = Z_OBJCE_P(classname);
04384                      break;
04385                      
04386               default:
04387                      _DO_THROW("The parameter class is expected to be either a string or an object");
04388                      /* returns out of this function */
04389        }
04390 
04391        if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
04392               /* Check for dynamic properties */
04393               if (property_info == NULL && Z_TYPE_P(classname) == IS_OBJECT && Z_OBJ_HT_P(classname)->get_properties) {
04394                      if (zend_hash_exists(Z_OBJ_HT_P(classname)->get_properties(classname TSRMLS_CC), name_str, name_len+1)) {
04395                             dynam_prop = 1;
04396                      }
04397               }
04398               if (dynam_prop == 0) {
04399                      zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Property %s::$%s does not exist", ce->name, name_str);
04400                      return;
04401               }
04402        }
04403        
04404        if (dynam_prop == 0 && (property_info->flags & ZEND_ACC_PRIVATE) == 0) {
04405               /* we have to search the class hierarchy for this (implicit) public or protected property */
04406               zend_class_entry *tmp_ce = ce;
04407               zend_property_info *tmp_info;
04408               
04409               while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, name_str, name_len + 1, (void **) &tmp_info) != SUCCESS) {
04410                      ce = tmp_ce;
04411                      property_info = tmp_info;
04412                      tmp_ce = tmp_ce->parent;
04413               }
04414        }
04415 
04416        MAKE_STD_ZVAL(classname);   
04417        MAKE_STD_ZVAL(propname);
04418        
04419        if (dynam_prop == 0) {
04420               zend_unmangle_property_name(property_info->name, property_info->name_length, &class_name, &prop_name);
04421               ZVAL_STRINGL(classname, property_info->ce->name, property_info->ce->name_length, 1);
04422               ZVAL_STRING(propname, prop_name, 1);
04423        } else {
04424               ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);  
04425               ZVAL_STRINGL(propname, name_str, name_len, 1);
04426        }
04427        zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
04428        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
04429 
04430        reference = (property_reference*) emalloc(sizeof(property_reference));
04431        if (dynam_prop) {
04432               reference->prop.flags = ZEND_ACC_IMPLICIT_PUBLIC;
04433               reference->prop.name = Z_STRVAL_P(propname);
04434               reference->prop.name_length = Z_STRLEN_P(propname);
04435               reference->prop.h = zend_get_hash_value(name_str, name_len+1);
04436               reference->prop.doc_comment = NULL;
04437               reference->prop.ce = ce;
04438        } else {
04439               reference->prop = *property_info;
04440        }
04441        reference->ce = ce;
04442        intern->ptr = reference;
04443        intern->ref_type = REF_TYPE_PROPERTY;
04444        intern->ce = ce;
04445        intern->ignore_visibility = 0;
04446 }
04447 /* }}} */
04448 
04449 /* {{{ proto public string ReflectionProperty::__toString()
04450    Returns a string representation */
04451 ZEND_METHOD(reflection_property, __toString)
04452 {
04453        reflection_object *intern;
04454        property_reference *ref;
04455        string str;
04456 
04457        if (zend_parse_parameters_none() == FAILURE) {
04458               return;
04459        }
04460        GET_REFLECTION_OBJECT_PTR(ref);
04461        string_init(&str);
04462        _property_string(&str, &ref->prop, NULL, "" TSRMLS_CC);
04463        RETURN_STRINGL(str.string, str.len - 1, 0);
04464 }
04465 /* }}} */
04466 
04467 /* {{{ proto public string ReflectionProperty::getName()
04468    Returns the class' name */
04469 ZEND_METHOD(reflection_property, getName)
04470 {
04471        if (zend_parse_parameters_none() == FAILURE) {
04472               return;
04473        }
04474        _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
04475 }
04476 /* }}} */
04477 
04478 static void _property_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask)
04479 {
04480        reflection_object *intern;
04481        property_reference *ref;
04482 
04483        if (zend_parse_parameters_none() == FAILURE) {
04484               return;
04485        }
04486        GET_REFLECTION_OBJECT_PTR(ref);
04487        RETURN_BOOL(ref->prop.flags & mask);
04488 }
04489 
04490 /* {{{ proto public bool ReflectionProperty::isPublic()
04491    Returns whether this property is public */
04492 ZEND_METHOD(reflection_property, isPublic)
04493 {
04494        _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
04495 }
04496 /* }}} */
04497 
04498 /* {{{ proto public bool ReflectionProperty::isPrivate()
04499    Returns whether this property is private */
04500 ZEND_METHOD(reflection_property, isPrivate)
04501 {
04502        _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
04503 }
04504 /* }}} */
04505 
04506 /* {{{ proto public bool ReflectionProperty::isProtected()
04507    Returns whether this property is protected */
04508 ZEND_METHOD(reflection_property, isProtected)
04509 {
04510        _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
04511 }
04512 /* }}} */
04513 
04514 /* {{{ proto public bool ReflectionProperty::isStatic()
04515    Returns whether this property is static */
04516 ZEND_METHOD(reflection_property, isStatic)
04517 {
04518        _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_STATIC);
04519 }
04520 /* }}} */
04521 
04522 /* {{{ proto public bool ReflectionProperty::isDefault()
04523    Returns whether this property is default (declared at compilation time). */
04524 ZEND_METHOD(reflection_property, isDefault)
04525 {
04526        _property_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ~ZEND_ACC_IMPLICIT_PUBLIC);
04527 }
04528 /* }}} */
04529 
04530 /* {{{ proto public int ReflectionProperty::getModifiers()
04531    Returns a bitfield of the access modifiers for this property */
04532 ZEND_METHOD(reflection_property, getModifiers)
04533 {
04534        reflection_object *intern;
04535        property_reference *ref;
04536 
04537        if (zend_parse_parameters_none() == FAILURE) {
04538               return;
04539        }
04540        GET_REFLECTION_OBJECT_PTR(ref);
04541 
04542        RETURN_LONG(ref->prop.flags);
04543 }
04544 /* }}} */
04545 
04546 /* {{{ proto public mixed ReflectionProperty::getValue([stdclass object])
04547    Returns this property's value */
04548 ZEND_METHOD(reflection_property, getValue)
04549 {
04550        reflection_object *intern;
04551        property_reference *ref;
04552        zval *object, name;
04553        zval **member = NULL, *member_p = NULL;
04554 
04555        METHOD_NOTSTATIC(reflection_property_ptr);
04556        GET_REFLECTION_OBJECT_PTR(ref);
04557 
04558        if (!(ref->prop.flags & (ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC)) && intern->ignore_visibility == 0) {
04559               _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
04560               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04561                      "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
04562               zval_dtor(&name);
04563               return;
04564        }
04565 
04566        if ((ref->prop.flags & ZEND_ACC_STATIC)) {
04567               zend_update_class_constants(intern->ce TSRMLS_CC);
04568               if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &member) == FAILURE) {
04569                      php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
04570                      /* Bails out */
04571               }
04572               MAKE_COPY_ZVAL(member, return_value);
04573        } else {
04574               char *class_name, *prop_name;
04575               
04576               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
04577                      return;
04578               }
04579               zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name);
04580               member_p = zend_read_property(ref->ce, object, prop_name, strlen(prop_name), 1 TSRMLS_CC);
04581               MAKE_COPY_ZVAL(&member_p, return_value);
04582               if (member_p != EG(uninitialized_zval_ptr)) {
04583                      zval_add_ref(&member_p);
04584                      zval_ptr_dtor(&member_p);
04585               }
04586        }
04587 }
04588 /* }}} */
04589 
04590 /* {{{ proto public void ReflectionProperty::setValue([stdclass object,] mixed value)
04591    Sets this property's value */
04592 ZEND_METHOD(reflection_property, setValue)
04593 {
04594        reflection_object *intern;
04595        property_reference *ref;
04596        zval **variable_ptr;
04597        zval *object, name;
04598        zval *value;
04599        int setter_done = 0;
04600        zval *tmp;
04601        HashTable *prop_table;
04602 
04603        METHOD_NOTSTATIC(reflection_property_ptr);
04604        GET_REFLECTION_OBJECT_PTR(ref);
04605 
04606        if (!(ref->prop.flags & ZEND_ACC_PUBLIC) && intern->ignore_visibility == 0) {
04607               _default_get_entry(getThis(), "name", sizeof("name"), &name TSRMLS_CC);
04608               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04609                      "Cannot access non-public member %s::%s", intern->ce->name, Z_STRVAL(name));
04610               zval_dtor(&name);
04611               return;
04612        }
04613 
04614        if ((ref->prop.flags & ZEND_ACC_STATIC)) {
04615               if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
04616                      if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &tmp, &value) == FAILURE) {
04617                             return;
04618                      }
04619               }
04620               zend_update_class_constants(intern->ce TSRMLS_CC);
04621               prop_table = CE_STATIC_MEMBERS(intern->ce);
04622 
04623               if (zend_hash_quick_find(prop_table, ref->prop.name, ref->prop.name_length + 1, ref->prop.h, (void **) &variable_ptr) == FAILURE) {
04624                      php_error_docref(NULL TSRMLS_CC, E_ERROR, "Internal error: Could not find the property %s::%s", intern->ce->name, ref->prop.name);
04625                      /* Bails out */
04626               }
04627               if (*variable_ptr == value) {
04628                      setter_done = 1;
04629               } else {
04630                      if (PZVAL_IS_REF(*variable_ptr)) {
04631                             zval_dtor(*variable_ptr);
04632                             (*variable_ptr)->type = value->type;
04633                             (*variable_ptr)->value = value->value;
04634                             if (Z_REFCOUNT_P(value) > 0) {
04635                                    zval_copy_ctor(*variable_ptr);
04636                             }
04637                             setter_done = 1;
04638                      }
04639               }
04640               if (!setter_done) {
04641                      zval **foo;
04642 
04643                      Z_ADDREF_P(value);
04644                      if (PZVAL_IS_REF(value)) {
04645                             SEPARATE_ZVAL(&value);
04646                      }
04647                      zend_hash_quick_update(prop_table, ref->prop.name, ref->prop.name_length+1, ref->prop.h, &value, sizeof(zval *), (void **) &foo);
04648               }
04649        } else {
04650               char *class_name, *prop_name;
04651 
04652               if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) {
04653                      return;
04654               }
04655               zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name);
04656               zend_update_property(ref->ce, object, prop_name, strlen(prop_name), value TSRMLS_CC);
04657        }
04658 }
04659 /* }}} */
04660 
04661 /* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
04662    Get the declaring class */
04663 ZEND_METHOD(reflection_property, getDeclaringClass)
04664 {
04665        reflection_object *intern;
04666        property_reference *ref;
04667        zend_class_entry *tmp_ce, *ce;
04668        zend_property_info *tmp_info;
04669        char *prop_name, *class_name;
04670        int prop_name_len;
04671 
04672        if (zend_parse_parameters_none() == FAILURE) {
04673               return;
04674        }
04675        GET_REFLECTION_OBJECT_PTR(ref);
04676 
04677        if (zend_unmangle_property_name(ref->prop.name, ref->prop.name_length, &class_name, &prop_name) != SUCCESS) {
04678               RETURN_FALSE;
04679        }
04680 
04681        prop_name_len = strlen(prop_name);
04682        ce = tmp_ce = ref->ce;
04683        while (tmp_ce && zend_hash_find(&tmp_ce->properties_info, prop_name, prop_name_len + 1, (void **) &tmp_info) == SUCCESS) {
04684               if (tmp_info->flags & ZEND_ACC_PRIVATE || tmp_info->flags & ZEND_ACC_SHADOW) {
04685                      /* it's a private property, so it can't be inherited */
04686                      break;
04687               }
04688               ce = tmp_ce;
04689               if (tmp_ce == tmp_info->ce) {
04690                      /* declared in this class, done */
04691                      break;
04692               }
04693               tmp_ce = tmp_ce->parent;
04694        }
04695 
04696        zend_reflection_class_factory(ce, return_value TSRMLS_CC);
04697 }
04698 /* }}} */
04699 
04700 /* {{{ proto public string ReflectionProperty::getDocComment()
04701    Returns the doc comment for this property */
04702 ZEND_METHOD(reflection_property, getDocComment)
04703 {
04704        reflection_object *intern;
04705        property_reference *ref;
04706 
04707        if (zend_parse_parameters_none() == FAILURE) {
04708               return;
04709        }
04710        GET_REFLECTION_OBJECT_PTR(ref);
04711        if (ref->prop.doc_comment) {
04712               RETURN_STRINGL(ref->prop.doc_comment, ref->prop.doc_comment_len, 1);
04713        }
04714        RETURN_FALSE;
04715 }
04716 /* }}} */
04717 
04718 /* {{{ proto public int ReflectionProperty::setAccessible(bool visible)
04719    Sets whether non-public properties can be requested */
04720 ZEND_METHOD(reflection_property, setAccessible)
04721 {
04722        reflection_object *intern;
04723        zend_bool visible;
04724 
04725        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &visible) == FAILURE) {
04726               return;
04727        }
04728 
04729        intern = (reflection_object *) zend_object_store_get_object(getThis() TSRMLS_CC);
04730 
04731        if (intern == NULL) {
04732               return;
04733        }
04734 
04735        intern->ignore_visibility = visible;
04736 }
04737 /* }}} */
04738 
04739 /* {{{ proto public static mixed ReflectionExtension::export(string name [, bool return]) throws ReflectionException
04740    Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
04741 ZEND_METHOD(reflection_extension, export)
04742 {
04743        _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_extension_ptr, 1);
04744 }
04745 /* }}} */
04746 
04747 /* {{{ proto public void ReflectionExtension::__construct(string name)
04748    Constructor. Throws an Exception in case the given extension does not exist */
04749 ZEND_METHOD(reflection_extension, __construct)
04750 {
04751        zval *name;
04752        zval *object;
04753        char *lcname;
04754        reflection_object *intern;
04755        zend_module_entry *module;
04756        char *name_str;
04757        int name_len;
04758        ALLOCA_FLAG(use_heap)
04759 
04760        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
04761               return;
04762        }
04763 
04764        object = getThis();
04765        intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
04766        if (intern == NULL) {
04767               return;
04768        }
04769        lcname = do_alloca(name_len + 1, use_heap);
04770        zend_str_tolower_copy(lcname, name_str, name_len);
04771        if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
04772               free_alloca(lcname, use_heap);
04773               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
04774                      "Extension %s does not exist", name_str);
04775               return;
04776        }
04777        free_alloca(lcname, use_heap);
04778        MAKE_STD_ZVAL(name);
04779        ZVAL_STRING(name, module->name, 1);
04780        zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
04781        intern->ptr = module;
04782        intern->ref_type = REF_TYPE_OTHER;
04783        intern->ce = NULL;
04784 }
04785 /* }}} */
04786 
04787 /* {{{ proto public string ReflectionExtension::__toString()
04788    Returns a string representation */
04789 ZEND_METHOD(reflection_extension, __toString)
04790 {
04791        reflection_object *intern;
04792        zend_module_entry *module;
04793        string str;
04794 
04795        if (zend_parse_parameters_none() == FAILURE) {
04796               return;
04797        }
04798        GET_REFLECTION_OBJECT_PTR(module);
04799        string_init(&str);
04800        _extension_string(&str, module, "" TSRMLS_CC);
04801        RETURN_STRINGL(str.string, str.len - 1, 0);
04802 }
04803 /* }}} */
04804 
04805 /* {{{ proto public string ReflectionExtension::getName()
04806    Returns this extension's name */
04807 ZEND_METHOD(reflection_extension, getName)
04808 {
04809        if (zend_parse_parameters_none() == FAILURE) {
04810               return;
04811        }
04812        _default_get_entry(getThis(), "name", sizeof("name"), return_value TSRMLS_CC);
04813 }
04814 /* }}} */
04815 
04816 /* {{{ proto public string ReflectionExtension::getVersion()
04817    Returns this extension's version */
04818 ZEND_METHOD(reflection_extension, getVersion)
04819 {
04820        reflection_object *intern;
04821        zend_module_entry *module;
04822 
04823        if (zend_parse_parameters_none() == FAILURE) {
04824               return;
04825        }
04826        GET_REFLECTION_OBJECT_PTR(module);
04827 
04828        /* An extension does not necessarily have a version number */
04829        if (module->version == NO_VERSION_YET) {
04830               RETURN_NULL();
04831        } else {
04832               RETURN_STRING(module->version, 1);
04833        }
04834 }
04835 /* }}} */
04836 
04837 /* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
04838    Returns an array of this extension's fuctions */
04839 ZEND_METHOD(reflection_extension, getFunctions)
04840 {
04841        reflection_object *intern;
04842        zend_module_entry *module;
04843 
04844        if (zend_parse_parameters_none() == FAILURE) {
04845               return;
04846        }
04847        GET_REFLECTION_OBJECT_PTR(module);
04848 
04849        array_init(return_value);
04850        if (module->functions) {
04851               zval *function;
04852               zend_function *fptr;
04853               const zend_function_entry *func = module->functions;
04854 
04855               /* Is there a better way of doing this? */
04856               while (func->fname) {
04857                      int fname_len = strlen(func->fname);
04858                      char *lc_name = zend_str_tolower_dup(func->fname, fname_len);
04859                      
04860                      if (zend_hash_find(EG(function_table), lc_name, fname_len + 1, (void**) &fptr) == FAILURE) {
04861                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal error: Cannot find extension function %s in global function table", func->fname);
04862                             func++;
04863                             efree(lc_name);
04864                             continue;
04865                      }
04866                      
04867                      ALLOC_ZVAL(function);
04868                      reflection_function_factory(fptr, NULL, function TSRMLS_CC);
04869                      add_assoc_zval_ex(return_value, func->fname, fname_len+1, function);
04870                      func++;
04871                      efree(lc_name);
04872               }
04873        }
04874 }
04875 /* }}} */
04876 
04877 static int _addconstant(zend_constant *constant TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
04878 {
04879        zval *const_val;
04880        zval *retval = va_arg(args, zval*);
04881        int number = va_arg(args, int);
04882 
04883        if (number == constant->module_number) {
04884               ALLOC_ZVAL(const_val);
04885               *const_val = constant->value;
04886               zval_copy_ctor(const_val);
04887               INIT_PZVAL(const_val);
04888               add_assoc_zval_ex(retval, constant->name, constant->name_len, const_val);
04889        }
04890        return 0;
04891 }
04892 
04893 /* {{{ proto public array ReflectionExtension::getConstants()
04894    Returns an associative array containing this extension's constants and their values */
04895 ZEND_METHOD(reflection_extension, getConstants)
04896 {
04897        reflection_object *intern;
04898        zend_module_entry *module;
04899 
04900        if (zend_parse_parameters_none() == FAILURE) {
04901               return;
04902        }
04903        GET_REFLECTION_OBJECT_PTR(module);
04904 
04905        array_init(return_value);
04906        zend_hash_apply_with_arguments(EG(zend_constants) TSRMLS_CC, (apply_func_args_t) _addconstant, 2, return_value, module->module_number);
04907 }
04908 /* }}} */
04909 
04910 /* {{{ _addinientry */
04911 static int _addinientry(zend_ini_entry *ini_entry TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
04912 {
04913        zval *retval = va_arg(args, zval*);
04914        int number = va_arg(args, int);
04915 
04916        if (number == ini_entry->module_number) {
04917               if (ini_entry->value) {
04918                      add_assoc_stringl(retval, ini_entry->name, ini_entry->value, ini_entry->value_length, 1);
04919               } else {
04920                      add_assoc_null(retval, ini_entry->name);
04921               }
04922        }
04923        return ZEND_HASH_APPLY_KEEP;
04924 }
04925 /* }}} */
04926 
04927 /* {{{ proto public array ReflectionExtension::getINIEntries()
04928    Returns an associative array containing this extension's INI entries and their values */
04929 ZEND_METHOD(reflection_extension, getINIEntries)
04930 {
04931        reflection_object *intern;
04932        zend_module_entry *module;
04933 
04934        if (zend_parse_parameters_none() == FAILURE) {
04935               return;
04936        }
04937        GET_REFLECTION_OBJECT_PTR(module);
04938 
04939        array_init(return_value);
04940        zend_hash_apply_with_arguments(EG(ini_directives) TSRMLS_CC, (apply_func_args_t) _addinientry, 2, return_value, module->module_number);
04941 }
04942 /* }}} */
04943 
04944 /* {{{ add_extension_class */
04945 static int add_extension_class(zend_class_entry **pce TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
04946 {
04947        zval *class_array = va_arg(args, zval*), *zclass;
04948        struct _zend_module_entry *module = va_arg(args, struct _zend_module_entry*);
04949        int add_reflection_class = va_arg(args, int);
04950 
04951        if ((*pce)->module && !strcasecmp((*pce)->module->name, module->name)) {
04952               if (add_reflection_class) {
04953                      ALLOC_ZVAL(zclass);
04954                      zend_reflection_class_factory(*pce, zclass TSRMLS_CC);
04955                      add_assoc_zval_ex(class_array, (*pce)->name, (*pce)->name_length + 1, zclass);
04956               } else {
04957                      add_next_index_stringl(class_array, (*pce)->name, (*pce)->name_length, 1);
04958               }
04959        }
04960        return ZEND_HASH_APPLY_KEEP;
04961 }
04962 /* }}} */
04963 
04964 /* {{{ proto public ReflectionClass[] ReflectionExtension::getClasses()
04965    Returns an array containing ReflectionClass objects for all classes of this extension */
04966 ZEND_METHOD(reflection_extension, getClasses)
04967 {
04968        reflection_object *intern;
04969        zend_module_entry *module;
04970 
04971        if (zend_parse_parameters_none() == FAILURE) {
04972               return;
04973        }
04974        GET_REFLECTION_OBJECT_PTR(module);
04975 
04976        array_init(return_value);
04977        zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) add_extension_class, 3, return_value, module, 1);
04978 }
04979 /* }}} */
04980 
04981 /* {{{ proto public array ReflectionExtension::getClassNames()
04982    Returns an array containing all names of all classes of this extension */
04983 ZEND_METHOD(reflection_extension, getClassNames)
04984 {
04985        reflection_object *intern;
04986        zend_module_entry *module;
04987 
04988        if (zend_parse_parameters_none() == FAILURE) {
04989               return;
04990        }
04991        GET_REFLECTION_OBJECT_PTR(module);
04992 
04993        array_init(return_value);
04994        zend_hash_apply_with_arguments(EG(class_table) TSRMLS_CC, (apply_func_args_t) add_extension_class, 3, return_value, module, 0);
04995 }
04996 /* }}} */
04997 
04998 /* {{{ proto public array ReflectionExtension::getDependencies()
04999    Returns an array containing all names of all extensions this extension depends on */
05000 ZEND_METHOD(reflection_extension, getDependencies)
05001 {
05002        reflection_object *intern;
05003        zend_module_entry *module;
05004        const zend_module_dep *dep;
05005 
05006        if (zend_parse_parameters_none() == FAILURE) {
05007               return;
05008        }
05009        GET_REFLECTION_OBJECT_PTR(module);
05010        
05011        array_init(return_value);
05012 
05013        dep = module->deps;
05014        
05015        if (!dep)
05016        {
05017               return;
05018        }
05019 
05020        while(dep->name) {
05021               char *relation;
05022               char *rel_type;
05023               int len;
05024               
05025               switch(dep->type) {
05026               case MODULE_DEP_REQUIRED:
05027                      rel_type = "Required";
05028                      break;
05029               case MODULE_DEP_CONFLICTS:
05030                      rel_type = "Conflicts";
05031                      break;
05032               case MODULE_DEP_OPTIONAL:
05033                      rel_type = "Optional";
05034                      break;
05035               default:
05036                      rel_type = "Error"; /* shouldn't happen */
05037                      break;
05038               }
05039 
05040               len = spprintf(&relation, 0, "%s%s%s%s%s", 
05041                                           rel_type,
05042                                           dep->rel ? " " : "",
05043                                           dep->rel ? dep->rel : "", 
05044                                           dep->version ? " " : "",
05045                                           dep->version ? dep->version : "");
05046               add_assoc_stringl(return_value, dep->name, relation, len, 0);
05047               dep++;
05048        }
05049 }
05050 /* }}} */
05051 
05052 /* {{{ proto public void ReflectionExtension::info() U
05053        Prints phpinfo block for the extension */
05054 ZEND_METHOD(reflection_extension, info)
05055 {
05056        reflection_object *intern;
05057        zend_module_entry *module;
05058 
05059        if (zend_parse_parameters_none() == FAILURE) {
05060               return;
05061        }
05062        GET_REFLECTION_OBJECT_PTR(module);
05063 
05064        php_info_print_module(module TSRMLS_CC);
05065 }
05066 /* }}} */
05067 
05068 /* {{{ method tables */
05069 static const zend_function_entry reflection_exception_functions[] = {
05070        PHP_FE_END
05071 };
05072 
05073 ZEND_BEGIN_ARG_INFO(arginfo_reflection__void, 0)
05074 ZEND_END_ARG_INFO()
05075 
05076 
05077 ZEND_BEGIN_ARG_INFO(arginfo_reflection_getModifierNames, 0)
05078        ZEND_ARG_INFO(0, modifiers)
05079 ZEND_END_ARG_INFO()
05080 
05081 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_export, 0, 0, 1)
05082        ZEND_ARG_OBJ_INFO(0, reflector, Reflector, 0)
05083        ZEND_ARG_INFO(0, return)
05084 ZEND_END_ARG_INFO()
05085 
05086 static const zend_function_entry reflection_functions[] = {
05087        ZEND_ME(reflection, getModifierNames, arginfo_reflection_getModifierNames, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
05088        ZEND_ME(reflection, export, arginfo_reflection_export, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
05089        PHP_FE_END
05090 };
05091 
05092 static const zend_function_entry reflector_functions[] = {
05093        ZEND_FENTRY(export, NULL, NULL, ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_PUBLIC)
05094        ZEND_ABSTRACT_ME(reflector, __toString, arginfo_reflection__void)
05095        PHP_FE_END
05096 };
05097 
05098 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_export, 0, 0, 1)
05099        ZEND_ARG_INFO(0, name)
05100        ZEND_ARG_INFO(0, return)
05101 ZEND_END_ARG_INFO()
05102 
05103 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function___construct, 0)
05104        ZEND_ARG_INFO(0, name)
05105 ZEND_END_ARG_INFO()
05106 
05107 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_function_invoke, 0, 0, 0)
05108        ZEND_ARG_INFO(0, args)
05109 ZEND_END_ARG_INFO()
05110 
05111 ZEND_BEGIN_ARG_INFO(arginfo_reflection_function_invokeArgs, 0)
05112        ZEND_ARG_ARRAY_INFO(0, args, 0)
05113 ZEND_END_ARG_INFO()
05114 
05115 static const zend_function_entry reflection_function_abstract_functions[] = {
05116        ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
05117        PHP_ABSTRACT_ME(reflection_function, __toString, arginfo_reflection__void)
05118        ZEND_ME(reflection_function, inNamespace, arginfo_reflection__void, 0)
05119        ZEND_ME(reflection_function, isClosure, arginfo_reflection__void, 0)
05120        ZEND_ME(reflection_function, isDeprecated, arginfo_reflection__void, 0)
05121        ZEND_ME(reflection_function, isInternal, arginfo_reflection__void, 0)
05122        ZEND_ME(reflection_function, isUserDefined, arginfo_reflection__void, 0)
05123        ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0)
05124        ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0)
05125        ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0)
05126        ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0)
05127        ZEND_ME(reflection_function, getFileName, arginfo_reflection__void, 0)
05128        ZEND_ME(reflection_function, getName, arginfo_reflection__void, 0)
05129        ZEND_ME(reflection_function, getNamespaceName, arginfo_reflection__void, 0)
05130        ZEND_ME(reflection_function, getNumberOfParameters, arginfo_reflection__void, 0)
05131        ZEND_ME(reflection_function, getNumberOfRequiredParameters, arginfo_reflection__void, 0)
05132        ZEND_ME(reflection_function, getParameters, arginfo_reflection__void, 0)
05133        ZEND_ME(reflection_function, getShortName, arginfo_reflection__void, 0)
05134        ZEND_ME(reflection_function, getStartLine, arginfo_reflection__void, 0)
05135        ZEND_ME(reflection_function, getStaticVariables, arginfo_reflection__void, 0)
05136        ZEND_ME(reflection_function, returnsReference, arginfo_reflection__void, 0)
05137        PHP_FE_END
05138 };
05139 
05140 static const zend_function_entry reflection_function_functions[] = {
05141        ZEND_ME(reflection_function, __construct, arginfo_reflection_function___construct, 0)
05142        ZEND_ME(reflection_function, __toString, arginfo_reflection__void, 0)
05143        ZEND_ME(reflection_function, export, arginfo_reflection_function_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05144        ZEND_ME(reflection_function, isDisabled, arginfo_reflection__void, 0)
05145        ZEND_ME(reflection_function, invoke, arginfo_reflection_function_invoke, 0)
05146        ZEND_ME(reflection_function, invokeArgs, arginfo_reflection_function_invokeArgs, 0)
05147        PHP_FE_END
05148 };
05149 
05150 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method_export, 0, 0, 2)
05151        ZEND_ARG_INFO(0, class)
05152        ZEND_ARG_INFO(0, name)
05153        ZEND_ARG_INFO(0, return)
05154 ZEND_END_ARG_INFO()
05155 
05156 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_method___construct, 0, 0, 1)
05157        ZEND_ARG_INFO(0, class_or_method)
05158        ZEND_ARG_INFO(0, name)
05159 ZEND_END_ARG_INFO()
05160 
05161 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invoke, 0)
05162        ZEND_ARG_INFO(0, object)
05163        ZEND_ARG_INFO(0, args)
05164 ZEND_END_ARG_INFO()
05165 
05166 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_invokeArgs, 0)
05167        ZEND_ARG_INFO(0, object)
05168        ZEND_ARG_ARRAY_INFO(0, args, 0)
05169 ZEND_END_ARG_INFO()
05170 
05171 ZEND_BEGIN_ARG_INFO(arginfo_reflection_method_setAccessible, 0)
05172        ZEND_ARG_INFO(0, value)
05173 ZEND_END_ARG_INFO()
05174 
05175 static const zend_function_entry reflection_method_functions[] = {
05176        ZEND_ME(reflection_method, export, arginfo_reflection_method_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05177        ZEND_ME(reflection_method, __construct, arginfo_reflection_method___construct, 0)
05178        ZEND_ME(reflection_method, __toString, arginfo_reflection__void, 0)
05179        ZEND_ME(reflection_method, isPublic, arginfo_reflection__void, 0)
05180        ZEND_ME(reflection_method, isPrivate, arginfo_reflection__void, 0)
05181        ZEND_ME(reflection_method, isProtected, arginfo_reflection__void, 0)
05182        ZEND_ME(reflection_method, isAbstract, arginfo_reflection__void, 0)
05183        ZEND_ME(reflection_method, isFinal, arginfo_reflection__void, 0)
05184        ZEND_ME(reflection_method, isStatic, arginfo_reflection__void, 0)
05185        ZEND_ME(reflection_method, isConstructor, arginfo_reflection__void, 0)
05186        ZEND_ME(reflection_method, isDestructor, arginfo_reflection__void, 0)
05187        ZEND_ME(reflection_method, getModifiers, arginfo_reflection__void, 0)
05188        ZEND_ME(reflection_method, invoke, arginfo_reflection_method_invoke, 0)
05189        ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
05190        ZEND_ME(reflection_method, getDeclaringClass, arginfo_reflection__void, 0)
05191        ZEND_ME(reflection_method, getPrototype, arginfo_reflection__void, 0)
05192        ZEND_ME(reflection_property, setAccessible, arginfo_reflection_method_setAccessible, 0)
05193        PHP_FE_END
05194 };
05195 
05196 
05197 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_export, 0, 0, 1)
05198        ZEND_ARG_INFO(0, argument)
05199        ZEND_ARG_INFO(0, return)
05200 ZEND_END_ARG_INFO()
05201 
05202 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class___construct, 0)
05203        ZEND_ARG_INFO(0, argument)
05204 ZEND_END_ARG_INFO()
05205 
05206 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getStaticPropertyValue, 0, 0, 1)
05207        ZEND_ARG_INFO(0, name)
05208        ZEND_ARG_INFO(0, default)
05209 ZEND_END_ARG_INFO()
05210 
05211 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_setStaticPropertyValue, 0)
05212        ZEND_ARG_INFO(0, name)
05213        ZEND_ARG_INFO(0, value)
05214 ZEND_END_ARG_INFO()
05215 
05216 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasMethod, 0)
05217        ZEND_ARG_INFO(0, name)
05218 ZEND_END_ARG_INFO()
05219 
05220 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getMethod, 0)
05221        ZEND_ARG_INFO(0, name)
05222 ZEND_END_ARG_INFO()
05223 
05224 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getMethods, 0, 0, 0)
05225        ZEND_ARG_INFO(0, filter)
05226 ZEND_END_ARG_INFO()
05227 
05228 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasProperty, 0)
05229        ZEND_ARG_INFO(0, name)
05230 ZEND_END_ARG_INFO()
05231 
05232 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getProperty, 0)
05233        ZEND_ARG_INFO(0, name)
05234 ZEND_END_ARG_INFO()
05235 
05236 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_getProperties, 0, 0, 0)
05237        ZEND_ARG_INFO(0, filter)
05238 ZEND_END_ARG_INFO()
05239 
05240 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_hasConstant, 0)
05241        ZEND_ARG_INFO(0, name)
05242 ZEND_END_ARG_INFO()
05243 
05244 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_getConstant, 0)
05245        ZEND_ARG_INFO(0, name)
05246 ZEND_END_ARG_INFO()
05247 
05248 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isInstance, 0)
05249        ZEND_ARG_INFO(0, object)
05250 ZEND_END_ARG_INFO()
05251 
05252 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_newInstance, 0)
05253        ZEND_ARG_INFO(0, args)
05254 ZEND_END_ARG_INFO()
05255 
05256 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_newInstanceArgs, 0, 0, 0)
05257        ZEND_ARG_ARRAY_INFO(0, args, 0)
05258 ZEND_END_ARG_INFO()
05259 
05260 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_isSubclassOf, 0)
05261        ZEND_ARG_INFO(0, class)
05262 ZEND_END_ARG_INFO()
05263 
05264 ZEND_BEGIN_ARG_INFO(arginfo_reflection_class_implementsInterface, 0)
05265        ZEND_ARG_INFO(0, interface)
05266 ZEND_END_ARG_INFO()
05267 
05268 static const zend_function_entry reflection_class_functions[] = {
05269        ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
05270        ZEND_ME(reflection_class, export, arginfo_reflection_class_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05271        ZEND_ME(reflection_class, __construct, arginfo_reflection_class___construct, 0)
05272        ZEND_ME(reflection_class, __toString, arginfo_reflection__void, 0)
05273        ZEND_ME(reflection_class, getName, arginfo_reflection__void, 0)
05274        ZEND_ME(reflection_class, isInternal, arginfo_reflection__void, 0)
05275        ZEND_ME(reflection_class, isUserDefined, arginfo_reflection__void, 0)
05276        ZEND_ME(reflection_class, isInstantiable, arginfo_reflection__void, 0)
05277        ZEND_ME(reflection_class, getFileName, arginfo_reflection__void, 0)
05278        ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0)
05279        ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0)
05280        ZEND_ME(reflection_class, getDocComment, arginfo_reflection__void, 0)
05281        ZEND_ME(reflection_class, getConstructor, arginfo_reflection__void, 0)
05282        ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0)
05283        ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0)
05284        ZEND_ME(reflection_class, getMethods, arginfo_reflection_class_getMethods, 0)
05285        ZEND_ME(reflection_class, hasProperty, arginfo_reflection_class_hasProperty, 0)
05286        ZEND_ME(reflection_class, getProperty, arginfo_reflection_class_getProperty, 0)
05287        ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
05288        ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
05289        ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
05290        ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
05291        ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
05292        ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
05293        ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
05294        ZEND_ME(reflection_class, isAbstract, arginfo_reflection__void, 0)
05295        ZEND_ME(reflection_class, isFinal, arginfo_reflection__void, 0)
05296        ZEND_ME(reflection_class, getModifiers, arginfo_reflection__void, 0)
05297        ZEND_ME(reflection_class, isInstance, arginfo_reflection_class_isInstance, 0)
05298        ZEND_ME(reflection_class, newInstance, arginfo_reflection_class_newInstance, 0)
05299        ZEND_ME(reflection_class, newInstanceArgs, arginfo_reflection_class_newInstanceArgs, 0)
05300        ZEND_ME(reflection_class, getParentClass, arginfo_reflection__void, 0)
05301        ZEND_ME(reflection_class, isSubclassOf, arginfo_reflection_class_isSubclassOf, 0)
05302        ZEND_ME(reflection_class, getStaticProperties, arginfo_reflection__void, 0)
05303        ZEND_ME(reflection_class, getStaticPropertyValue, arginfo_reflection_class_getStaticPropertyValue, 0)
05304        ZEND_ME(reflection_class, setStaticPropertyValue, arginfo_reflection_class_setStaticPropertyValue, 0)
05305        ZEND_ME(reflection_class, getDefaultProperties, arginfo_reflection__void, 0)
05306        ZEND_ME(reflection_class, isIterateable, arginfo_reflection__void, 0)
05307        ZEND_ME(reflection_class, implementsInterface, arginfo_reflection_class_implementsInterface, 0)
05308        ZEND_ME(reflection_class, getExtension, arginfo_reflection__void, 0)
05309        ZEND_ME(reflection_class, getExtensionName, arginfo_reflection__void, 0)
05310        ZEND_ME(reflection_class, inNamespace, arginfo_reflection__void, 0)
05311        ZEND_ME(reflection_class, getNamespaceName, arginfo_reflection__void, 0)
05312        ZEND_ME(reflection_class, getShortName, arginfo_reflection__void, 0)
05313        PHP_FE_END
05314 };
05315 
05316 
05317 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_object_export, 0, 0, 1)
05318        ZEND_ARG_INFO(0, argument)
05319        ZEND_ARG_INFO(0, return)
05320 ZEND_END_ARG_INFO()
05321 
05322 ZEND_BEGIN_ARG_INFO(arginfo_reflection_object___construct, 0)
05323        ZEND_ARG_INFO(0, argument)
05324 ZEND_END_ARG_INFO()
05325 
05326 static const zend_function_entry reflection_object_functions[] = {
05327        ZEND_ME(reflection_object, export, arginfo_reflection_object_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05328        ZEND_ME(reflection_object, __construct, arginfo_reflection_object___construct, 0)
05329        PHP_FE_END
05330 };
05331 
05332 
05333 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_export, 0, 0, 2)
05334        ZEND_ARG_INFO(0, class)
05335        ZEND_ARG_INFO(0, name)
05336        ZEND_ARG_INFO(0, return)
05337 ZEND_END_ARG_INFO()
05338 
05339 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property___construct, 0, 0, 2)
05340        ZEND_ARG_INFO(0, class)
05341        ZEND_ARG_INFO(0, name)
05342 ZEND_END_ARG_INFO()
05343 
05344 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_getValue, 0, 0, 0)
05345        ZEND_ARG_INFO(0, object)
05346 ZEND_END_ARG_INFO()
05347 
05348 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_property_setValue, 0, 0, 1)
05349        ZEND_ARG_INFO(0, object)
05350        ZEND_ARG_INFO(0, value)
05351 ZEND_END_ARG_INFO()
05352 
05353 ZEND_BEGIN_ARG_INFO(arginfo_reflection_property_setAccessible, 0)
05354        ZEND_ARG_INFO(0, visible)
05355 ZEND_END_ARG_INFO()
05356 
05357 static const zend_function_entry reflection_property_functions[] = {
05358        ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
05359        ZEND_ME(reflection_property, export, arginfo_reflection_property_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05360        ZEND_ME(reflection_property, __construct, arginfo_reflection_property___construct, 0)
05361        ZEND_ME(reflection_property, __toString, arginfo_reflection__void, 0)
05362        ZEND_ME(reflection_property, getName, arginfo_reflection__void, 0)
05363        ZEND_ME(reflection_property, getValue, arginfo_reflection_property_getValue, 0)
05364        ZEND_ME(reflection_property, setValue, arginfo_reflection_property_setValue, 0)
05365        ZEND_ME(reflection_property, isPublic, arginfo_reflection__void, 0)
05366        ZEND_ME(reflection_property, isPrivate, arginfo_reflection__void, 0)
05367        ZEND_ME(reflection_property, isProtected, arginfo_reflection__void, 0)
05368        ZEND_ME(reflection_property, isStatic, arginfo_reflection__void, 0)
05369        ZEND_ME(reflection_property, isDefault, arginfo_reflection__void, 0)
05370        ZEND_ME(reflection_property, getModifiers, arginfo_reflection__void, 0)
05371        ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0)
05372        ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0)
05373        ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0)
05374        PHP_FE_END
05375 };
05376 
05377 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
05378        ZEND_ARG_INFO(0, function)
05379        ZEND_ARG_INFO(0, parameter)
05380        ZEND_ARG_INFO(0, return)
05381 ZEND_END_ARG_INFO()
05382 
05383 ZEND_BEGIN_ARG_INFO(arginfo_reflection_parameter___construct, 0)
05384        ZEND_ARG_INFO(0, function)
05385        ZEND_ARG_INFO(0, parameter)
05386 ZEND_END_ARG_INFO()
05387 
05388 static const zend_function_entry reflection_parameter_functions[] = {
05389        ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
05390        ZEND_ME(reflection_parameter, export, arginfo_reflection_parameter_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05391        ZEND_ME(reflection_parameter, __construct, arginfo_reflection_parameter___construct, 0)
05392        ZEND_ME(reflection_parameter, __toString, arginfo_reflection__void, 0)
05393        ZEND_ME(reflection_parameter, getName, arginfo_reflection__void, 0)
05394        ZEND_ME(reflection_parameter, isPassedByReference, arginfo_reflection__void, 0)
05395        ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
05396        ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
05397        ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
05398        ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
05399        ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
05400        ZEND_ME(reflection_parameter, getPosition, arginfo_reflection__void, 0)
05401        ZEND_ME(reflection_parameter, isOptional, arginfo_reflection__void, 0)
05402        ZEND_ME(reflection_parameter, isDefaultValueAvailable, arginfo_reflection__void, 0)
05403        ZEND_ME(reflection_parameter, getDefaultValue, arginfo_reflection__void, 0)
05404        PHP_FE_END
05405 };
05406 
05407 ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
05408        ZEND_ARG_INFO(0, name)
05409        ZEND_ARG_INFO(0, return)
05410 ZEND_END_ARG_INFO()
05411 
05412 ZEND_BEGIN_ARG_INFO(arginfo_reflection_extension___construct, 0)
05413        ZEND_ARG_INFO(0, name)
05414 ZEND_END_ARG_INFO()
05415 
05416 static const zend_function_entry reflection_extension_functions[] = {
05417        ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
05418        ZEND_ME(reflection_extension, export, arginfo_reflection_extension_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
05419        ZEND_ME(reflection_extension, __construct, arginfo_reflection_extension___construct, 0)
05420        ZEND_ME(reflection_extension, __toString, arginfo_reflection__void, 0)
05421        ZEND_ME(reflection_extension, getName, arginfo_reflection__void, 0)
05422        ZEND_ME(reflection_extension, getVersion, arginfo_reflection__void, 0)
05423        ZEND_ME(reflection_extension, getFunctions, arginfo_reflection__void, 0)
05424        ZEND_ME(reflection_extension, getConstants, arginfo_reflection__void, 0)
05425        ZEND_ME(reflection_extension, getINIEntries, arginfo_reflection__void, 0)
05426        ZEND_ME(reflection_extension, getClasses, arginfo_reflection__void, 0)
05427        ZEND_ME(reflection_extension, getClassNames, arginfo_reflection__void, 0)
05428        ZEND_ME(reflection_extension, getDependencies, arginfo_reflection__void, 0)
05429        ZEND_ME(reflection_extension, info, arginfo_reflection__void, 0)
05430        PHP_FE_END
05431 };
05432 /* }}} */
05433 
05434 const zend_function_entry reflection_ext_functions[] = { /* {{{ */
05435        PHP_FE_END
05436 }; /* }}} */
05437 
05438 static zend_object_handlers *zend_std_obj_handlers;
05439 
05440 /* {{{ _reflection_write_property */
05441 static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
05442 {
05443        if ((Z_TYPE_P(member) == IS_STRING)
05444               && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
05445               && ((Z_STRLEN_P(member) == sizeof("name") - 1  && !memcmp(Z_STRVAL_P(member), "name",  sizeof("name")))
05446                      || (Z_STRLEN_P(member) == sizeof("class") - 1 && !memcmp(Z_STRVAL_P(member), "class", sizeof("class")))))
05447        {
05448               zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
05449                      "Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
05450        }
05451        else
05452        {
05453               zend_std_obj_handlers->write_property(object, member, value TSRMLS_CC);             
05454        }
05455 }
05456 /* }}} */
05457 
05458 PHP_MINIT_FUNCTION(reflection) /* {{{ */
05459 {
05460        zend_class_entry _reflection_entry;
05461 
05462        zend_std_obj_handlers = zend_get_std_object_handlers();
05463        memcpy(&reflection_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
05464        reflection_object_handlers.clone_obj = NULL;
05465        reflection_object_handlers.write_property = _reflection_write_property;
05466 
05467        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", reflection_exception_functions);
05468        reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
05469 
05470        INIT_CLASS_ENTRY(_reflection_entry, "Reflection", reflection_functions);
05471        reflection_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
05472 
05473        INIT_CLASS_ENTRY(_reflection_entry, "Reflector", reflector_functions);
05474        reflector_ptr = zend_register_internal_interface(&_reflection_entry TSRMLS_CC);
05475 
05476        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", reflection_function_abstract_functions);
05477        _reflection_entry.create_object = reflection_objects_new;
05478        reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
05479        reflection_register_implement(reflection_function_abstract_ptr, reflector_ptr TSRMLS_CC);
05480        zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT TSRMLS_CC);
05481 
05482        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", reflection_function_functions);
05483        _reflection_entry.create_object = reflection_objects_new;
05484        reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr, NULL TSRMLS_CC);
05485        zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05486 
05487        REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
05488 
05489        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", reflection_parameter_functions);
05490        _reflection_entry.create_object = reflection_objects_new;
05491        reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
05492        reflection_register_implement(reflection_parameter_ptr, reflector_ptr TSRMLS_CC);
05493        zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05494 
05495        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
05496        _reflection_entry.create_object = reflection_objects_new;
05497        reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr, NULL TSRMLS_CC);
05498        zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05499        zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05500 
05501        REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
05502        REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
05503        REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PROTECTED", ZEND_ACC_PROTECTED);
05504        REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PRIVATE", ZEND_ACC_PRIVATE);
05505        REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
05506        REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
05507 
05508        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", reflection_class_functions);
05509        _reflection_entry.create_object = reflection_objects_new;
05510        reflection_class_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
05511        reflection_register_implement(reflection_class_ptr, reflector_ptr TSRMLS_CC);
05512        zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05513 
05514        REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
05515        REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
05516        REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL_CLASS);
05517 
05518        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", reflection_object_functions);
05519        _reflection_entry.create_object = reflection_objects_new;
05520        reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr, NULL TSRMLS_CC);
05521 
05522        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", reflection_property_functions);
05523        _reflection_entry.create_object = reflection_objects_new;
05524        reflection_property_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
05525        reflection_register_implement(reflection_property_ptr, reflector_ptr TSRMLS_CC);
05526        zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05527        zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05528 
05529        REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
05530        REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
05531        REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
05532        REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
05533 
05534        INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", reflection_extension_functions);
05535        _reflection_entry.create_object = reflection_objects_new;
05536        reflection_extension_ptr = zend_register_internal_class(&_reflection_entry TSRMLS_CC);
05537        reflection_register_implement(reflection_extension_ptr, reflector_ptr TSRMLS_CC);
05538        zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC TSRMLS_CC);
05539 
05540        return SUCCESS;
05541 } /* }}} */
05542 
05543 PHP_MINFO_FUNCTION(reflection) /* {{{ */
05544 {
05545        php_info_print_table_start();
05546        php_info_print_table_header(2, "Reflection", "enabled");
05547 
05548        php_info_print_table_row(2, "Version", "$Revision: 321634 $");
05549 
05550        php_info_print_table_end();
05551 } /* }}} */
05552 
05553 zend_module_entry reflection_module_entry = { /* {{{ */
05554        STANDARD_MODULE_HEADER,
05555        "Reflection",
05556        reflection_ext_functions,
05557        PHP_MINIT(reflection),
05558        NULL,
05559        NULL,
05560        NULL,
05561        PHP_MINFO(reflection),
05562        "$Revision: 321634 $",
05563        STANDARD_MODULE_PROPERTIES
05564 }; /* }}} */
05565 
05566 /*
05567  * Local variables:
05568  * tab-width: 4
05569  * c-basic-offset: 4
05570  * indent-tabs-mode: t
05571  * End:
05572  * vim600: noet sw=4 ts=4 fdm=marker
05573  */