2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 | Andrei Zmievski <andrei@php.net> |
18 +----------------------------------------------------------------------+
24 #include "zend_execute.h"
26 #include "zend_modules.h"
27 #include "zend_constants.h"
28 #include "zend_exceptions.h"
29 #include "zend_closures.h"
35 /* these variables are true statics/globals, and have to be mutex'ed on every access */
36 ZEND_API HashTable module_registry
;
38 static zend_module_entry
**module_request_startup_handlers
;
39 static zend_module_entry
**module_request_shutdown_handlers
;
40 static zend_module_entry
**module_post_deactivate_handlers
;
42 static zend_class_entry
**class_cleanup_handlers
;
44 /* this function doesn't check for too many parameters */
45 ZEND_API
int zend_get_parameters(int ht
, int param_count
, ...) /* {{{ */
50 zval
**param
, *param_ptr
;
53 p
= zend_vm_stack_top(TSRMLS_C
) - 1;
54 arg_count
= (int)(zend_uintptr_t
) *p
;
56 if (param_count
>arg_count
) {
60 va_start(ptr
, param_count
);
62 while (param_count
-->0) {
63 param
= va_arg(ptr
, zval
**);
64 param_ptr
= *(p
-arg_count
);
65 if (!PZVAL_IS_REF(param_ptr
) && Z_REFCOUNT_P(param_ptr
) > 1) {
69 *new_tmp
= *param_ptr
;
70 zval_copy_ctor(new_tmp
);
73 Z_DELREF_P((zval
*) *(p
-arg_count
));
74 *(p
-arg_count
) = param_ptr
;
85 ZEND_API
int _zend_get_parameters_array(int ht
, int param_count
, zval
**argument_array TSRMLS_DC
) /* {{{ */
91 p
= zend_vm_stack_top(TSRMLS_C
) - 1;
92 arg_count
= (int)(zend_uintptr_t
) *p
;
94 if (param_count
>arg_count
) {
98 while (param_count
-->0) {
99 param_ptr
= *(p
-arg_count
);
100 if (!PZVAL_IS_REF(param_ptr
) && Z_REFCOUNT_P(param_ptr
) > 1) {
104 *new_tmp
= *param_ptr
;
105 zval_copy_ctor(new_tmp
);
108 Z_DELREF_P((zval
*) *(p
-arg_count
));
109 *(p
-arg_count
) = param_ptr
;
111 *(argument_array
++) = param_ptr
;
119 /* Zend-optimized Extended functions */
120 /* this function doesn't check for too many parameters */
121 ZEND_API
int zend_get_parameters_ex(int param_count
, ...) /* {{{ */
129 p
= zend_vm_stack_top(TSRMLS_C
) - 1;
130 arg_count
= (int)(zend_uintptr_t
) *p
;
132 if (param_count
>arg_count
) {
136 va_start(ptr
, param_count
);
137 while (param_count
-->0) {
138 param
= va_arg(ptr
, zval
***);
139 *param
= (zval
**) p
-(arg_count
--);
147 ZEND_API
int _zend_get_parameters_array_ex(int param_count
, zval
***argument_array TSRMLS_DC
) /* {{{ */
152 p
= zend_vm_stack_top(TSRMLS_C
) - 1;
153 arg_count
= (int)(zend_uintptr_t
) *p
;
155 if (param_count
>arg_count
) {
159 while (param_count
-->0) {
160 zval
**value
= (zval
**)(p
-arg_count
);
162 *(argument_array
++) = value
;
170 ZEND_API
int zend_copy_parameters_array(int param_count
, zval
*argument_array TSRMLS_DC
) /* {{{ */
175 p
= zend_vm_stack_top(TSRMLS_C
) - 1;
176 arg_count
= (int)(zend_uintptr_t
) *p
;
178 if (param_count
>arg_count
) {
182 while (param_count
-->0) {
183 zval
**param
= (zval
**) p
-(arg_count
--);
185 add_next_index_zval(argument_array
, *param
);
192 ZEND_API
void zend_wrong_param_count(TSRMLS_D
) /* {{{ */
195 const char *class_name
= get_active_class_name(&space TSRMLS_CC
);
197 zend_error(E_WARNING
, "Wrong parameter count for %s%s%s()", class_name
, space
, get_active_function_name(TSRMLS_C
));
201 /* Argument parsing API -- andrei */
202 ZEND_API
char *zend_get_type_by_const(int type
) /* {{{ */
229 ZEND_API
char *zend_zval_type_name(const zval
*arg
) /* {{{ */
231 return zend_get_type_by_const(Z_TYPE_P(arg
));
235 ZEND_API zend_class_entry
*zend_get_class_entry(const zval
*zobject TSRMLS_DC
) /* {{{ */
237 if (Z_OBJ_HT_P(zobject
)->get_class_entry
) {
238 return Z_OBJ_HT_P(zobject
)->get_class_entry(zobject TSRMLS_CC
);
240 zend_error(E_ERROR
, "Class entry requested for an object without PHP class");
246 /* returns 1 if you need to copy result, 0 if it's already a copy */
247 ZEND_API
int zend_get_object_classname(const zval
*object
, const char **class_name
, zend_uint
*class_name_len TSRMLS_DC
) /* {{{ */
249 if (Z_OBJ_HT_P(object
)->get_class_name
== NULL
||
250 Z_OBJ_HT_P(object
)->get_class_name(object
, class_name
, class_name_len
, 0 TSRMLS_CC
) != SUCCESS
) {
251 zend_class_entry
*ce
= Z_OBJCE_P(object
);
253 *class_name
= ce
->name
;
254 *class_name_len
= ce
->name_length
;
261 static int parse_arg_object_to_string(zval
**arg
, char **p
, int *pl
, int type TSRMLS_DC
) /* {{{ */
263 if (Z_OBJ_HANDLER_PP(arg
, cast_object
)) {
266 if (Z_OBJ_HANDLER_P(*arg
, cast_object
)(*arg
, obj
, type TSRMLS_CC
) == SUCCESS
) {
269 *pl
= Z_STRLEN_PP(arg
);
270 *p
= Z_STRVAL_PP(arg
);
275 /* Standard PHP objects */
276 if (Z_OBJ_HT_PP(arg
) == &std_object_handlers
|| !Z_OBJ_HANDLER_PP(arg
, cast_object
)) {
277 SEPARATE_ZVAL_IF_NOT_REF(arg
);
278 if (zend_std_cast_object_tostring(*arg
, *arg
, type TSRMLS_CC
) == SUCCESS
) {
279 *pl
= Z_STRLEN_PP(arg
);
280 *p
= Z_STRVAL_PP(arg
);
284 if (!Z_OBJ_HANDLER_PP(arg
, cast_object
) && Z_OBJ_HANDLER_PP(arg
, get
)) {
286 zval
*z
= Z_OBJ_HANDLER_PP(arg
, get
)(*arg TSRMLS_CC
);
288 if(Z_TYPE_P(z
) != IS_OBJECT
) {
290 Z_TYPE_P(*arg
) = IS_NULL
;
291 zend_make_printable_zval(z
, *arg
, &use_copy
);
293 ZVAL_ZVAL(*arg
, z
, 1, 1);
295 *pl
= Z_STRLEN_PP(arg
);
296 *p
= Z_STRVAL_PP(arg
);
305 static const char *zend_parse_arg_impl(int arg_num
, zval
**arg
, va_list *va
, const char **spec
, char **error
, int *severity TSRMLS_DC
) /* {{{ */
307 const char *spec_walk
= *spec
;
308 char c
= *spec_walk
++;
311 /* scan through modifiers */
313 if (*spec_walk
== '/') {
314 SEPARATE_ZVAL_IF_NOT_REF(arg
);
315 } else if (*spec_walk
== '!') {
316 if (Z_TYPE_PP(arg
) == IS_NULL
) {
329 long *p
= va_arg(*va
, long *);
330 switch (Z_TYPE_PP(arg
)) {
336 if ((type
= is_numeric_string(Z_STRVAL_PP(arg
), Z_STRLEN_PP(arg
), p
, &d
, -1)) == 0) {
338 } else if (type
== IS_DOUBLE
) {
343 } else if (d
< LONG_MIN
) {
349 *p
= zend_dval_to_lval(d
);
356 if (Z_DVAL_PP(arg
) > LONG_MAX
) {
359 } else if (Z_DVAL_PP(arg
) < LONG_MIN
) {
367 convert_to_long_ex(arg
);
382 double *p
= va_arg(*va
, double *);
383 switch (Z_TYPE_PP(arg
)) {
389 if ((type
= is_numeric_string(Z_STRVAL_PP(arg
), Z_STRLEN_PP(arg
), &l
, p
, -1)) == 0) {
391 } else if (type
== IS_LONG
) {
401 convert_to_double_ex(arg
);
417 char **p
= va_arg(*va
, char **);
418 int *pl
= va_arg(*va
, int *);
419 switch (Z_TYPE_PP(arg
)) {
426 /* break omitted intentionally */
432 convert_to_string_ex(arg
);
433 if (UNEXPECTED(Z_ISREF_PP(arg
) != 0)) {
434 /* it's dangerous to return pointers to string
435 buffer of referenced variable, because it can
436 be clobbered throug magic callbacks */
439 *p
= Z_STRVAL_PP(arg
);
440 *pl
= Z_STRLEN_PP(arg
);
441 if (c
== 'p' && CHECK_ZVAL_NULL_PATH(*arg
)) {
442 return "a valid path";
447 if (parse_arg_object_to_string(arg
, p
, pl
, IS_STRING TSRMLS_CC
) == SUCCESS
) {
448 if (c
== 'p' && CHECK_ZVAL_NULL_PATH(*arg
)) {
449 return "a valid path";
457 return c
== 's' ? "string" : "a valid path";
464 zend_bool
*p
= va_arg(*va
, zend_bool
*);
465 switch (Z_TYPE_PP(arg
)) {
471 convert_to_boolean_ex(arg
);
486 zval
**p
= va_arg(*va
, zval
**);
491 if (Z_TYPE_PP(arg
) == IS_RESOURCE
) {
501 zval
**p
= va_arg(*va
, zval
**);
506 if (Z_TYPE_PP(arg
) == IS_ARRAY
|| (c
== 'A' && Z_TYPE_PP(arg
) == IS_OBJECT
)) {
516 HashTable
**p
= va_arg(*va
, HashTable
**);
521 if (Z_TYPE_PP(arg
) == IS_ARRAY
) {
522 *p
= Z_ARRVAL_PP(arg
);
523 } else if(c
== 'H' && Z_TYPE_PP(arg
) == IS_OBJECT
) {
536 zval
**p
= va_arg(*va
, zval
**);
541 if (Z_TYPE_PP(arg
) == IS_OBJECT
) {
551 zval
**p
= va_arg(*va
, zval
**);
552 zend_class_entry
*ce
= va_arg(*va
, zend_class_entry
*);
558 if (Z_TYPE_PP(arg
) == IS_OBJECT
&&
559 (!ce
|| instanceof_function(Z_OBJCE_PP(arg
), ce TSRMLS_CC
))) {
573 zend_class_entry
**lookup
, **pce
= va_arg(*va
, zend_class_entry
**);
574 zend_class_entry
*ce_base
= *pce
;
580 convert_to_string_ex(arg
);
581 if (zend_lookup_class(Z_STRVAL_PP(arg
), Z_STRLEN_PP(arg
), &lookup TSRMLS_CC
) == FAILURE
) {
587 if ((!*pce
|| !instanceof_function(*pce
, ce_base TSRMLS_CC
))) {
588 zend_spprintf(error
, 0, "to be a class name derived from %s, '%s' given",
589 ce_base
->name
, Z_STRVAL_PP(arg
));
595 zend_spprintf(error
, 0, "to be a valid class name, '%s' given",
606 zend_fcall_info
*fci
= va_arg(*va
, zend_fcall_info
*);
607 zend_fcall_info_cache
*fcc
= va_arg(*va
, zend_fcall_info_cache
*);
608 char *is_callable_error
= NULL
;
612 fcc
->initialized
= 0;
616 if (zend_fcall_info_init(*arg
, 0, fci
, fcc
, NULL
, &is_callable_error TSRMLS_CC
) == SUCCESS
) {
617 if (is_callable_error
) {
618 *severity
= E_STRICT
;
619 zend_spprintf(error
, 0, "to be a valid callback, %s", is_callable_error
);
620 efree(is_callable_error
);
626 if (is_callable_error
) {
627 *severity
= E_WARNING
;
628 zend_spprintf(error
, 0, "to be a valid callback, %s", is_callable_error
);
629 efree(is_callable_error
);
632 return "valid callback";
639 zval
**p
= va_arg(*va
, zval
**);
650 zval
***p
= va_arg(*va
, zval
***);
669 static int zend_parse_arg(int arg_num
, zval
**arg
, va_list *va
, const char **spec
, int quiet TSRMLS_DC
) /* {{{ */
671 const char *expected_type
= NULL
;
673 int severity
= E_WARNING
;
675 expected_type
= zend_parse_arg_impl(arg_num
, arg
, va
, spec
, &error
, &severity TSRMLS_CC
);
677 if (!quiet
&& (*expected_type
|| error
)) {
679 const char *class_name
= get_active_class_name(&space TSRMLS_CC
);
682 zend_error(severity
, "%s%s%s() expects parameter %d %s",
683 class_name
, space
, get_active_function_name(TSRMLS_C
), arg_num
, error
);
686 zend_error(severity
, "%s%s%s() expects parameter %d to be %s, %s given",
687 class_name
, space
, get_active_function_name(TSRMLS_C
), arg_num
, expected_type
,
688 zend_zval_type_name(*arg
));
691 if (severity
!= E_STRICT
) {
700 static int zend_parse_va_args(int num_args
, const char *type_spec
, va_list *va
, int flags TSRMLS_DC
) /* {{{ */
702 const char *spec_walk
;
704 int min_num_args
= -1;
705 int max_num_args
= 0;
706 int post_varargs
= 0;
709 int quiet
= flags
& ZEND_PARSE_PARAMS_QUIET
;
710 zend_bool have_varargs
= 0;
711 zval
****varargs
= NULL
;
712 int *n_varargs
= NULL
;
714 for (spec_walk
= type_spec
; *spec_walk
; spec_walk
++) {
729 min_num_args
= max_num_args
;
741 zend_function
*active_function
= EG(current_execute_data
)->function_state
.function
;
742 const char *class_name
= active_function
->common
.scope
? active_function
->common
.scope
->name
: "";
743 zend_error(E_WARNING
, "%s%s%s(): only one varargs specifier (* or +) is permitted",
745 class_name
[0] ? "::" : "",
746 active_function
->common
.function_name
);
751 /* we expect at least one parameter in varargs */
755 /* mark the beginning of varargs */
756 post_varargs
= max_num_args
;
761 zend_function
*active_function
= EG(current_execute_data
)->function_state
.function
;
762 const char *class_name
= active_function
->common
.scope
? active_function
->common
.scope
->name
: "";
763 zend_error(E_WARNING
, "%s%s%s(): bad type specifier while parsing parameters",
765 class_name
[0] ? "::" : "",
766 active_function
->common
.function_name
);
772 if (min_num_args
< 0) {
773 min_num_args
= max_num_args
;
777 /* calculate how many required args are at the end of the specifier list */
778 post_varargs
= max_num_args
- post_varargs
;
782 if (num_args
< min_num_args
|| (num_args
> max_num_args
&& max_num_args
> 0)) {
784 zend_function
*active_function
= EG(current_execute_data
)->function_state
.function
;
785 const char *class_name
= active_function
->common
.scope
? active_function
->common
.scope
->name
: "";
786 zend_error(E_WARNING
, "%s%s%s() expects %s %d parameter%s, %d given",
788 class_name
[0] ? "::" : "",
789 active_function
->common
.function_name
,
790 min_num_args
== max_num_args
? "exactly" : num_args
< min_num_args
? "at least" : "at most",
791 num_args
< min_num_args
? min_num_args
: max_num_args
,
792 (num_args
< min_num_args
? min_num_args
: max_num_args
) == 1 ? "" : "s",
798 arg_count
= (int)(zend_uintptr_t
) *(zend_vm_stack_top(TSRMLS_C
) - 1);
800 if (num_args
> arg_count
) {
801 zend_error(E_WARNING
, "%s(): could not obtain parameters for parsing",
802 get_active_function_name(TSRMLS_C
));
807 while (num_args
-- > 0) {
808 if (*type_spec
== '|') {
812 if (*type_spec
== '*' || *type_spec
== '+') {
813 int num_varargs
= num_args
+ 1 - post_varargs
;
815 /* eat up the passed in storage even if it won't be filled in with varargs */
816 varargs
= va_arg(*va
, zval
****);
817 n_varargs
= va_arg(*va
, int *);
820 if (num_varargs
> 0) {
822 zval
**p
= (zval
**) (zend_vm_stack_top(TSRMLS_C
) - 1 - (arg_count
- i
));
824 *n_varargs
= num_varargs
;
826 /* allocate space for array and store args */
827 *varargs
= safe_emalloc(num_varargs
, sizeof(zval
**), 0);
828 while (num_varargs
-- > 0) {
829 (*varargs
)[iv
++] = p
++;
832 /* adjust how many args we have left and restart loop */
833 num_args
= num_args
+ 1 - iv
;
842 arg
= (zval
**) (zend_vm_stack_top(TSRMLS_C
) - 1 - (arg_count
-i
));
844 if (zend_parse_arg(i
+1, arg
, va
, &type_spec
, quiet TSRMLS_CC
) == FAILURE
) {
845 /* clean up varargs array if it was used */
846 if (varargs
&& *varargs
) {
859 #define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \
860 int __num_args = (num_args); \
862 if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
863 const char *__space; \
864 const char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
865 zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
866 __class_name, __space, \
867 get_active_function_name(TSRMLS_C), __num_args); \
872 ZEND_API
int zend_parse_parameters_ex(int flags
, int num_args TSRMLS_DC
, const char *type_spec
, ...) /* {{{ */
877 RETURN_IF_ZERO_ARGS(num_args
, type_spec
, flags
& ZEND_PARSE_PARAMS_QUIET
);
879 va_start(va
, type_spec
);
880 retval
= zend_parse_va_args(num_args
, type_spec
, &va
, flags TSRMLS_CC
);
887 ZEND_API
int zend_parse_parameters(int num_args TSRMLS_DC
, const char *type_spec
, ...) /* {{{ */
892 RETURN_IF_ZERO_ARGS(num_args
, type_spec
, 0);
894 va_start(va
, type_spec
);
895 retval
= zend_parse_va_args(num_args
, type_spec
, &va
, 0 TSRMLS_CC
);
902 ZEND_API
int zend_parse_method_parameters(int num_args TSRMLS_DC
, zval
*this_ptr
, const char *type_spec
, ...) /* {{{ */
906 const char *p
= type_spec
;
908 zend_class_entry
*ce
;
911 RETURN_IF_ZERO_ARGS(num_args
, p
, 0);
913 va_start(va
, type_spec
);
914 retval
= zend_parse_va_args(num_args
, type_spec
, &va
, 0 TSRMLS_CC
);
918 RETURN_IF_ZERO_ARGS(num_args
, p
, 0);
920 va_start(va
, type_spec
);
922 object
= va_arg(va
, zval
**);
923 ce
= va_arg(va
, zend_class_entry
*);
926 if (ce
&& !instanceof_function(Z_OBJCE_P(this_ptr
), ce TSRMLS_CC
)) {
927 zend_error(E_CORE_ERROR
, "%s::%s() must be derived from %s::%s",
928 ce
->name
, get_active_function_name(TSRMLS_C
), Z_OBJCE_P(this_ptr
)->name
, get_active_function_name(TSRMLS_C
));
931 retval
= zend_parse_va_args(num_args
, p
, &va
, 0 TSRMLS_CC
);
938 ZEND_API
int zend_parse_method_parameters_ex(int flags
, int num_args TSRMLS_DC
, zval
*this_ptr
, const char *type_spec
, ...) /* {{{ */
942 const char *p
= type_spec
;
944 zend_class_entry
*ce
;
945 int quiet
= flags
& ZEND_PARSE_PARAMS_QUIET
;
948 RETURN_IF_ZERO_ARGS(num_args
, p
, quiet
);
950 va_start(va
, type_spec
);
951 retval
= zend_parse_va_args(num_args
, type_spec
, &va
, flags TSRMLS_CC
);
955 RETURN_IF_ZERO_ARGS(num_args
, p
, quiet
);
957 va_start(va
, type_spec
);
959 object
= va_arg(va
, zval
**);
960 ce
= va_arg(va
, zend_class_entry
*);
963 if (ce
&& !instanceof_function(Z_OBJCE_P(this_ptr
), ce TSRMLS_CC
)) {
965 zend_error(E_CORE_ERROR
, "%s::%s() must be derived from %s::%s",
966 ce
->name
, get_active_function_name(TSRMLS_C
), Z_OBJCE_P(this_ptr
)->name
, get_active_function_name(TSRMLS_C
));
972 retval
= zend_parse_va_args(num_args
, p
, &va
, flags TSRMLS_CC
);
979 /* Argument parsing API -- andrei */
980 ZEND_API
int _array_init(zval
*arg
, uint size ZEND_FILE_LINE_DC
) /* {{{ */
982 ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg
));
984 _zend_hash_init(Z_ARRVAL_P(arg
), size
, NULL
, ZVAL_PTR_DTOR
, 0 ZEND_FILE_LINE_RELAY_CC
);
985 Z_TYPE_P(arg
) = IS_ARRAY
;
990 static int zend_merge_property(zval
**value TSRMLS_DC
, int num_args
, va_list args
, const zend_hash_key
*hash_key
) /* {{{ */
992 /* which name should a numeric property have ? */
993 if (hash_key
->nKeyLength
) {
994 zval
*obj
= va_arg(args
, zval
*);
995 zend_object_handlers
*obj_ht
= va_arg(args
, zend_object_handlers
*);
998 MAKE_STD_ZVAL(member
);
999 ZVAL_STRINGL(member
, hash_key
->arKey
, hash_key
->nKeyLength
-1, 1);
1000 obj_ht
->write_property(obj
, member
, *value
, 0 TSRMLS_CC
);
1001 zval_ptr_dtor(&member
);
1003 return ZEND_HASH_APPLY_KEEP
;
1007 /* This function should be called after the constructor has been called
1008 * because it may call __set from the uninitialized object otherwise. */
1009 ZEND_API
void zend_merge_properties(zval
*obj
, HashTable
*properties
, int destroy_ht TSRMLS_DC
) /* {{{ */
1011 const zend_object_handlers
*obj_ht
= Z_OBJ_HT_P(obj
);
1012 zend_class_entry
*old_scope
= EG(scope
);
1014 EG(scope
) = Z_OBJCE_P(obj
);
1015 zend_hash_apply_with_arguments(properties TSRMLS_CC
, (apply_func_args_t
)zend_merge_property
, 2, obj
, obj_ht
);
1016 EG(scope
) = old_scope
;
1019 zend_hash_destroy(properties
);
1020 FREE_HASHTABLE(properties
);
1025 static int zval_update_class_constant(zval
**pp
, int is_static
, int offset TSRMLS_DC
) /* {{{ */
1027 if ((Z_TYPE_PP(pp
) & IS_CONSTANT_TYPE_MASK
) == IS_CONSTANT
||
1028 (Z_TYPE_PP(pp
) & IS_CONSTANT_TYPE_MASK
) == IS_CONSTANT_ARRAY
) {
1029 zend_class_entry
**scope
= EG(in_execution
)?&EG(scope
):&CG(active_class_entry
);
1031 if ((*scope
)->parent
) {
1032 zend_class_entry
*ce
= *scope
;
1034 zend_property_info
*prop_info
;
1037 for (zend_hash_internal_pointer_reset_ex(&ce
->properties_info
, &pos
);
1038 zend_hash_get_current_data_ex(&ce
->properties_info
, (void **) &prop_info
, &pos
) == SUCCESS
;
1039 zend_hash_move_forward_ex(&ce
->properties_info
, &pos
)) {
1040 if (is_static
== ((prop_info
->flags
& ZEND_ACC_STATIC
) != 0) &&
1041 offset
== prop_info
->offset
) {
1043 zend_class_entry
*old_scope
= *scope
;
1044 *scope
= prop_info
->ce
;
1045 ret
= zval_update_constant(pp
, (void*)1 TSRMLS_CC
);
1054 return zval_update_constant(pp
, (void*)1 TSRMLS_CC
);
1060 ZEND_API
void zend_update_class_constants(zend_class_entry
*class_type TSRMLS_DC
) /* {{{ */
1062 if ((class_type
->ce_flags
& ZEND_ACC_CONSTANTS_UPDATED
) == 0 || (!CE_STATIC_MEMBERS(class_type
) && class_type
->default_static_members_count
)) {
1063 zend_class_entry
**scope
= EG(in_execution
)?&EG(scope
):&CG(active_class_entry
);
1064 zend_class_entry
*old_scope
= *scope
;
1067 *scope
= class_type
;
1068 zend_hash_apply_with_argument(&class_type
->constants_table
, (apply_func_arg_t
) zval_update_constant
, (void*)1 TSRMLS_CC
);
1070 for (i
= 0; i
< class_type
->default_properties_count
; i
++) {
1071 if (class_type
->default_properties_table
[i
]) {
1072 zval_update_class_constant(&class_type
->default_properties_table
[i
], 0, i TSRMLS_CC
);
1076 if (!CE_STATIC_MEMBERS(class_type
) && class_type
->default_static_members_count
) {
1079 if (class_type
->parent
) {
1080 zend_update_class_constants(class_type
->parent TSRMLS_CC
);
1083 CG(static_members_table
)[(zend_intptr_t
)(class_type
->static_members_table
)] = emalloc(sizeof(zval
*) * class_type
->default_static_members_count
);
1085 class_type
->static_members_table
= emalloc(sizeof(zval
*) * class_type
->default_static_members_count
);
1087 for (i
= 0; i
< class_type
->default_static_members_count
; i
++) {
1088 p
= &class_type
->default_static_members_table
[i
];
1089 if (Z_ISREF_PP(p
) &&
1090 class_type
->parent
&&
1091 i
< class_type
->parent
->default_static_members_count
&&
1092 *p
== class_type
->parent
->default_static_members_table
[i
] &&
1093 CE_STATIC_MEMBERS(class_type
->parent
)[i
]
1095 zval
*q
= CE_STATIC_MEMBERS(class_type
->parent
)[i
];
1099 CE_STATIC_MEMBERS(class_type
)[i
] = q
;
1107 CE_STATIC_MEMBERS(class_type
)[i
] = r
;
1112 for (i
= 0; i
< class_type
->default_static_members_count
; i
++) {
1113 zval_update_class_constant(&CE_STATIC_MEMBERS(class_type
)[i
], 1, i TSRMLS_CC
);
1117 class_type
->ce_flags
|= ZEND_ACC_CONSTANTS_UPDATED
;
1122 ZEND_API
void object_properties_init(zend_object
*object
, zend_class_entry
*class_type
) /* {{{ */
1126 if (class_type
->default_properties_count
) {
1127 object
->properties_table
= emalloc(sizeof(zval
*) * class_type
->default_properties_count
);
1128 for (i
= 0; i
< class_type
->default_properties_count
; i
++) {
1129 object
->properties_table
[i
] = class_type
->default_properties_table
[i
];
1130 if (class_type
->default_properties_table
[i
]) {
1132 ALLOC_ZVAL( object
->properties_table
[i
]);
1133 MAKE_COPY_ZVAL(&class_type
->default_properties_table
[i
], object
->properties_table
[i
]);
1135 Z_ADDREF_P(object
->properties_table
[i
]);
1139 object
->properties
= NULL
;
1144 /* This function requires 'properties' to contain all props declared in the
1145 * class and all props being public. If only a subset is given or the class
1146 * has protected members then you need to merge the properties seperately by
1147 * calling zend_merge_properties(). */
1148 ZEND_API
int _object_and_properties_init(zval
*arg
, zend_class_entry
*class_type
, HashTable
*properties ZEND_FILE_LINE_DC TSRMLS_DC
) /* {{{ */
1150 zend_object
*object
;
1152 if (class_type
->ce_flags
& (ZEND_ACC_INTERFACE
|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS
|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
)) {
1153 char *what
= (class_type
->ce_flags
& ZEND_ACC_INTERFACE
) ? "interface"
1154 :((class_type
->ce_flags
& ZEND_ACC_TRAIT
) == ZEND_ACC_TRAIT
) ? "trait"
1156 zend_error(E_ERROR
, "Cannot instantiate %s %s", what
, class_type
->name
);
1159 zend_update_class_constants(class_type TSRMLS_CC
);
1161 Z_TYPE_P(arg
) = IS_OBJECT
;
1162 if (class_type
->create_object
== NULL
) {
1163 Z_OBJVAL_P(arg
) = zend_objects_new(&object
, class_type TSRMLS_CC
);
1165 object
->properties
= properties
;
1166 object
->properties_table
= NULL
;
1168 object_properties_init(object
, class_type
);
1171 Z_OBJVAL_P(arg
) = class_type
->create_object(class_type TSRMLS_CC
);
1177 ZEND_API
int _object_init_ex(zval
*arg
, zend_class_entry
*class_type ZEND_FILE_LINE_DC TSRMLS_DC
) /* {{{ */
1179 return _object_and_properties_init(arg
, class_type
, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC
);
1183 ZEND_API
int _object_init(zval
*arg ZEND_FILE_LINE_DC TSRMLS_DC
) /* {{{ */
1185 return _object_init_ex(arg
, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC
);
1189 ZEND_API
int add_assoc_function(zval
*arg
, const char *key
, void (*function_ptr
)(INTERNAL_FUNCTION_PARAMETERS
)) /* {{{ */
1191 zend_error(E_WARNING
, "add_assoc_function() is no longer supported");
1196 ZEND_API
int add_assoc_long_ex(zval
*arg
, const char *key
, uint key_len
, long n
) /* {{{ */
1203 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1207 ZEND_API
int add_assoc_null_ex(zval
*arg
, const char *key
, uint key_len
) /* {{{ */
1214 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1218 ZEND_API
int add_assoc_bool_ex(zval
*arg
, const char *key
, uint key_len
, int b
) /* {{{ */
1225 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1229 ZEND_API
int add_assoc_resource_ex(zval
*arg
, const char *key
, uint key_len
, int r
) /* {{{ */
1234 ZVAL_RESOURCE(tmp
, r
);
1236 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1240 ZEND_API
int add_assoc_double_ex(zval
*arg
, const char *key
, uint key_len
, double d
) /* {{{ */
1245 ZVAL_DOUBLE(tmp
, d
);
1247 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1251 ZEND_API
int add_assoc_string_ex(zval
*arg
, const char *key
, uint key_len
, char *str
, int duplicate
) /* {{{ */
1256 ZVAL_STRING(tmp
, str
, duplicate
);
1258 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1262 ZEND_API
int add_assoc_stringl_ex(zval
*arg
, const char *key
, uint key_len
, char *str
, uint length
, int duplicate
) /* {{{ */
1267 ZVAL_STRINGL(tmp
, str
, length
, duplicate
);
1269 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), NULL
);
1273 ZEND_API
int add_assoc_zval_ex(zval
*arg
, const char *key
, uint key_len
, zval
*value
) /* {{{ */
1275 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &value
, sizeof(zval
*), NULL
);
1279 ZEND_API
int add_index_long(zval
*arg
, ulong index
, long n
) /* {{{ */
1286 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1290 ZEND_API
int add_index_null(zval
*arg
, ulong index
) /* {{{ */
1297 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1301 ZEND_API
int add_index_bool(zval
*arg
, ulong index
, int b
) /* {{{ */
1308 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1312 ZEND_API
int add_index_resource(zval
*arg
, ulong index
, int r
) /* {{{ */
1317 ZVAL_RESOURCE(tmp
, r
);
1319 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1323 ZEND_API
int add_index_double(zval
*arg
, ulong index
, double d
) /* {{{ */
1328 ZVAL_DOUBLE(tmp
, d
);
1330 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1334 ZEND_API
int add_index_string(zval
*arg
, ulong index
, const char *str
, int duplicate
) /* {{{ */
1339 ZVAL_STRING(tmp
, str
, duplicate
);
1341 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1345 ZEND_API
int add_index_stringl(zval
*arg
, ulong index
, const char *str
, uint length
, int duplicate
) /* {{{ */
1350 ZVAL_STRINGL(tmp
, str
, length
, duplicate
);
1352 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), NULL
);
1356 ZEND_API
int add_index_zval(zval
*arg
, ulong index
, zval
*value
) /* {{{ */
1358 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &value
, sizeof(zval
*), NULL
);
1362 ZEND_API
int add_next_index_long(zval
*arg
, long n
) /* {{{ */
1369 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1373 ZEND_API
int add_next_index_null(zval
*arg
) /* {{{ */
1380 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1384 ZEND_API
int add_next_index_bool(zval
*arg
, int b
) /* {{{ */
1391 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1395 ZEND_API
int add_next_index_resource(zval
*arg
, int r
) /* {{{ */
1400 ZVAL_RESOURCE(tmp
, r
);
1402 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1406 ZEND_API
int add_next_index_double(zval
*arg
, double d
) /* {{{ */
1411 ZVAL_DOUBLE(tmp
, d
);
1413 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1417 ZEND_API
int add_next_index_string(zval
*arg
, const char *str
, int duplicate
) /* {{{ */
1422 ZVAL_STRING(tmp
, str
, duplicate
);
1424 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1428 ZEND_API
int add_next_index_stringl(zval
*arg
, const char *str
, uint length
, int duplicate
) /* {{{ */
1433 ZVAL_STRINGL(tmp
, str
, length
, duplicate
);
1435 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &tmp
, sizeof(zval
*), NULL
);
1439 ZEND_API
int add_next_index_zval(zval
*arg
, zval
*value
) /* {{{ */
1441 return zend_hash_next_index_insert(Z_ARRVAL_P(arg
), &value
, sizeof(zval
*), NULL
);
1445 ZEND_API
int add_get_assoc_string_ex(zval
*arg
, const char *key
, uint key_len
, const char *str
, void **dest
, int duplicate
) /* {{{ */
1450 ZVAL_STRING(tmp
, str
, duplicate
);
1452 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), dest
);
1456 ZEND_API
int add_get_assoc_stringl_ex(zval
*arg
, const char *key
, uint key_len
, const char *str
, uint length
, void **dest
, int duplicate
) /* {{{ */
1461 ZVAL_STRINGL(tmp
, str
, length
, duplicate
);
1463 return zend_symtable_update(Z_ARRVAL_P(arg
), key
, key_len
, (void *) &tmp
, sizeof(zval
*), dest
);
1467 ZEND_API
int add_get_index_long(zval
*arg
, ulong index
, long l
, void **dest
) /* {{{ */
1474 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), dest
);
1478 ZEND_API
int add_get_index_double(zval
*arg
, ulong index
, double d
, void **dest
) /* {{{ */
1483 ZVAL_DOUBLE(tmp
, d
);
1485 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), dest
);
1489 ZEND_API
int add_get_index_string(zval
*arg
, ulong index
, const char *str
, void **dest
, int duplicate
) /* {{{ */
1494 ZVAL_STRING(tmp
, str
, duplicate
);
1496 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), dest
);
1500 ZEND_API
int add_get_index_stringl(zval
*arg
, ulong index
, const char *str
, uint length
, void **dest
, int duplicate
) /* {{{ */
1505 ZVAL_STRINGL(tmp
, str
, length
, duplicate
);
1507 return zend_hash_index_update(Z_ARRVAL_P(arg
), index
, (void *) &tmp
, sizeof(zval
*), dest
);
1511 ZEND_API
int add_property_long_ex(zval
*arg
, const char *key
, uint key_len
, long n TSRMLS_DC
) /* {{{ */
1519 MAKE_STD_ZVAL(z_key
);
1520 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1522 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1523 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1524 zval_ptr_dtor(&z_key
);
1529 ZEND_API
int add_property_bool_ex(zval
*arg
, const char *key
, uint key_len
, int b TSRMLS_DC
) /* {{{ */
1537 MAKE_STD_ZVAL(z_key
);
1538 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1540 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1541 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1542 zval_ptr_dtor(&z_key
);
1547 ZEND_API
int add_property_null_ex(zval
*arg
, const char *key
, uint key_len TSRMLS_DC
) /* {{{ */
1555 MAKE_STD_ZVAL(z_key
);
1556 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1558 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1559 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1560 zval_ptr_dtor(&z_key
);
1565 ZEND_API
int add_property_resource_ex(zval
*arg
, const char *key
, uint key_len
, long n TSRMLS_DC
) /* {{{ */
1571 ZVAL_RESOURCE(tmp
, n
);
1573 MAKE_STD_ZVAL(z_key
);
1574 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1576 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1577 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1578 zval_ptr_dtor(&z_key
);
1583 ZEND_API
int add_property_double_ex(zval
*arg
, const char *key
, uint key_len
, double d TSRMLS_DC
) /* {{{ */
1589 ZVAL_DOUBLE(tmp
, d
);
1591 MAKE_STD_ZVAL(z_key
);
1592 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1594 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1595 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1596 zval_ptr_dtor(&z_key
);
1601 ZEND_API
int add_property_string_ex(zval
*arg
, const char *key
, uint key_len
, const char *str
, int duplicate TSRMLS_DC
) /* {{{ */
1607 ZVAL_STRING(tmp
, str
, duplicate
);
1609 MAKE_STD_ZVAL(z_key
);
1610 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1612 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1613 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1614 zval_ptr_dtor(&z_key
);
1619 ZEND_API
int add_property_stringl_ex(zval
*arg
, const char *key
, uint key_len
, const char *str
, uint length
, int duplicate TSRMLS_DC
) /* {{{ */
1625 ZVAL_STRINGL(tmp
, str
, length
, duplicate
);
1627 MAKE_STD_ZVAL(z_key
);
1628 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1630 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, tmp
, 0 TSRMLS_CC
);
1631 zval_ptr_dtor(&tmp
); /* write_property will add 1 to refcount */
1632 zval_ptr_dtor(&z_key
);
1637 ZEND_API
int add_property_zval_ex(zval
*arg
, const char *key
, uint key_len
, zval
*value TSRMLS_DC
) /* {{{ */
1641 MAKE_STD_ZVAL(z_key
);
1642 ZVAL_STRINGL(z_key
, key
, key_len
-1, 1);
1644 Z_OBJ_HANDLER_P(arg
, write_property
)(arg
, z_key
, value
, 0 TSRMLS_CC
);
1645 zval_ptr_dtor(&z_key
);
1650 ZEND_API
int zend_startup_module_ex(zend_module_entry
*module TSRMLS_DC
) /* {{{ */
1655 if (module
->module_started
) {
1658 module
->module_started
= 1;
1660 /* Check module dependencies */
1662 const zend_module_dep
*dep
= module
->deps
;
1665 if (dep
->type
== MODULE_DEP_REQUIRED
) {
1666 zend_module_entry
*req_mod
;
1668 name_len
= strlen(dep
->name
);
1669 lcname
= zend_str_tolower_dup(dep
->name
, name_len
);
1671 if (zend_hash_find(&module_registry
, lcname
, name_len
+1, (void**)&req_mod
) == FAILURE
|| !req_mod
->module_started
) {
1673 /* TODO: Check version relationship */
1674 zend_error(E_CORE_WARNING
, "Cannot load module '%s' because required module '%s' is not loaded", module
->name
, dep
->name
);
1675 module
->module_started
= 0;
1684 /* Initialize module globals */
1685 if (module
->globals_size
) {
1687 ts_allocate_id(module
->globals_id_ptr
, module
->globals_size
, (ts_allocate_ctor
) module
->globals_ctor
, (ts_allocate_dtor
) module
->globals_dtor
);
1689 if (module
->globals_ctor
) {
1690 module
->globals_ctor(module
->globals_ptr TSRMLS_CC
);
1694 if (module
->module_startup_func
) {
1695 EG(current_module
) = module
;
1696 if (module
->module_startup_func(module
->type
, module
->module_number TSRMLS_CC
)==FAILURE
) {
1697 zend_error(E_CORE_ERROR
,"Unable to start %s module", module
->name
);
1698 EG(current_module
) = NULL
;
1701 EG(current_module
) = NULL
;
1707 static void zend_sort_modules(void *base
, size_t count
, size_t siz
, compare_func_t compare TSRMLS_DC
) /* {{{ */
1711 Bucket
**end
= b1
+ count
;
1713 zend_module_entry
*m
, *r
;
1717 m
= (zend_module_entry
*)(*b1
)->pData
;
1718 if (!m
->module_started
&& m
->deps
) {
1719 const zend_module_dep
*dep
= m
->deps
;
1721 if (dep
->type
== MODULE_DEP_REQUIRED
|| dep
->type
== MODULE_DEP_OPTIONAL
) {
1724 r
= (zend_module_entry
*)(*b2
)->pData
;
1725 if (strcasecmp(dep
->name
, r
->name
) == 0) {
1742 ZEND_API
void zend_collect_module_handlers(TSRMLS_D
) /* {{{ */
1745 zend_module_entry
*module
;
1746 int startup_count
= 0;
1747 int shutdown_count
= 0;
1748 int post_deactivate_count
= 0;
1749 zend_class_entry
**pce
;
1750 int class_count
= 0;
1752 /* Collect extensions with request startup/shutdown handlers */
1753 for (zend_hash_internal_pointer_reset_ex(&module_registry
, &pos
);
1754 zend_hash_get_current_data_ex(&module_registry
, (void *) &module
, &pos
) == SUCCESS
;
1755 zend_hash_move_forward_ex(&module_registry
, &pos
)) {
1756 if (module
->request_startup_func
) {
1759 if (module
->request_shutdown_func
) {
1762 if (module
->post_deactivate_func
) {
1763 post_deactivate_count
++;
1766 module_request_startup_handlers
= (zend_module_entry
**)malloc(
1767 sizeof(zend_module_entry
*) *
1768 (startup_count
+ 1 +
1769 shutdown_count
+ 1 +
1770 post_deactivate_count
+ 1));
1771 module_request_startup_handlers
[startup_count
] = NULL
;
1772 module_request_shutdown_handlers
= module_request_startup_handlers
+ startup_count
+ 1;
1773 module_request_shutdown_handlers
[shutdown_count
] = NULL
;
1774 module_post_deactivate_handlers
= module_request_shutdown_handlers
+ shutdown_count
+ 1;
1775 module_post_deactivate_handlers
[post_deactivate_count
] = NULL
;
1778 for (zend_hash_internal_pointer_reset_ex(&module_registry
, &pos
);
1779 zend_hash_get_current_data_ex(&module_registry
, (void *) &module
, &pos
) == SUCCESS
;
1780 zend_hash_move_forward_ex(&module_registry
, &pos
)) {
1781 if (module
->request_startup_func
) {
1782 module_request_startup_handlers
[startup_count
++] = module
;
1784 if (module
->request_shutdown_func
) {
1785 module_request_shutdown_handlers
[--shutdown_count
] = module
;
1787 if (module
->post_deactivate_func
) {
1788 module_post_deactivate_handlers
[--post_deactivate_count
] = module
;
1792 /* Collect internal classes with static members */
1793 for (zend_hash_internal_pointer_reset_ex(CG(class_table
), &pos
);
1794 zend_hash_get_current_data_ex(CG(class_table
), (void *) &pce
, &pos
) == SUCCESS
;
1795 zend_hash_move_forward_ex(CG(class_table
), &pos
)) {
1796 if ((*pce
)->type
== ZEND_INTERNAL_CLASS
&&
1797 (*pce
)->default_static_members_count
> 0) {
1802 class_cleanup_handlers
= (zend_class_entry
**)malloc(
1803 sizeof(zend_class_entry
*) *
1805 class_cleanup_handlers
[class_count
] = NULL
;
1808 for (zend_hash_internal_pointer_reset_ex(CG(class_table
), &pos
);
1809 zend_hash_get_current_data_ex(CG(class_table
), (void *) &pce
, &pos
) == SUCCESS
;
1810 zend_hash_move_forward_ex(CG(class_table
), &pos
)) {
1811 if ((*pce
)->type
== ZEND_INTERNAL_CLASS
&&
1812 (*pce
)->default_static_members_count
> 0) {
1813 class_cleanup_handlers
[--class_count
] = *pce
;
1820 ZEND_API
int zend_startup_modules(TSRMLS_D
) /* {{{ */
1822 zend_hash_sort(&module_registry
, zend_sort_modules
, NULL
, 0 TSRMLS_CC
);
1823 zend_hash_apply(&module_registry
, (apply_func_t
)zend_startup_module_ex TSRMLS_CC
);
1828 ZEND_API
void zend_destroy_modules(void) /* {{{ */
1830 free(class_cleanup_handlers
);
1831 free(module_request_startup_handlers
);
1832 zend_hash_graceful_reverse_destroy(&module_registry
);
1836 ZEND_API zend_module_entry
* zend_register_module_ex(zend_module_entry
*module TSRMLS_DC
) /* {{{ */
1840 zend_module_entry
*module_ptr
;
1847 zend_printf("%s: Registering module %d\n", module
->name
, module
->module_number
);
1850 /* Check module dependencies */
1852 const zend_module_dep
*dep
= module
->deps
;
1855 if (dep
->type
== MODULE_DEP_CONFLICTS
) {
1856 name_len
= strlen(dep
->name
);
1857 lcname
= zend_str_tolower_dup(dep
->name
, name_len
);
1859 if (zend_hash_exists(&module_registry
, lcname
, name_len
+1)) {
1861 /* TODO: Check version relationship */
1862 zend_error(E_CORE_WARNING
, "Cannot load module '%s' because conflicting module '%s' is already loaded", module
->name
, dep
->name
);
1871 name_len
= strlen(module
->name
);
1872 lcname
= zend_str_tolower_dup(module
->name
, name_len
);
1874 if (zend_hash_add(&module_registry
, lcname
, name_len
+1, (void *)module
, sizeof(zend_module_entry
), (void**)&module_ptr
)==FAILURE
) {
1875 zend_error(E_CORE_WARNING
, "Module '%s' already loaded", module
->name
);
1880 module
= module_ptr
;
1881 EG(current_module
) = module
;
1883 if (module
->functions
&& zend_register_functions(NULL
, module
->functions
, NULL
, module
->type TSRMLS_CC
)==FAILURE
) {
1884 EG(current_module
) = NULL
;
1885 zend_error(E_CORE_WARNING
,"%s: Unable to register functions, unable to load", module
->name
);
1889 EG(current_module
) = NULL
;
1894 ZEND_API zend_module_entry
* zend_register_internal_module(zend_module_entry
*module TSRMLS_DC
) /* {{{ */
1896 module
->module_number
= zend_next_free_module();
1897 module
->type
= MODULE_PERSISTENT
;
1898 return zend_register_module_ex(module TSRMLS_CC
);
1902 ZEND_API
void zend_check_magic_method_implementation(const zend_class_entry
*ce
, const zend_function
*fptr
, int error_type TSRMLS_DC
) /* {{{ */
1907 /* we don't care if the function name is longer, in fact lowercasing only
1908 * the beginning of the name speeds up the check process */
1909 name_len
= strlen(fptr
->common
.function_name
);
1910 zend_str_tolower_copy(lcname
, fptr
->common
.function_name
, MIN(name_len
, sizeof(lcname
)-1));
1911 lcname
[sizeof(lcname
)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
1913 if (name_len
== sizeof(ZEND_DESTRUCTOR_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_DESTRUCTOR_FUNC_NAME
, sizeof(ZEND_DESTRUCTOR_FUNC_NAME
)) && fptr
->common
.num_args
!= 0) {
1914 zend_error(error_type
, "Destructor %s::%s() cannot take arguments", ce
->name
, ZEND_DESTRUCTOR_FUNC_NAME
);
1915 } else if (name_len
== sizeof(ZEND_CLONE_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_CLONE_FUNC_NAME
, sizeof(ZEND_CLONE_FUNC_NAME
)) && fptr
->common
.num_args
!= 0) {
1916 zend_error(error_type
, "Method %s::%s() cannot accept any arguments", ce
->name
, ZEND_CLONE_FUNC_NAME
);
1917 } else if (name_len
== sizeof(ZEND_GET_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_GET_FUNC_NAME
, sizeof(ZEND_GET_FUNC_NAME
))) {
1918 if (fptr
->common
.num_args
!= 1) {
1919 zend_error(error_type
, "Method %s::%s() must take exactly 1 argument", ce
->name
, ZEND_GET_FUNC_NAME
);
1920 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr
, 1)) {
1921 zend_error(error_type
, "Method %s::%s() cannot take arguments by reference", ce
->name
, ZEND_GET_FUNC_NAME
);
1923 } else if (name_len
== sizeof(ZEND_SET_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_SET_FUNC_NAME
, sizeof(ZEND_SET_FUNC_NAME
))) {
1924 if (fptr
->common
.num_args
!= 2) {
1925 zend_error(error_type
, "Method %s::%s() must take exactly 2 arguments", ce
->name
, ZEND_SET_FUNC_NAME
);
1926 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr
, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr
, 2)) {
1927 zend_error(error_type
, "Method %s::%s() cannot take arguments by reference", ce
->name
, ZEND_SET_FUNC_NAME
);
1929 } else if (name_len
== sizeof(ZEND_UNSET_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_UNSET_FUNC_NAME
, sizeof(ZEND_UNSET_FUNC_NAME
))) {
1930 if (fptr
->common
.num_args
!= 1) {
1931 zend_error(error_type
, "Method %s::%s() must take exactly 1 argument", ce
->name
, ZEND_UNSET_FUNC_NAME
);
1932 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr
, 1)) {
1933 zend_error(error_type
, "Method %s::%s() cannot take arguments by reference", ce
->name
, ZEND_UNSET_FUNC_NAME
);
1935 } else if (name_len
== sizeof(ZEND_ISSET_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_ISSET_FUNC_NAME
, sizeof(ZEND_ISSET_FUNC_NAME
))) {
1936 if (fptr
->common
.num_args
!= 1) {
1937 zend_error(error_type
, "Method %s::%s() must take exactly 1 argument", ce
->name
, ZEND_ISSET_FUNC_NAME
);
1938 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr
, 1)) {
1939 zend_error(error_type
, "Method %s::%s() cannot take arguments by reference", ce
->name
, ZEND_ISSET_FUNC_NAME
);
1941 } else if (name_len
== sizeof(ZEND_CALL_FUNC_NAME
) - 1 && !memcmp(lcname
, ZEND_CALL_FUNC_NAME
, sizeof(ZEND_CALL_FUNC_NAME
))) {
1942 if (fptr
->common
.num_args
!= 2) {
1943 zend_error(error_type
, "Method %s::%s() must take exactly 2 arguments", ce
->name
, ZEND_CALL_FUNC_NAME
);
1944 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr
, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr
, 2)) {
1945 zend_error(error_type
, "Method %s::%s() cannot take arguments by reference", ce
->name
, ZEND_CALL_FUNC_NAME
);
1947 } else if (name_len
== sizeof(ZEND_CALLSTATIC_FUNC_NAME
) - 1 &&
1948 !memcmp(lcname
, ZEND_CALLSTATIC_FUNC_NAME
, sizeof(ZEND_CALLSTATIC_FUNC_NAME
)-1)
1950 if (fptr
->common
.num_args
!= 2) {
1951 zend_error(error_type
, "Method %s::%s() must take exactly 2 arguments", ce
->name
, ZEND_CALLSTATIC_FUNC_NAME
);
1952 } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr
, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr
, 2)) {
1953 zend_error(error_type
, "Method %s::%s() cannot take arguments by reference", ce
->name
, ZEND_CALLSTATIC_FUNC_NAME
);
1955 } else if (name_len
== sizeof(ZEND_TOSTRING_FUNC_NAME
) - 1 &&
1956 !memcmp(lcname
, ZEND_TOSTRING_FUNC_NAME
, sizeof(ZEND_TOSTRING_FUNC_NAME
)-1) && fptr
->common
.num_args
!= 0
1958 zend_error(error_type
, "Method %s::%s() cannot take arguments", ce
->name
, ZEND_TOSTRING_FUNC_NAME
);
1963 /* registers all functions in *library_functions in the function hash */
1964 ZEND_API
int zend_register_functions(zend_class_entry
*scope
, const zend_function_entry
*functions
, HashTable
*function_table
, int type TSRMLS_DC
) /* {{{ */
1966 const zend_function_entry
*ptr
= functions
;
1967 zend_function function
, *reg_function
;
1968 zend_internal_function
*internal_function
= (zend_internal_function
*)&function
;
1969 int count
=0, unload
=0, result
=0;
1970 HashTable
*target_function_table
= function_table
;
1972 zend_function
*ctor
= NULL
, *dtor
= NULL
, *clone
= NULL
, *__get
= NULL
, *__set
= NULL
, *__unset
= NULL
, *__isset
= NULL
, *__call
= NULL
, *__callstatic
= NULL
, *__tostring
= NULL
;
1973 const char *lowercase_name
;
1975 const char *lc_class_name
= NULL
;
1976 int class_name_len
= 0;
1978 if (type
==MODULE_PERSISTENT
) {
1979 error_type
= E_CORE_WARNING
;
1981 error_type
= E_WARNING
;
1984 if (!target_function_table
) {
1985 target_function_table
= CG(function_table
);
1987 internal_function
->type
= ZEND_INTERNAL_FUNCTION
;
1988 internal_function
->module
= EG(current_module
);
1991 class_name_len
= strlen(scope
->name
);
1992 if ((lc_class_name
= zend_memrchr(scope
->name
, '\\', class_name_len
))) {
1994 class_name_len
-= (lc_class_name
- scope
->name
);
1995 lc_class_name
= zend_str_tolower_dup(lc_class_name
, class_name_len
);
1997 lc_class_name
= zend_str_tolower_dup(scope
->name
, class_name_len
);
2001 while (ptr
->fname
) {
2002 internal_function
->handler
= ptr
->handler
;
2003 internal_function
->function_name
= (char*)ptr
->fname
;
2004 internal_function
->scope
= scope
;
2005 internal_function
->prototype
= NULL
;
2007 if (!(ptr
->flags
& ZEND_ACC_PPP_MASK
)) {
2008 if (ptr
->flags
!= ZEND_ACC_DEPRECATED
|| scope
) {
2009 zend_error(error_type
, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope
? scope
->name
: "", scope
? "::" : "", ptr
->fname
);
2011 internal_function
->fn_flags
= ZEND_ACC_PUBLIC
| ptr
->flags
;
2013 internal_function
->fn_flags
= ptr
->flags
;
2016 internal_function
->fn_flags
= ZEND_ACC_PUBLIC
;
2018 if (ptr
->arg_info
) {
2019 zend_internal_function_info
*info
= (zend_internal_function_info
*)ptr
->arg_info
;
2021 internal_function
->arg_info
= (zend_arg_info
*)ptr
->arg_info
+1;
2022 internal_function
->num_args
= ptr
->num_args
;
2023 /* Currently you cannot denote that the function can accept less arguments than num_args */
2024 if (info
->required_num_args
== -1) {
2025 internal_function
->required_num_args
= ptr
->num_args
;
2027 internal_function
->required_num_args
= info
->required_num_args
;
2029 if (info
->pass_rest_by_reference
) {
2030 if (info
->pass_rest_by_reference
== ZEND_SEND_PREFER_REF
) {
2031 internal_function
->fn_flags
|= ZEND_ACC_PASS_REST_PREFER_REF
;
2033 internal_function
->fn_flags
|= ZEND_ACC_PASS_REST_BY_REFERENCE
;
2036 if (info
->return_reference
) {
2037 internal_function
->fn_flags
|= ZEND_ACC_RETURN_REFERENCE
;
2040 internal_function
->arg_info
= NULL
;
2041 internal_function
->num_args
= 0;
2042 internal_function
->required_num_args
= 0;
2044 if (ptr
->flags
& ZEND_ACC_ABSTRACT
) {
2046 /* This is a class that must be abstract itself. Here we set the check info. */
2047 scope
->ce_flags
|= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS
;
2048 if (!(scope
->ce_flags
& ZEND_ACC_INTERFACE
)) {
2049 /* Since the class is not an interface it needs to be declared as a abstract class. */
2050 /* Since here we are handling internal functions only we can add the keyword flag. */
2051 /* This time we set the flag for the keyword 'abstract'. */
2052 scope
->ce_flags
|= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
;
2055 if (ptr
->flags
& ZEND_ACC_STATIC
&& (!scope
|| !(scope
->ce_flags
& ZEND_ACC_INTERFACE
))) {
2056 zend_error(error_type
, "Static function %s%s%s() cannot be abstract", scope
? scope
->name
: "", scope
? "::" : "", ptr
->fname
);
2059 if (scope
&& (scope
->ce_flags
& ZEND_ACC_INTERFACE
)) {
2060 efree((char*)lc_class_name
);
2061 zend_error(error_type
, "Interface %s cannot contain non abstract method %s()", scope
->name
, ptr
->fname
);
2064 if (!internal_function
->handler
) {
2066 efree((char*)lc_class_name
);
2068 zend_error(error_type
, "Method %s%s%s() cannot be a NULL function", scope
? scope
->name
: "", scope
? "::" : "", ptr
->fname
);
2069 zend_unregister_functions(functions
, count
, target_function_table TSRMLS_CC
);
2073 fname_len
= strlen(ptr
->fname
);
2074 lowercase_name
= zend_new_interned_string(zend_str_tolower_dup(ptr
->fname
, fname_len
), fname_len
+ 1, 1 TSRMLS_CC
);
2075 if (IS_INTERNED(lowercase_name
)) {
2076 result
= zend_hash_quick_add(target_function_table
, lowercase_name
, fname_len
+1, INTERNED_HASH(lowercase_name
), &function
, sizeof(zend_function
), (void**)®_function
);
2078 result
= zend_hash_add(target_function_table
, lowercase_name
, fname_len
+1, &function
, sizeof(zend_function
), (void**)®_function
);
2080 if (result
== FAILURE
) {
2082 str_efree(lowercase_name
);
2086 /* Look for ctor, dtor, clone
2087 * If it's an old-style constructor, store it only if we don't have
2088 * a constructor already.
2090 if ((fname_len
== class_name_len
) && !ctor
&& !memcmp(lowercase_name
, lc_class_name
, class_name_len
+1)) {
2091 ctor
= reg_function
;
2092 } else if ((fname_len
== sizeof(ZEND_CONSTRUCTOR_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_CONSTRUCTOR_FUNC_NAME
, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME
))) {
2093 ctor
= reg_function
;
2094 } else if ((fname_len
== sizeof(ZEND_DESTRUCTOR_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_DESTRUCTOR_FUNC_NAME
, sizeof(ZEND_DESTRUCTOR_FUNC_NAME
))) {
2095 dtor
= reg_function
;
2096 if (internal_function
->num_args
) {
2097 zend_error(error_type
, "Destructor %s::%s() cannot take arguments", scope
->name
, ptr
->fname
);
2099 } else if ((fname_len
== sizeof(ZEND_CLONE_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_CLONE_FUNC_NAME
, sizeof(ZEND_CLONE_FUNC_NAME
))) {
2100 clone
= reg_function
;
2101 } else if ((fname_len
== sizeof(ZEND_CALL_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_CALL_FUNC_NAME
, sizeof(ZEND_CALL_FUNC_NAME
))) {
2102 __call
= reg_function
;
2103 } else if ((fname_len
== sizeof(ZEND_CALLSTATIC_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_CALLSTATIC_FUNC_NAME
, sizeof(ZEND_CALLSTATIC_FUNC_NAME
))) {
2104 __callstatic
= reg_function
;
2105 } else if ((fname_len
== sizeof(ZEND_TOSTRING_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_TOSTRING_FUNC_NAME
, sizeof(ZEND_TOSTRING_FUNC_NAME
))) {
2106 __tostring
= reg_function
;
2107 } else if ((fname_len
== sizeof(ZEND_GET_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_GET_FUNC_NAME
, sizeof(ZEND_GET_FUNC_NAME
))) {
2108 __get
= reg_function
;
2109 } else if ((fname_len
== sizeof(ZEND_SET_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_SET_FUNC_NAME
, sizeof(ZEND_SET_FUNC_NAME
))) {
2110 __set
= reg_function
;
2111 } else if ((fname_len
== sizeof(ZEND_UNSET_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_UNSET_FUNC_NAME
, sizeof(ZEND_UNSET_FUNC_NAME
))) {
2112 __unset
= reg_function
;
2113 } else if ((fname_len
== sizeof(ZEND_ISSET_FUNC_NAME
)-1) && !memcmp(lowercase_name
, ZEND_ISSET_FUNC_NAME
, sizeof(ZEND_ISSET_FUNC_NAME
))) {
2114 __isset
= reg_function
;
2116 reg_function
= NULL
;
2119 zend_check_magic_method_implementation(scope
, reg_function
, error_type TSRMLS_CC
);
2124 str_efree(lowercase_name
);
2126 if (unload
) { /* before unloading, display all remaining bad function in the module */
2128 efree((char*)lc_class_name
);
2130 while (ptr
->fname
) {
2131 fname_len
= strlen(ptr
->fname
);
2132 lowercase_name
= zend_str_tolower_dup(ptr
->fname
, fname_len
);
2133 if (zend_hash_exists(target_function_table
, lowercase_name
, fname_len
+1)) {
2134 zend_error(error_type
, "Function registration failed - duplicate name - %s%s%s", scope
? scope
->name
: "", scope
? "::" : "", ptr
->fname
);
2136 efree((char*)lowercase_name
);
2139 zend_unregister_functions(functions
, count
, target_function_table TSRMLS_CC
);
2143 scope
->constructor
= ctor
;
2144 scope
->destructor
= dtor
;
2145 scope
->clone
= clone
;
2146 scope
->__call
= __call
;
2147 scope
->__callstatic
= __callstatic
;
2148 scope
->__tostring
= __tostring
;
2149 scope
->__get
= __get
;
2150 scope
->__set
= __set
;
2151 scope
->__unset
= __unset
;
2152 scope
->__isset
= __isset
;
2154 ctor
->common
.fn_flags
|= ZEND_ACC_CTOR
;
2155 if (ctor
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2156 zend_error(error_type
, "Constructor %s::%s() cannot be static", scope
->name
, ctor
->common
.function_name
);
2158 ctor
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2161 dtor
->common
.fn_flags
|= ZEND_ACC_DTOR
;
2162 if (dtor
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2163 zend_error(error_type
, "Destructor %s::%s() cannot be static", scope
->name
, dtor
->common
.function_name
);
2165 dtor
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2168 clone
->common
.fn_flags
|= ZEND_ACC_CLONE
;
2169 if (clone
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2170 zend_error(error_type
, "Constructor %s::%s() cannot be static", scope
->name
, clone
->common
.function_name
);
2172 clone
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2175 if (__call
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2176 zend_error(error_type
, "Method %s::%s() cannot be static", scope
->name
, __call
->common
.function_name
);
2178 __call
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2181 if (!(__callstatic
->common
.fn_flags
& ZEND_ACC_STATIC
)) {
2182 zend_error(error_type
, "Method %s::%s() must be static", scope
->name
, __callstatic
->common
.function_name
);
2184 __callstatic
->common
.fn_flags
|= ZEND_ACC_STATIC
;
2187 if (__tostring
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2188 zend_error(error_type
, "Method %s::%s() cannot be static", scope
->name
, __tostring
->common
.function_name
);
2190 __tostring
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2193 if (__get
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2194 zend_error(error_type
, "Method %s::%s() cannot be static", scope
->name
, __get
->common
.function_name
);
2196 __get
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2199 if (__set
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2200 zend_error(error_type
, "Method %s::%s() cannot be static", scope
->name
, __set
->common
.function_name
);
2202 __set
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2205 if (__unset
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2206 zend_error(error_type
, "Method %s::%s() cannot be static", scope
->name
, __unset
->common
.function_name
);
2208 __unset
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2211 if (__isset
->common
.fn_flags
& ZEND_ACC_STATIC
) {
2212 zend_error(error_type
, "Method %s::%s() cannot be static", scope
->name
, __isset
->common
.function_name
);
2214 __isset
->common
.fn_flags
&= ~ZEND_ACC_ALLOW_STATIC
;
2216 efree((char*)lc_class_name
);
2222 /* count=-1 means erase all functions, otherwise,
2223 * erase the first count functions
2225 ZEND_API
void zend_unregister_functions(const zend_function_entry
*functions
, int count
, HashTable
*function_table TSRMLS_DC
) /* {{{ */
2227 const zend_function_entry
*ptr
= functions
;
2229 HashTable
*target_function_table
= function_table
;
2231 if (!target_function_table
) {
2232 target_function_table
= CG(function_table
);
2234 while (ptr
->fname
) {
2235 if (count
!=-1 && i
>=count
) {
2239 zend_printf("Unregistering %s()\n", ptr
->fname
);
2241 zend_hash_del(target_function_table
, ptr
->fname
, strlen(ptr
->fname
)+1);
2248 ZEND_API
int zend_startup_module(zend_module_entry
*module
) /* {{{ */
2252 if ((module
= zend_register_internal_module(module TSRMLS_CC
)) != NULL
&& zend_startup_module_ex(module TSRMLS_CC
) == SUCCESS
) {
2259 ZEND_API
int zend_get_module_started(const char *module_name
) /* {{{ */
2261 zend_module_entry
*module
;
2263 return (zend_hash_find(&module_registry
, module_name
, strlen(module_name
)+1, (void**)&module
) == SUCCESS
&& module
->module_started
) ? SUCCESS
: FAILURE
;
2267 static int clean_module_class(const zend_class_entry
**ce
, int *module_number TSRMLS_DC
) /* {{{ */
2269 if ((*ce
)->type
== ZEND_INTERNAL_CLASS
&& (*ce
)->info
.internal
.module
->module_number
== *module_number
) {
2270 return ZEND_HASH_APPLY_REMOVE
;
2272 return ZEND_HASH_APPLY_KEEP
;
2277 static void clean_module_classes(int module_number TSRMLS_DC
) /* {{{ */
2279 zend_hash_apply_with_argument(EG(class_table
), (apply_func_arg_t
) clean_module_class
, (void *) &module_number TSRMLS_CC
);
2283 void module_destructor(zend_module_entry
*module
) /* {{{ */
2287 if (module
->type
== MODULE_TEMPORARY
) {
2288 zend_clean_module_rsrc_dtors(module
->module_number TSRMLS_CC
);
2289 clean_module_constants(module
->module_number TSRMLS_CC
);
2290 clean_module_classes(module
->module_number TSRMLS_CC
);
2293 if (module
->module_started
&& module
->module_shutdown_func
) {
2295 zend_printf("%s: Module shutdown\n", module
->name
);
2297 module
->module_shutdown_func(module
->type
, module
->module_number TSRMLS_CC
);
2300 /* Deinitilaise module globals */
2301 if (module
->globals_size
) {
2303 if (*module
->globals_id_ptr
) {
2304 ts_free_id(*module
->globals_id_ptr
);
2307 if (module
->globals_dtor
) {
2308 module
->globals_dtor(module
->globals_ptr TSRMLS_CC
);
2313 module
->module_started
=0;
2314 if (module
->functions
) {
2315 zend_unregister_functions(module
->functions
, -1, NULL TSRMLS_CC
);
2319 #if !(defined(NETWARE) && defined(APACHE_1_BUILD))
2320 if (module
->handle
&& !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2321 DL_UNLOAD(module
->handle
);
2328 void zend_activate_modules(TSRMLS_D
) /* {{{ */
2330 zend_module_entry
**p
= module_request_startup_handlers
;
2333 zend_module_entry
*module
= *p
;
2335 if (module
->request_startup_func(module
->type
, module
->module_number TSRMLS_CC
)==FAILURE
) {
2336 zend_error(E_WARNING
, "request_startup() for %s module failed", module
->name
);
2344 /* call request shutdown for all modules */
2345 int module_registry_cleanup(zend_module_entry
*module TSRMLS_DC
) /* {{{ */
2347 if (module
->request_shutdown_func
) {
2349 zend_printf("%s: Request shutdown\n", module
->name
);
2351 module
->request_shutdown_func(module
->type
, module
->module_number TSRMLS_CC
);
2357 void zend_deactivate_modules(TSRMLS_D
) /* {{{ */
2359 EG(opline_ptr
) = NULL
; /* we're no longer executing anything */
2362 if (EG(full_tables_cleanup
)) {
2363 zend_hash_reverse_apply(&module_registry
, (apply_func_t
) module_registry_cleanup TSRMLS_CC
);
2365 zend_module_entry
**p
= module_request_shutdown_handlers
;
2368 zend_module_entry
*module
= *p
;
2370 module
->request_shutdown_func(module
->type
, module
->module_number TSRMLS_CC
);
2378 ZEND_API
void zend_cleanup_internal_classes(TSRMLS_D
) /* {{{ */
2380 zend_class_entry
**p
= class_cleanup_handlers
;
2383 zend_cleanup_internal_class_data(*p TSRMLS_CC
);
2389 int module_registry_unload_temp(const zend_module_entry
*module TSRMLS_DC
) /* {{{ */
2391 return (module
->type
== MODULE_TEMPORARY
) ? ZEND_HASH_APPLY_REMOVE
: ZEND_HASH_APPLY_STOP
;
2395 static int exec_done_cb(zend_module_entry
*module TSRMLS_DC
) /* {{{ */
2397 if (module
->post_deactivate_func
) {
2398 module
->post_deactivate_func();
2404 void zend_post_deactivate_modules(TSRMLS_D
) /* {{{ */
2406 if (EG(full_tables_cleanup
)) {
2407 zend_hash_apply(&module_registry
, (apply_func_t
) exec_done_cb TSRMLS_CC
);
2408 zend_hash_reverse_apply(&module_registry
, (apply_func_t
) module_registry_unload_temp TSRMLS_CC
);
2410 zend_module_entry
**p
= module_post_deactivate_handlers
;
2413 zend_module_entry
*module
= *p
;
2415 module
->post_deactivate_func();
2422 /* return the next free module number */
2423 int zend_next_free_module(void) /* {{{ */
2425 return zend_hash_num_elements(&module_registry
) + 1;
2429 static zend_class_entry
*do_register_internal_class(zend_class_entry
*orig_class_entry
, zend_uint ce_flags TSRMLS_DC
) /* {{{ */
2431 zend_class_entry
*class_entry
= malloc(sizeof(zend_class_entry
));
2432 char *lowercase_name
= emalloc(orig_class_entry
->name_length
+ 1);
2433 *class_entry
= *orig_class_entry
;
2435 class_entry
->type
= ZEND_INTERNAL_CLASS
;
2436 zend_initialize_class_data(class_entry
, 0 TSRMLS_CC
);
2437 class_entry
->ce_flags
= ce_flags
;
2438 class_entry
->info
.internal
.module
= EG(current_module
);
2440 if (class_entry
->info
.internal
.builtin_functions
) {
2441 zend_register_functions(class_entry
, class_entry
->info
.internal
.builtin_functions
, &class_entry
->function_table
, MODULE_PERSISTENT TSRMLS_CC
);
2444 zend_str_tolower_copy(lowercase_name
, orig_class_entry
->name
, class_entry
->name_length
);
2445 lowercase_name
= (char*)zend_new_interned_string(lowercase_name
, class_entry
->name_length
+ 1, 1 TSRMLS_CC
);
2446 if (IS_INTERNED(lowercase_name
)) {
2447 zend_hash_quick_update(CG(class_table
), lowercase_name
, class_entry
->name_length
+1, INTERNED_HASH(lowercase_name
), &class_entry
, sizeof(zend_class_entry
*), NULL
);
2449 zend_hash_update(CG(class_table
), lowercase_name
, class_entry
->name_length
+1, &class_entry
, sizeof(zend_class_entry
*), NULL
);
2451 str_efree(lowercase_name
);
2456 /* If parent_ce is not NULL then it inherits from parent_ce
2457 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2458 * If both parent_ce and parent_name are NULL it does a regular class registration
2459 * If parent_name is specified but not found NULL is returned
2461 ZEND_API zend_class_entry
*zend_register_internal_class_ex(zend_class_entry
*class_entry
, zend_class_entry
*parent_ce
, char *parent_name TSRMLS_DC
) /* {{{ */
2463 zend_class_entry
*register_class
;
2465 if (!parent_ce
&& parent_name
) {
2466 zend_class_entry
**pce
;
2467 if (zend_hash_find(CG(class_table
), parent_name
, strlen(parent_name
)+1, (void **) &pce
)==FAILURE
) {
2474 register_class
= zend_register_internal_class(class_entry TSRMLS_CC
);
2477 zend_do_inheritance(register_class
, parent_ce TSRMLS_CC
);
2479 return register_class
;
2483 ZEND_API
void zend_class_implements(zend_class_entry
*class_entry TSRMLS_DC
, int num_interfaces
, ...) /* {{{ */
2485 zend_class_entry
*interface_entry
;
2486 va_list interface_list
;
2487 va_start(interface_list
, num_interfaces
);
2489 while (num_interfaces
--) {
2490 interface_entry
= va_arg(interface_list
, zend_class_entry
*);
2491 zend_do_implement_interface(class_entry
, interface_entry TSRMLS_CC
);
2494 va_end(interface_list
);
2498 /* A class that contains at least one abstract method automatically becomes an abstract class.
2500 ZEND_API zend_class_entry
*zend_register_internal_class(zend_class_entry
*orig_class_entry TSRMLS_DC
) /* {{{ */
2502 return do_register_internal_class(orig_class_entry
, 0 TSRMLS_CC
);
2506 ZEND_API zend_class_entry
*zend_register_internal_interface(zend_class_entry
*orig_class_entry TSRMLS_DC
) /* {{{ */
2508 return do_register_internal_class(orig_class_entry
, ZEND_ACC_INTERFACE TSRMLS_CC
);
2512 ZEND_API
int zend_register_class_alias_ex(const char *name
, int name_len
, zend_class_entry
*ce TSRMLS_DC
) /* {{{ */
2514 char *lcname
= zend_str_tolower_dup(name
, name_len
);
2517 ret
= zend_hash_add(CG(class_table
), lcname
, name_len
+1, &ce
, sizeof(zend_class_entry
*), NULL
);
2519 if (ret
== SUCCESS
) {
2526 ZEND_API
int zend_set_hash_symbol(zval
*symbol
, const char *name
, int name_length
, zend_bool is_ref
, int num_symbol_tables
, ...) /* {{{ */
2528 HashTable
*symbol_table
;
2529 va_list symbol_table_list
;
2531 if (num_symbol_tables
<= 0) return FAILURE
;
2533 Z_SET_ISREF_TO_P(symbol
, is_ref
);
2535 va_start(symbol_table_list
, num_symbol_tables
);
2536 while (num_symbol_tables
-- > 0) {
2537 symbol_table
= va_arg(symbol_table_list
, HashTable
*);
2538 zend_hash_update(symbol_table
, name
, name_length
+ 1, &symbol
, sizeof(zval
*), NULL
);
2539 zval_add_ref(&symbol
);
2541 va_end(symbol_table_list
);
2546 /* Disabled functions support */
2548 /* {{{ proto void display_disabled_function(void)
2549 Dummy function which displays an error when a disabled function is called. */
2550 ZEND_API
ZEND_FUNCTION(display_disabled_function
)
2552 zend_error(E_WARNING
, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C
));
2556 static zend_function_entry disabled_function
[] = {
2557 ZEND_FE(display_disabled_function
, NULL
)
2561 ZEND_API
int zend_disable_function(char *function_name
, uint function_name_length TSRMLS_DC
) /* {{{ */
2563 if (zend_hash_del(CG(function_table
), function_name
, function_name_length
+1)==FAILURE
) {
2566 disabled_function
[0].fname
= function_name
;
2567 return zend_register_functions(NULL
, disabled_function
, CG(function_table
), MODULE_PERSISTENT TSRMLS_CC
);
2572 #pragma optimize("", off)
2574 static zend_object_value
display_disabled_class(zend_class_entry
*class_type TSRMLS_DC
) /* {{{ */
2576 zend_object_value retval
;
2577 zend_object
*intern
;
2578 retval
= zend_objects_new(&intern
, class_type TSRMLS_CC
);
2579 zend_error(E_WARNING
, "%s() has been disabled for security reasons", class_type
->name
);
2583 #pragma optimize("", on)
2587 static const zend_function_entry disabled_class_new
[] = {
2591 ZEND_API
int zend_disable_class(char *class_name
, uint class_name_length TSRMLS_DC
) /* {{{ */
2593 zend_class_entry
**disabled_class
;
2595 zend_str_tolower(class_name
, class_name_length
);
2596 if (zend_hash_find(CG(class_table
), class_name
, class_name_length
+1, (void **)&disabled_class
)==FAILURE
) {
2599 INIT_CLASS_ENTRY_INIT_METHODS((**disabled_class
), disabled_class_new
, NULL
, NULL
, NULL
, NULL
, NULL
);
2600 (*disabled_class
)->create_object
= display_disabled_class
;
2601 zend_hash_clean(&((*disabled_class
)->function_table
));
2606 static int zend_is_callable_check_class(const char *name
, int name_len
, zend_fcall_info_cache
*fcc
, int *strict_class
, char **error TSRMLS_DC
) /* {{{ */
2609 zend_class_entry
**pce
;
2610 char *lcname
= zend_str_tolower_dup(name
, name_len
);
2613 if (name_len
== sizeof("self") - 1 &&
2614 !memcmp(lcname
, "self", sizeof("self") - 1)) {
2616 if (error
) *error
= estrdup("cannot access self:: when no class scope is active");
2618 fcc
->called_scope
= EG(called_scope
);
2619 fcc
->calling_scope
= EG(scope
);
2620 if (!fcc
->object_ptr
) {
2621 fcc
->object_ptr
= EG(This
);
2625 } else if (name_len
== sizeof("parent") - 1 &&
2626 !memcmp(lcname
, "parent", sizeof("parent") - 1)) {
2628 if (error
) *error
= estrdup("cannot access parent:: when no class scope is active");
2629 } else if (!EG(scope
)->parent
) {
2630 if (error
) *error
= estrdup("cannot access parent:: when current class scope has no parent");
2632 fcc
->called_scope
= EG(called_scope
);
2633 fcc
->calling_scope
= EG(scope
)->parent
;
2634 if (!fcc
->object_ptr
) {
2635 fcc
->object_ptr
= EG(This
);
2640 } else if (name_len
== sizeof("static") - 1 &&
2641 !memcmp(lcname
, "static", sizeof("static") - 1)) {
2642 if (!EG(called_scope
)) {
2643 if (error
) *error
= estrdup("cannot access static:: when no class scope is active");
2645 fcc
->called_scope
= EG(called_scope
);
2646 fcc
->calling_scope
= EG(called_scope
);
2647 if (!fcc
->object_ptr
) {
2648 fcc
->object_ptr
= EG(This
);
2653 } else if (zend_lookup_class_ex(name
, name_len
, NULL
, 1, &pce TSRMLS_CC
) == SUCCESS
) {
2654 zend_class_entry
*scope
= EG(active_op_array
) ? EG(active_op_array
)->scope
: NULL
;
2656 fcc
->calling_scope
= *pce
;
2657 if (scope
&& !fcc
->object_ptr
&& EG(This
) &&
2658 instanceof_function(Z_OBJCE_P(EG(This
)), scope TSRMLS_CC
) &&
2659 instanceof_function(scope
, fcc
->calling_scope TSRMLS_CC
)) {
2660 fcc
->object_ptr
= EG(This
);
2661 fcc
->called_scope
= Z_OBJCE_P(fcc
->object_ptr
);
2663 fcc
->called_scope
= fcc
->object_ptr
? Z_OBJCE_P(fcc
->object_ptr
) : fcc
->calling_scope
;
2668 if (error
) zend_spprintf(error
, 0, "class '%.*s' not found", name_len
, name
);
2675 static int zend_is_callable_check_func(int check_flags
, zval
*callable
, zend_fcall_info_cache
*fcc
, int strict_class
, char **error TSRMLS_DC
) /* {{{ */
2677 zend_class_entry
*ce_org
= fcc
->calling_scope
;
2679 char *mname
, *lmname
;
2682 zend_class_entry
*last_scope
;
2684 int call_via_handler
= 0;
2690 fcc
->calling_scope
= NULL
;
2691 fcc
->function_handler
= NULL
;
2694 /* Skip leading \ */
2695 if (Z_STRVAL_P(callable
)[0] == '\\') {
2696 mlen
= Z_STRLEN_P(callable
) - 1;
2697 lmname
= zend_str_tolower_dup(Z_STRVAL_P(callable
) + 1, mlen
);
2699 mlen
= Z_STRLEN_P(callable
);
2700 lmname
= zend_str_tolower_dup(Z_STRVAL_P(callable
), mlen
);
2702 /* Check if function with given name exists.
2703 * This may be a compound name that includes namespace name */
2704 if (zend_hash_find(EG(function_table
), lmname
, mlen
+1, (void**)&fcc
->function_handler
) == SUCCESS
) {
2711 /* Split name into class/namespace and method/function names */
2712 if ((colon
= zend_memrchr(Z_STRVAL_P(callable
), ':', Z_STRLEN_P(callable
))) != NULL
&&
2713 colon
> Z_STRVAL_P(callable
) &&
2717 clen
= colon
- Z_STRVAL_P(callable
);
2718 mlen
= Z_STRLEN_P(callable
) - clen
- 2;
2720 if (colon
== Z_STRVAL_P(callable
)) {
2721 if (error
) zend_spprintf(error
, 0, "invalid function name");
2725 /* This is a compound name.
2726 * Try to fetch class and then find static method. */
2727 last_scope
= EG(scope
);
2732 if (!zend_is_callable_check_class(Z_STRVAL_P(callable
), clen
, fcc
, &strict_class
, error TSRMLS_CC
)) {
2733 EG(scope
) = last_scope
;
2736 EG(scope
) = last_scope
;
2738 ftable
= &fcc
->calling_scope
->function_table
;
2739 if (ce_org
&& !instanceof_function(ce_org
, fcc
->calling_scope TSRMLS_CC
)) {
2740 if (error
) zend_spprintf(error
, 0, "class '%s' is not a subclass of '%s'", ce_org
->name
, fcc
->calling_scope
->name
);
2743 mname
= Z_STRVAL_P(callable
) + clen
+ 2;
2744 } else if (ce_org
) {
2745 /* Try to fetch find static method of given class. */
2746 mlen
= Z_STRLEN_P(callable
);
2747 mname
= Z_STRVAL_P(callable
);
2748 ftable
= &ce_org
->function_table
;
2749 fcc
->calling_scope
= ce_org
;
2751 /* We already checked for plain function before. */
2752 if (error
&& !(check_flags
& IS_CALLABLE_CHECK_SILENT
)) {
2753 zend_spprintf(error
, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable
));
2758 lmname
= zend_str_tolower_dup(mname
, mlen
);
2760 fcc
->calling_scope
&&
2761 mlen
== sizeof(ZEND_CONSTRUCTOR_FUNC_NAME
)-1 &&
2762 !memcmp(lmname
, ZEND_CONSTRUCTOR_FUNC_NAME
, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME
))) {
2763 fcc
->function_handler
= fcc
->calling_scope
->constructor
;
2764 if (fcc
->function_handler
) {
2767 } else if (zend_hash_find(ftable
, lmname
, mlen
+1, (void**)&fcc
->function_handler
) == SUCCESS
) {
2769 if ((fcc
->function_handler
->op_array
.fn_flags
& ZEND_ACC_CHANGED
) &&
2770 !strict_class
&& EG(scope
) &&
2771 instanceof_function(fcc
->function_handler
->common
.scope
, EG(scope
) TSRMLS_CC
)) {
2772 zend_function
*priv_fbc
;
2774 if (zend_hash_find(&EG(scope
)->function_table
, lmname
, mlen
+1, (void **) &priv_fbc
)==SUCCESS
2775 && priv_fbc
->common
.fn_flags
& ZEND_ACC_PRIVATE
2776 && priv_fbc
->common
.scope
== EG(scope
)) {
2777 fcc
->function_handler
= priv_fbc
;
2780 if ((check_flags
& IS_CALLABLE_CHECK_NO_ACCESS
) == 0 &&
2781 (fcc
->calling_scope
&&
2782 (fcc
->calling_scope
->__call
||
2783 fcc
->calling_scope
->__callstatic
))) {
2784 if (fcc
->function_handler
->op_array
.fn_flags
& ZEND_ACC_PRIVATE
) {
2785 if (!zend_check_private(fcc
->function_handler
, fcc
->object_ptr
? Z_OBJCE_P(fcc
->object_ptr
) : EG(scope
), lmname
, mlen TSRMLS_CC
)) {
2787 fcc
->function_handler
= NULL
;
2788 goto get_function_via_handler
;
2790 } else if (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_PROTECTED
) {
2791 if (!zend_check_protected(fcc
->function_handler
->common
.scope
, EG(scope
))) {
2793 fcc
->function_handler
= NULL
;
2794 goto get_function_via_handler
;
2799 get_function_via_handler
:
2800 if (fcc
->object_ptr
&& fcc
->calling_scope
== ce_org
) {
2801 if (strict_class
&& ce_org
->__call
) {
2802 fcc
->function_handler
= emalloc(sizeof(zend_internal_function
));
2803 fcc
->function_handler
->internal_function
.type
= ZEND_INTERNAL_FUNCTION
;
2804 fcc
->function_handler
->internal_function
.module
= (ce_org
->type
== ZEND_INTERNAL_CLASS
) ? ce_org
->info
.internal
.module
: NULL
;
2805 fcc
->function_handler
->internal_function
.handler
= zend_std_call_user_call
;
2806 fcc
->function_handler
->internal_function
.arg_info
= NULL
;
2807 fcc
->function_handler
->internal_function
.num_args
= 0;
2808 fcc
->function_handler
->internal_function
.scope
= ce_org
;
2809 fcc
->function_handler
->internal_function
.fn_flags
= ZEND_ACC_CALL_VIA_HANDLER
;
2810 fcc
->function_handler
->internal_function
.function_name
= estrndup(mname
, mlen
);
2811 call_via_handler
= 1;
2813 } else if (Z_OBJ_HT_P(fcc
->object_ptr
)->get_method
) {
2814 fcc
->function_handler
= Z_OBJ_HT_P(fcc
->object_ptr
)->get_method(&fcc
->object_ptr
, mname
, mlen
, NULL TSRMLS_CC
);
2815 if (fcc
->function_handler
) {
2817 (!fcc
->function_handler
->common
.scope
||
2818 !instanceof_function(ce_org
, fcc
->function_handler
->common
.scope TSRMLS_CC
))) {
2819 if ((fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_CALL_VIA_HANDLER
) != 0) {
2820 if (fcc
->function_handler
->type
!= ZEND_OVERLOADED_FUNCTION
) {
2821 efree((char*)fcc
->function_handler
->common
.function_name
);
2823 efree(fcc
->function_handler
);
2827 call_via_handler
= (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_CALL_VIA_HANDLER
) != 0;
2831 } else if (fcc
->calling_scope
) {
2832 if (fcc
->calling_scope
->get_static_method
) {
2833 fcc
->function_handler
= fcc
->calling_scope
->get_static_method(fcc
->calling_scope
, mname
, mlen TSRMLS_CC
);
2835 fcc
->function_handler
= zend_std_get_static_method(fcc
->calling_scope
, mname
, mlen
, NULL TSRMLS_CC
);
2837 if (fcc
->function_handler
) {
2839 call_via_handler
= (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_CALL_VIA_HANDLER
) != 0;
2840 if (call_via_handler
&& !fcc
->object_ptr
&& EG(This
) &&
2841 Z_OBJ_HT_P(EG(This
))->get_class_entry
&&
2842 instanceof_function(Z_OBJCE_P(EG(This
)), fcc
->calling_scope TSRMLS_CC
)) {
2843 fcc
->object_ptr
= EG(This
);
2850 if (fcc
->calling_scope
&& !call_via_handler
) {
2851 if (!fcc
->object_ptr
&& (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_ABSTRACT
)) {
2853 zend_spprintf(error
, 0, "cannot call abstract method %s::%s()", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
);
2856 zend_error(E_ERROR
, "Cannot call abstract method %s::%s()", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
);
2858 } else if (!fcc
->object_ptr
&& !(fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_STATIC
)) {
2861 if (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_ALLOW_STATIC
) {
2862 severity
= E_STRICT
;
2863 verb
= "should not";
2865 /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2869 if ((check_flags
& IS_CALLABLE_CHECK_IS_STATIC
) != 0) {
2872 if (EG(This
) && instanceof_function(Z_OBJCE_P(EG(This
)), fcc
->calling_scope TSRMLS_CC
)) {
2873 fcc
->object_ptr
= EG(This
);
2875 zend_spprintf(error
, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
, verb
, Z_OBJCE_P(EG(This
))->name
);
2876 if (severity
== E_ERROR
) {
2879 } else if (retval
) {
2880 zend_error(severity
, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
, verb
, Z_OBJCE_P(EG(This
))->name
);
2884 zend_spprintf(error
, 0, "non-static method %s::%s() %s be called statically", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
, verb
);
2885 if (severity
== E_ERROR
) {
2888 } else if (retval
) {
2889 zend_error(severity
, "Non-static method %s::%s() %s be called statically", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
, verb
);
2893 if (retval
&& (check_flags
& IS_CALLABLE_CHECK_NO_ACCESS
) == 0) {
2894 if (fcc
->function_handler
->op_array
.fn_flags
& ZEND_ACC_PRIVATE
) {
2895 if (!zend_check_private(fcc
->function_handler
, fcc
->object_ptr
? Z_OBJCE_P(fcc
->object_ptr
) : EG(scope
), lmname
, mlen TSRMLS_CC
)) {
2900 zend_spprintf(error
, 0, "cannot access private method %s::%s()", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
);
2904 } else if ((fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_PROTECTED
)) {
2905 if (!zend_check_protected(fcc
->function_handler
->common
.scope
, EG(scope
))) {
2910 zend_spprintf(error
, 0, "cannot access protected method %s::%s()", fcc
->calling_scope
->name
, fcc
->function_handler
->common
.function_name
);
2917 } else if (error
&& !(check_flags
& IS_CALLABLE_CHECK_SILENT
)) {
2918 if (fcc
->calling_scope
) {
2919 if (error
) zend_spprintf(error
, 0, "class '%s' does not have a method '%s'", fcc
->calling_scope
->name
, mname
);
2921 if (error
) zend_spprintf(error
, 0, "function '%s' does not exist", mname
);
2926 if (fcc
->object_ptr
) {
2927 fcc
->called_scope
= Z_OBJCE_P(fcc
->object_ptr
);
2930 fcc
->initialized
= 1;
2936 ZEND_API zend_bool
zend_is_callable_ex(zval
*callable
, zval
*object_ptr
, uint check_flags
, char **callable_name
, int *callable_name_len
, zend_fcall_info_cache
*fcc
, char **error TSRMLS_DC
) /* {{{ */
2939 int callable_name_len_local
;
2940 zend_fcall_info_cache fcc_local
;
2942 if (callable_name
) {
2943 *callable_name
= NULL
;
2945 if (callable_name_len
== NULL
) {
2946 callable_name_len
= &callable_name_len_local
;
2955 fcc
->initialized
= 0;
2956 fcc
->calling_scope
= NULL
;
2957 fcc
->called_scope
= NULL
;
2958 fcc
->function_handler
= NULL
;
2959 fcc
->calling_scope
= NULL
;
2960 fcc
->object_ptr
= NULL
;
2962 if (object_ptr
&& Z_TYPE_P(object_ptr
) != IS_OBJECT
) {
2966 (!EG(objects_store
).object_buckets
||
2967 !EG(objects_store
).object_buckets
[Z_OBJ_HANDLE_P(object_ptr
)].valid
)) {
2971 switch (Z_TYPE_P(callable
)) {
2974 fcc
->object_ptr
= object_ptr
;
2975 fcc
->calling_scope
= Z_OBJCE_P(object_ptr
);
2976 if (callable_name
) {
2979 *callable_name_len
= fcc
->calling_scope
->name_length
+ Z_STRLEN_P(callable
) + sizeof("::") - 1;
2980 ptr
= *callable_name
= emalloc(*callable_name_len
+ 1);
2981 memcpy(ptr
, fcc
->calling_scope
->name
, fcc
->calling_scope
->name_length
);
2982 ptr
+= fcc
->calling_scope
->name_length
;
2983 memcpy(ptr
, "::", sizeof("::") - 1);
2984 ptr
+= sizeof("::") - 1;
2985 memcpy(ptr
, Z_STRVAL_P(callable
), Z_STRLEN_P(callable
) + 1);
2987 } else if (callable_name
) {
2988 *callable_name
= estrndup(Z_STRVAL_P(callable
), Z_STRLEN_P(callable
));
2989 *callable_name_len
= Z_STRLEN_P(callable
);
2991 if (check_flags
& IS_CALLABLE_CHECK_SYNTAX_ONLY
) {
2992 fcc
->called_scope
= fcc
->calling_scope
;
2996 ret
= zend_is_callable_check_func(check_flags
, callable
, fcc
, 0, error TSRMLS_CC
);
2997 if (fcc
== &fcc_local
&&
2998 fcc
->function_handler
&&
2999 ((fcc
->function_handler
->type
== ZEND_INTERNAL_FUNCTION
&&
3000 (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_CALL_VIA_HANDLER
)) ||
3001 fcc
->function_handler
->type
== ZEND_OVERLOADED_FUNCTION_TEMPORARY
||
3002 fcc
->function_handler
->type
== ZEND_OVERLOADED_FUNCTION
)) {
3003 if (fcc
->function_handler
->type
!= ZEND_OVERLOADED_FUNCTION
) {
3004 efree((char*)fcc
->function_handler
->common
.function_name
);
3006 efree(fcc
->function_handler
);
3012 zval
**method
= NULL
;
3014 int strict_class
= 0;
3016 if (zend_hash_num_elements(Z_ARRVAL_P(callable
)) == 2) {
3017 zend_hash_index_find(Z_ARRVAL_P(callable
), 0, (void **) &obj
);
3018 zend_hash_index_find(Z_ARRVAL_P(callable
), 1, (void **) &method
);
3020 if (obj
&& method
&&
3021 (Z_TYPE_PP(obj
) == IS_OBJECT
||
3022 Z_TYPE_PP(obj
) == IS_STRING
) &&
3023 Z_TYPE_PP(method
) == IS_STRING
) {
3025 if (Z_TYPE_PP(obj
) == IS_STRING
) {
3026 if (callable_name
) {
3029 *callable_name_len
= Z_STRLEN_PP(obj
) + Z_STRLEN_PP(method
) + sizeof("::") - 1;
3030 ptr
= *callable_name
= emalloc(*callable_name_len
+ 1);
3031 memcpy(ptr
, Z_STRVAL_PP(obj
), Z_STRLEN_PP(obj
));
3032 ptr
+= Z_STRLEN_PP(obj
);
3033 memcpy(ptr
, "::", sizeof("::") - 1);
3034 ptr
+= sizeof("::") - 1;
3035 memcpy(ptr
, Z_STRVAL_PP(method
), Z_STRLEN_PP(method
) + 1);
3038 if (check_flags
& IS_CALLABLE_CHECK_SYNTAX_ONLY
) {
3042 if (!zend_is_callable_check_class(Z_STRVAL_PP(obj
), Z_STRLEN_PP(obj
), fcc
, &strict_class
, error TSRMLS_CC
)) {
3047 if (!EG(objects_store
).object_buckets
||
3048 !EG(objects_store
).object_buckets
[Z_OBJ_HANDLE_PP(obj
)].valid
) {
3052 fcc
->calling_scope
= Z_OBJCE_PP(obj
); /* TBFixed: what if it's overloaded? */
3054 fcc
->object_ptr
= *obj
;
3056 if (callable_name
) {
3059 *callable_name_len
= fcc
->calling_scope
->name_length
+ Z_STRLEN_PP(method
) + sizeof("::") - 1;
3060 ptr
= *callable_name
= emalloc(*callable_name_len
+ 1);
3061 memcpy(ptr
, fcc
->calling_scope
->name
, fcc
->calling_scope
->name_length
);
3062 ptr
+= fcc
->calling_scope
->name_length
;
3063 memcpy(ptr
, "::", sizeof("::") - 1);
3064 ptr
+= sizeof("::") - 1;
3065 memcpy(ptr
, Z_STRVAL_PP(method
), Z_STRLEN_PP(method
) + 1);
3068 if (check_flags
& IS_CALLABLE_CHECK_SYNTAX_ONLY
) {
3069 fcc
->called_scope
= fcc
->calling_scope
;
3074 ret
= zend_is_callable_check_func(check_flags
, *method
, fcc
, strict_class
, error TSRMLS_CC
);
3075 if (fcc
== &fcc_local
&&
3076 fcc
->function_handler
&&
3077 ((fcc
->function_handler
->type
== ZEND_INTERNAL_FUNCTION
&&
3078 (fcc
->function_handler
->common
.fn_flags
& ZEND_ACC_CALL_VIA_HANDLER
)) ||
3079 fcc
->function_handler
->type
== ZEND_OVERLOADED_FUNCTION_TEMPORARY
||
3080 fcc
->function_handler
->type
== ZEND_OVERLOADED_FUNCTION
)) {
3081 if (fcc
->function_handler
->type
!= ZEND_OVERLOADED_FUNCTION
) {
3082 efree((char*)fcc
->function_handler
->common
.function_name
);
3084 efree(fcc
->function_handler
);
3089 if (zend_hash_num_elements(Z_ARRVAL_P(callable
)) == 2) {
3090 if (!obj
|| (Z_TYPE_PP(obj
) != IS_STRING
&& Z_TYPE_PP(obj
) != IS_OBJECT
)) {
3091 if (error
) zend_spprintf(error
, 0, "first array member is not a valid class name or object");
3093 if (error
) zend_spprintf(error
, 0, "second array member is not a valid method");
3096 if (error
) zend_spprintf(error
, 0, "array must have exactly two members");
3098 if (callable_name
) {
3099 *callable_name
= estrndup("Array", sizeof("Array")-1);
3100 *callable_name_len
= sizeof("Array") - 1;
3107 if (Z_OBJ_HANDLER_P(callable
, get_closure
) && Z_OBJ_HANDLER_P(callable
, get_closure
)(callable
, &fcc
->calling_scope
, &fcc
->function_handler
, &fcc
->object_ptr TSRMLS_CC
) == SUCCESS
) {
3108 fcc
->called_scope
= fcc
->calling_scope
;
3109 if (callable_name
) {
3110 zend_class_entry
*ce
= Z_OBJCE_P(callable
); /* TBFixed: what if it's overloaded? */
3112 *callable_name_len
= ce
->name_length
+ sizeof("::__invoke") - 1;
3113 *callable_name
= emalloc(*callable_name_len
+ 1);
3114 memcpy(*callable_name
, ce
->name
, ce
->name_length
);
3115 memcpy((*callable_name
) + ce
->name_length
, "::__invoke", sizeof("::__invoke"));
3119 /* break missing intentionally */
3122 if (callable_name
) {
3126 zend_make_printable_zval(callable
, &expr_copy
, &use_copy
);
3127 *callable_name
= estrndup(Z_STRVAL(expr_copy
), Z_STRLEN(expr_copy
));
3128 *callable_name_len
= Z_STRLEN(expr_copy
);
3129 zval_dtor(&expr_copy
);
3131 if (error
) zend_spprintf(error
, 0, "no array or string given");
3137 ZEND_API zend_bool
zend_is_callable(zval
*callable
, uint check_flags
, char **callable_name TSRMLS_DC
) /* {{{ */
3139 return zend_is_callable_ex(callable
, NULL
, check_flags
, callable_name
, NULL
, NULL
, NULL TSRMLS_CC
);
3143 ZEND_API zend_bool
zend_make_callable(zval
*callable
, char **callable_name TSRMLS_DC
) /* {{{ */
3145 zend_fcall_info_cache fcc
;
3147 if (zend_is_callable_ex(callable
, NULL
, IS_CALLABLE_STRICT
, callable_name
, NULL
, &fcc
, NULL TSRMLS_CC
)) {
3148 if (Z_TYPE_P(callable
) == IS_STRING
&& fcc
.calling_scope
) {
3149 zval_dtor(callable
);
3150 array_init(callable
);
3151 add_next_index_string(callable
, fcc
.calling_scope
->name
, 1);
3152 add_next_index_string(callable
, fcc
.function_handler
->common
.function_name
, 1);
3154 if (fcc
.function_handler
&&
3155 ((fcc
.function_handler
->type
== ZEND_INTERNAL_FUNCTION
&&
3156 (fcc
.function_handler
->common
.fn_flags
& ZEND_ACC_CALL_VIA_HANDLER
)) ||
3157 fcc
.function_handler
->type
== ZEND_OVERLOADED_FUNCTION_TEMPORARY
||
3158 fcc
.function_handler
->type
== ZEND_OVERLOADED_FUNCTION
)) {
3159 if (fcc
.function_handler
->type
!= ZEND_OVERLOADED_FUNCTION
) {
3160 efree((char*)fcc
.function_handler
->common
.function_name
);
3162 efree(fcc
.function_handler
);
3170 ZEND_API
int zend_fcall_info_init(zval
*callable
, uint check_flags
, zend_fcall_info
*fci
, zend_fcall_info_cache
*fcc
, char **callable_name
, char **error TSRMLS_DC
) /* {{{ */
3172 if (!zend_is_callable_ex(callable
, NULL
, check_flags
, callable_name
, NULL
, fcc
, error TSRMLS_CC
)) {
3176 fci
->size
= sizeof(*fci
);
3177 fci
->function_table
= fcc
->calling_scope
? &fcc
->calling_scope
->function_table
: EG(function_table
);
3178 fci
->object_ptr
= fcc
->object_ptr
;
3179 fci
->function_name
= callable
;
3180 fci
->retval_ptr_ptr
= NULL
;
3181 fci
->param_count
= 0;
3183 fci
->no_separation
= 1;
3184 fci
->symbol_table
= NULL
;
3190 ZEND_API
void zend_fcall_info_args_clear(zend_fcall_info
*fci
, int free_mem
) /* {{{ */
3198 fci
->param_count
= 0;
3202 ZEND_API
void zend_fcall_info_args_save(zend_fcall_info
*fci
, int *param_count
, zval
****params
) /* {{{ */
3204 *param_count
= fci
->param_count
;
3205 *params
= fci
->params
;
3206 fci
->param_count
= 0;
3211 ZEND_API
void zend_fcall_info_args_restore(zend_fcall_info
*fci
, int param_count
, zval
***params
) /* {{{ */
3213 zend_fcall_info_args_clear(fci
, 1);
3214 fci
->param_count
= param_count
;
3215 fci
->params
= params
;
3219 ZEND_API
int zend_fcall_info_args(zend_fcall_info
*fci
, zval
*args TSRMLS_DC
) /* {{{ */
3222 zval
**arg
, ***params
;
3224 zend_fcall_info_args_clear(fci
, !args
);
3230 if (Z_TYPE_P(args
) != IS_ARRAY
) {
3234 fci
->param_count
= zend_hash_num_elements(Z_ARRVAL_P(args
));
3235 fci
->params
= params
= (zval
***) erealloc(fci
->params
, fci
->param_count
* sizeof(zval
**));
3237 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args
), &pos
);
3238 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args
), (void *) &arg
, &pos
) == SUCCESS
) {
3240 zend_hash_move_forward_ex(Z_ARRVAL_P(args
), &pos
);
3247 ZEND_API
int zend_fcall_info_argp(zend_fcall_info
*fci TSRMLS_DC
, int argc
, zval
***argv
) /* {{{ */
3255 zend_fcall_info_args_clear(fci
, !argc
);
3258 fci
->param_count
= argc
;
3259 fci
->params
= (zval
***) erealloc(fci
->params
, fci
->param_count
* sizeof(zval
**));
3261 for (i
= 0; i
< argc
; ++i
) {
3262 fci
->params
[i
] = argv
[i
];
3270 ZEND_API
int zend_fcall_info_argv(zend_fcall_info
*fci TSRMLS_DC
, int argc
, va_list *argv
) /* {{{ */
3279 zend_fcall_info_args_clear(fci
, !argc
);
3282 fci
->param_count
= argc
;
3283 fci
->params
= (zval
***) erealloc(fci
->params
, fci
->param_count
* sizeof(zval
**));
3285 for (i
= 0; i
< argc
; ++i
) {
3286 arg
= va_arg(*argv
, zval
**);
3287 fci
->params
[i
] = arg
;
3295 ZEND_API
int zend_fcall_info_argn(zend_fcall_info
*fci TSRMLS_DC
, int argc
, ...) /* {{{ */
3300 va_start(argv
, argc
);
3301 ret
= zend_fcall_info_argv(fci TSRMLS_CC
, argc
, &argv
);
3308 ZEND_API
int zend_fcall_info_call(zend_fcall_info
*fci
, zend_fcall_info_cache
*fcc
, zval
**retval_ptr_ptr
, zval
*args TSRMLS_DC
) /* {{{ */
3310 zval
*retval
, ***org_params
= NULL
;
3311 int result
, org_count
= 0;
3313 fci
->retval_ptr_ptr
= retval_ptr_ptr
? retval_ptr_ptr
: &retval
;
3315 zend_fcall_info_args_save(fci
, &org_count
, &org_params
);
3316 zend_fcall_info_args(fci
, args TSRMLS_CC
);
3318 result
= zend_call_function(fci
, fcc TSRMLS_CC
);
3320 if (!retval_ptr_ptr
&& retval
) {
3321 zval_ptr_dtor(&retval
);
3324 zend_fcall_info_args_restore(fci
, org_count
, org_params
);
3330 ZEND_API
const char *zend_get_module_version(const char *module_name
) /* {{{ */
3333 int name_len
= strlen(module_name
);
3334 zend_module_entry
*module
;
3336 lname
= zend_str_tolower_dup(module_name
, name_len
);
3337 if (zend_hash_find(&module_registry
, lname
, name_len
+ 1, (void**)&module
) == FAILURE
) {
3342 return module
->version
;
3346 ZEND_API
int zend_declare_property_ex(zend_class_entry
*ce
, const char *name
, int name_length
, zval
*property
, int access_type
, const char *doc_comment
, int doc_comment_len TSRMLS_DC
) /* {{{ */
3348 zend_property_info property_info
, *property_info_ptr
;
3349 const char *interned_name
;
3350 ulong h
= zend_get_hash_value(name
, name_length
+1);
3352 if (!(access_type
& ZEND_ACC_PPP_MASK
)) {
3353 access_type
|= ZEND_ACC_PUBLIC
;
3355 if (access_type
& ZEND_ACC_STATIC
) {
3356 if (zend_hash_quick_find(&ce
->properties_info
, name
, name_length
+ 1, h
, (void**)&property_info_ptr
) == SUCCESS
&&
3357 (property_info_ptr
->flags
& ZEND_ACC_STATIC
) != 0) {
3358 property_info
.offset
= property_info_ptr
->offset
;
3359 zval_ptr_dtor(&ce
->default_static_members_table
[property_info
.offset
]);
3360 zend_hash_quick_del(&ce
->properties_info
, name
, name_length
+ 1, h
);
3362 property_info
.offset
= ce
->default_static_members_count
++;
3363 ce
->default_static_members_table
= perealloc(ce
->default_static_members_table
, sizeof(zval
*) * ce
->default_static_members_count
, ce
->type
== ZEND_INTERNAL_CLASS
);
3365 ce
->default_static_members_table
[property_info
.offset
] = property
;
3366 if (ce
->type
== ZEND_USER_CLASS
) {
3367 ce
->static_members_table
= ce
->default_static_members_table
;
3370 if (zend_hash_quick_find(&ce
->properties_info
, name
, name_length
+ 1, h
, (void**)&property_info_ptr
) == SUCCESS
&&
3371 (property_info_ptr
->flags
& ZEND_ACC_STATIC
) == 0) {
3372 property_info
.offset
= property_info_ptr
->offset
;
3373 zval_ptr_dtor(&ce
->default_properties_table
[property_info
.offset
]);
3374 zend_hash_quick_del(&ce
->properties_info
, name
, name_length
+ 1, h
);
3376 property_info
.offset
= ce
->default_properties_count
++;
3377 ce
->default_properties_table
= perealloc(ce
->default_properties_table
, sizeof(zval
*) * ce
->default_properties_count
, ce
->type
== ZEND_INTERNAL_CLASS
);
3379 ce
->default_properties_table
[property_info
.offset
] = property
;
3381 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3382 switch(Z_TYPE_P(property
)) {
3384 case IS_CONSTANT_ARRAY
:
3387 zend_error(E_CORE_ERROR
, "Internal zval's can't be arrays, objects or resources");
3393 switch (access_type
& ZEND_ACC_PPP_MASK
) {
3394 case ZEND_ACC_PRIVATE
: {
3396 int priv_name_length
;
3398 zend_mangle_property_name(&priv_name
, &priv_name_length
, ce
->name
, ce
->name_length
, name
, name_length
, ce
->type
& ZEND_INTERNAL_CLASS
);
3399 property_info
.name
= priv_name
;
3400 property_info
.name_length
= priv_name_length
;
3403 case ZEND_ACC_PROTECTED
: {
3405 int prot_name_length
;
3407 zend_mangle_property_name(&prot_name
, &prot_name_length
, "*", 1, name
, name_length
, ce
->type
& ZEND_INTERNAL_CLASS
);
3408 property_info
.name
= prot_name
;
3409 property_info
.name_length
= prot_name_length
;
3412 case ZEND_ACC_PUBLIC
:
3413 if (IS_INTERNED(name
)) {
3414 property_info
.name
= (char*)name
;
3416 property_info
.name
= ce
->type
& ZEND_INTERNAL_CLASS
? zend_strndup(name
, name_length
) : estrndup(name
, name_length
);
3418 property_info
.name_length
= name_length
;
3422 interned_name
= zend_new_interned_string(property_info
.name
, property_info
.name_length
+1, 0 TSRMLS_CC
);
3423 if (interned_name
!= property_info
.name
) {
3424 if (ce
->type
== ZEND_USER_CLASS
) {
3425 efree((char*)property_info
.name
);
3427 free((char*)property_info
.name
);
3429 property_info
.name
= interned_name
;
3432 property_info
.flags
= access_type
;
3433 property_info
.h
= (access_type
& ZEND_ACC_PUBLIC
) ? h
: zend_get_hash_value(property_info
.name
, property_info
.name_length
+1);
3435 property_info
.doc_comment
= doc_comment
;
3436 property_info
.doc_comment_len
= doc_comment_len
;
3438 property_info
.ce
= ce
;
3440 zend_hash_quick_update(&ce
->properties_info
, name
, name_length
+1, h
, &property_info
, sizeof(zend_property_info
), NULL
);
3446 ZEND_API
int zend_declare_property(zend_class_entry
*ce
, const char *name
, int name_length
, zval
*property
, int access_type TSRMLS_DC
) /* {{{ */
3448 return zend_declare_property_ex(ce
, name
, name_length
, property
, access_type
, NULL
, 0 TSRMLS_CC
);
3452 ZEND_API
int zend_declare_property_null(zend_class_entry
*ce
, const char *name
, int name_length
, int access_type TSRMLS_DC
) /* {{{ */
3456 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3457 ALLOC_PERMANENT_ZVAL(property
);
3459 ALLOC_ZVAL(property
);
3461 INIT_ZVAL(*property
);
3462 return zend_declare_property(ce
, name
, name_length
, property
, access_type TSRMLS_CC
);
3466 ZEND_API
int zend_declare_property_bool(zend_class_entry
*ce
, const char *name
, int name_length
, long value
, int access_type TSRMLS_DC
) /* {{{ */
3470 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3471 ALLOC_PERMANENT_ZVAL(property
);
3473 ALLOC_ZVAL(property
);
3475 INIT_PZVAL(property
);
3476 ZVAL_BOOL(property
, value
);
3477 return zend_declare_property(ce
, name
, name_length
, property
, access_type TSRMLS_CC
);
3481 ZEND_API
int zend_declare_property_long(zend_class_entry
*ce
, const char *name
, int name_length
, long value
, int access_type TSRMLS_DC
) /* {{{ */
3485 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3486 ALLOC_PERMANENT_ZVAL(property
);
3488 ALLOC_ZVAL(property
);
3490 INIT_PZVAL(property
);
3491 ZVAL_LONG(property
, value
);
3492 return zend_declare_property(ce
, name
, name_length
, property
, access_type TSRMLS_CC
);
3496 ZEND_API
int zend_declare_property_double(zend_class_entry
*ce
, const char *name
, int name_length
, double value
, int access_type TSRMLS_DC
) /* {{{ */
3500 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3501 ALLOC_PERMANENT_ZVAL(property
);
3503 ALLOC_ZVAL(property
);
3505 INIT_PZVAL(property
);
3506 ZVAL_DOUBLE(property
, value
);
3507 return zend_declare_property(ce
, name
, name_length
, property
, access_type TSRMLS_CC
);
3511 ZEND_API
int zend_declare_property_string(zend_class_entry
*ce
, const char *name
, int name_length
, const char *value
, int access_type TSRMLS_DC
) /* {{{ */
3514 int len
= strlen(value
);
3516 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3517 ALLOC_PERMANENT_ZVAL(property
);
3518 ZVAL_STRINGL(property
, zend_strndup(value
, len
), len
, 0);
3520 ALLOC_ZVAL(property
);
3521 ZVAL_STRINGL(property
, value
, len
, 1);
3523 INIT_PZVAL(property
);
3524 return zend_declare_property(ce
, name
, name_length
, property
, access_type TSRMLS_CC
);
3528 ZEND_API
int zend_declare_property_stringl(zend_class_entry
*ce
, const char *name
, int name_length
, const char *value
, int value_len
, int access_type TSRMLS_DC
) /* {{{ */
3532 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3533 ALLOC_PERMANENT_ZVAL(property
);
3534 ZVAL_STRINGL(property
, zend_strndup(value
, value_len
), value_len
, 0);
3536 ALLOC_ZVAL(property
);
3537 ZVAL_STRINGL(property
, value
, value_len
, 1);
3539 INIT_PZVAL(property
);
3540 return zend_declare_property(ce
, name
, name_length
, property
, access_type TSRMLS_CC
);
3544 ZEND_API
int zend_declare_class_constant(zend_class_entry
*ce
, const char *name
, size_t name_length
, zval
*value TSRMLS_DC
) /* {{{ */
3546 return zend_hash_update(&ce
->constants_table
, name
, name_length
+1, &value
, sizeof(zval
*), NULL
);
3550 ZEND_API
int zend_declare_class_constant_null(zend_class_entry
*ce
, const char *name
, size_t name_length TSRMLS_DC
) /* {{{ */
3554 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3555 ALLOC_PERMANENT_ZVAL(constant
);
3557 ALLOC_ZVAL(constant
);
3559 ZVAL_NULL(constant
);
3560 INIT_PZVAL(constant
);
3561 return zend_declare_class_constant(ce
, name
, name_length
, constant TSRMLS_CC
);
3565 ZEND_API
int zend_declare_class_constant_long(zend_class_entry
*ce
, const char *name
, size_t name_length
, long value TSRMLS_DC
) /* {{{ */
3569 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3570 ALLOC_PERMANENT_ZVAL(constant
);
3572 ALLOC_ZVAL(constant
);
3574 ZVAL_LONG(constant
, value
);
3575 INIT_PZVAL(constant
);
3576 return zend_declare_class_constant(ce
, name
, name_length
, constant TSRMLS_CC
);
3580 ZEND_API
int zend_declare_class_constant_bool(zend_class_entry
*ce
, const char *name
, size_t name_length
, zend_bool value TSRMLS_DC
) /* {{{ */
3584 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3585 ALLOC_PERMANENT_ZVAL(constant
);
3587 ALLOC_ZVAL(constant
);
3589 ZVAL_BOOL(constant
, value
);
3590 INIT_PZVAL(constant
);
3591 return zend_declare_class_constant(ce
, name
, name_length
, constant TSRMLS_CC
);
3595 ZEND_API
int zend_declare_class_constant_double(zend_class_entry
*ce
, const char *name
, size_t name_length
, double value TSRMLS_DC
) /* {{{ */
3599 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3600 ALLOC_PERMANENT_ZVAL(constant
);
3602 ALLOC_ZVAL(constant
);
3604 ZVAL_DOUBLE(constant
, value
);
3605 INIT_PZVAL(constant
);
3606 return zend_declare_class_constant(ce
, name
, name_length
, constant TSRMLS_CC
);
3610 ZEND_API
int zend_declare_class_constant_stringl(zend_class_entry
*ce
, const char *name
, size_t name_length
, const char *value
, size_t value_length TSRMLS_DC
) /* {{{ */
3614 if (ce
->type
& ZEND_INTERNAL_CLASS
) {
3615 ALLOC_PERMANENT_ZVAL(constant
);
3616 ZVAL_STRINGL(constant
, zend_strndup(value
, value_length
), value_length
, 0);
3618 ALLOC_ZVAL(constant
);
3619 ZVAL_STRINGL(constant
, value
, value_length
, 1);
3621 INIT_PZVAL(constant
);
3622 return zend_declare_class_constant(ce
, name
, name_length
, constant TSRMLS_CC
);
3626 ZEND_API
int zend_declare_class_constant_string(zend_class_entry
*ce
, const char *name
, size_t name_length
, const char *value TSRMLS_DC
) /* {{{ */
3628 return zend_declare_class_constant_stringl(ce
, name
, name_length
, value
, strlen(value
) TSRMLS_CC
);
3632 ZEND_API
void zend_update_property(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, zval
*value TSRMLS_DC
) /* {{{ */
3635 zend_class_entry
*old_scope
= EG(scope
);
3639 if (!Z_OBJ_HT_P(object
)->write_property
) {
3640 const char *class_name
;
3641 zend_uint class_name_len
;
3643 zend_get_object_classname(object
, &class_name
, &class_name_len TSRMLS_CC
);
3645 zend_error(E_CORE_ERROR
, "Property %s of class %s cannot be updated", name
, class_name
);
3647 MAKE_STD_ZVAL(property
);
3648 ZVAL_STRINGL(property
, name
, name_length
, 1);
3649 Z_OBJ_HT_P(object
)->write_property(object
, property
, value
, 0 TSRMLS_CC
);
3650 zval_ptr_dtor(&property
);
3652 EG(scope
) = old_scope
;
3656 ZEND_API
void zend_update_property_null(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length TSRMLS_DC
) /* {{{ */
3661 Z_UNSET_ISREF_P(tmp
);
3662 Z_SET_REFCOUNT_P(tmp
, 0);
3664 zend_update_property(scope
, object
, name
, name_length
, tmp TSRMLS_CC
);
3668 ZEND_API
void zend_update_property_bool(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, long value TSRMLS_DC
) /* {{{ */
3673 Z_UNSET_ISREF_P(tmp
);
3674 Z_SET_REFCOUNT_P(tmp
, 0);
3675 ZVAL_BOOL(tmp
, value
);
3676 zend_update_property(scope
, object
, name
, name_length
, tmp TSRMLS_CC
);
3680 ZEND_API
void zend_update_property_long(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, long value TSRMLS_DC
) /* {{{ */
3685 Z_UNSET_ISREF_P(tmp
);
3686 Z_SET_REFCOUNT_P(tmp
, 0);
3687 ZVAL_LONG(tmp
, value
);
3688 zend_update_property(scope
, object
, name
, name_length
, tmp TSRMLS_CC
);
3692 ZEND_API
void zend_update_property_double(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, double value TSRMLS_DC
) /* {{{ */
3697 Z_UNSET_ISREF_P(tmp
);
3698 Z_SET_REFCOUNT_P(tmp
, 0);
3699 ZVAL_DOUBLE(tmp
, value
);
3700 zend_update_property(scope
, object
, name
, name_length
, tmp TSRMLS_CC
);
3704 ZEND_API
void zend_update_property_string(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, const char *value TSRMLS_DC
) /* {{{ */
3709 Z_UNSET_ISREF_P(tmp
);
3710 Z_SET_REFCOUNT_P(tmp
, 0);
3711 ZVAL_STRING(tmp
, value
, 1);
3712 zend_update_property(scope
, object
, name
, name_length
, tmp TSRMLS_CC
);
3716 ZEND_API
void zend_update_property_stringl(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, const char *value
, int value_len TSRMLS_DC
) /* {{{ */
3721 Z_UNSET_ISREF_P(tmp
);
3722 Z_SET_REFCOUNT_P(tmp
, 0);
3723 ZVAL_STRINGL(tmp
, value
, value_len
, 1);
3724 zend_update_property(scope
, object
, name
, name_length
, tmp TSRMLS_CC
);
3728 ZEND_API
int zend_update_static_property(zend_class_entry
*scope
, const char *name
, int name_length
, zval
*value TSRMLS_DC
) /* {{{ */
3731 zend_class_entry
*old_scope
= EG(scope
);
3734 property
= zend_std_get_static_property(scope
, name
, name_length
, 0, NULL TSRMLS_CC
);
3735 EG(scope
) = old_scope
;
3739 if (*property
!= value
) {
3740 if (PZVAL_IS_REF(*property
)) {
3741 zval_dtor(*property
);
3742 Z_TYPE_PP(property
) = Z_TYPE_P(value
);
3743 (*property
)->value
= value
->value
;
3744 if (Z_REFCOUNT_P(value
) > 0) {
3745 zval_copy_ctor(*property
);
3750 zval
*garbage
= *property
;
3753 if (PZVAL_IS_REF(value
)) {
3754 SEPARATE_ZVAL(&value
);
3757 zval_ptr_dtor(&garbage
);
3765 ZEND_API
int zend_update_static_property_null(zend_class_entry
*scope
, const char *name
, int name_length TSRMLS_DC
) /* {{{ */
3770 Z_UNSET_ISREF_P(tmp
);
3771 Z_SET_REFCOUNT_P(tmp
, 0);
3773 return zend_update_static_property(scope
, name
, name_length
, tmp TSRMLS_CC
);
3777 ZEND_API
int zend_update_static_property_bool(zend_class_entry
*scope
, const char *name
, int name_length
, long value TSRMLS_DC
) /* {{{ */
3782 Z_UNSET_ISREF_P(tmp
);
3783 Z_SET_REFCOUNT_P(tmp
, 0);
3784 ZVAL_BOOL(tmp
, value
);
3785 return zend_update_static_property(scope
, name
, name_length
, tmp TSRMLS_CC
);
3789 ZEND_API
int zend_update_static_property_long(zend_class_entry
*scope
, const char *name
, int name_length
, long value TSRMLS_DC
) /* {{{ */
3794 Z_UNSET_ISREF_P(tmp
);
3795 Z_SET_REFCOUNT_P(tmp
, 0);
3796 ZVAL_LONG(tmp
, value
);
3797 return zend_update_static_property(scope
, name
, name_length
, tmp TSRMLS_CC
);
3801 ZEND_API
int zend_update_static_property_double(zend_class_entry
*scope
, const char *name
, int name_length
, double value TSRMLS_DC
) /* {{{ */
3806 Z_UNSET_ISREF_P(tmp
);
3807 Z_SET_REFCOUNT_P(tmp
, 0);
3808 ZVAL_DOUBLE(tmp
, value
);
3809 return zend_update_static_property(scope
, name
, name_length
, tmp TSRMLS_CC
);
3813 ZEND_API
int zend_update_static_property_string(zend_class_entry
*scope
, const char *name
, int name_length
, const char *value TSRMLS_DC
) /* {{{ */
3818 Z_UNSET_ISREF_P(tmp
);
3819 Z_SET_REFCOUNT_P(tmp
, 0);
3820 ZVAL_STRING(tmp
, value
, 1);
3821 return zend_update_static_property(scope
, name
, name_length
, tmp TSRMLS_CC
);
3825 ZEND_API
int zend_update_static_property_stringl(zend_class_entry
*scope
, const char *name
, int name_length
, const char *value
, int value_len TSRMLS_DC
) /* {{{ */
3830 Z_UNSET_ISREF_P(tmp
);
3831 Z_SET_REFCOUNT_P(tmp
, 0);
3832 ZVAL_STRINGL(tmp
, value
, value_len
, 1);
3833 return zend_update_static_property(scope
, name
, name_length
, tmp TSRMLS_CC
);
3837 ZEND_API zval
*zend_read_property(zend_class_entry
*scope
, zval
*object
, const char *name
, int name_length
, zend_bool silent TSRMLS_DC
) /* {{{ */
3839 zval
*property
, *value
;
3840 zend_class_entry
*old_scope
= EG(scope
);
3844 if (!Z_OBJ_HT_P(object
)->read_property
) {
3845 const char *class_name
;
3846 zend_uint class_name_len
;
3848 zend_get_object_classname(object
, &class_name
, &class_name_len TSRMLS_CC
);
3849 zend_error(E_CORE_ERROR
, "Property %s of class %s cannot be read", name
, class_name
);
3852 MAKE_STD_ZVAL(property
);
3853 ZVAL_STRINGL(property
, name
, name_length
, 1);
3854 value
= Z_OBJ_HT_P(object
)->read_property(object
, property
, silent
?BP_VAR_IS
:BP_VAR_R
, 0 TSRMLS_CC
);
3855 zval_ptr_dtor(&property
);
3857 EG(scope
) = old_scope
;
3862 ZEND_API zval
*zend_read_static_property(zend_class_entry
*scope
, const char *name
, int name_length
, zend_bool silent TSRMLS_DC
) /* {{{ */
3865 zend_class_entry
*old_scope
= EG(scope
);
3868 property
= zend_std_get_static_property(scope
, name
, name_length
, silent
, NULL TSRMLS_CC
);
3869 EG(scope
) = old_scope
;
3871 return property
?*property
:NULL
;
3875 ZEND_API
void zend_save_error_handling(zend_error_handling
*current TSRMLS_DC
) /* {{{ */
3877 current
->handling
= EG(error_handling
);
3878 current
->exception
= EG(exception_class
);
3879 current
->user_handler
= EG(user_error_handler
);
3880 if (current
->user_handler
) {
3881 Z_ADDREF_P(current
->user_handler
);
3886 ZEND_API
void zend_replace_error_handling(zend_error_handling_t error_handling
, zend_class_entry
*exception_class
, zend_error_handling
*current TSRMLS_DC
) /* {{{ */
3889 zend_save_error_handling(current TSRMLS_CC
);
3890 if (error_handling
!= EH_NORMAL
&& EG(user_error_handler
)) {
3891 zval_ptr_dtor(&EG(user_error_handler
));
3892 EG(user_error_handler
) = NULL
;
3895 EG(error_handling
) = error_handling
;
3896 EG(exception_class
) = error_handling
== EH_THROW
? exception_class
: NULL
;
3900 ZEND_API
void zend_restore_error_handling(zend_error_handling
*saved TSRMLS_DC
) /* {{{ */
3902 EG(error_handling
) = saved
->handling
;
3903 EG(exception_class
) = saved
->handling
== EH_THROW
? saved
->exception
: NULL
;
3904 if (saved
->user_handler
&& saved
->user_handler
!= EG(user_error_handler
)) {
3905 if (EG(user_error_handler
)) {
3906 zval_ptr_dtor(&EG(user_error_handler
));
3908 EG(user_error_handler
) = saved
->user_handler
;
3909 } else if (saved
->user_handler
) {
3910 zval_ptr_dtor(&saved
->user_handler
);
3912 saved
->user_handler
= NULL
;
3916 ZEND_API
const char* zend_find_alias_name(zend_class_entry
*ce
, const char *name
, zend_uint len
) /* {{{ */
3918 zend_trait_alias
*alias
, **alias_ptr
;
3920 alias_ptr
= ce
->trait_aliases
;
3923 if (alias
->alias_len
== len
&&
3924 !strncasecmp(name
, alias
->alias
, alias
->alias_len
)) {
3925 return alias
->alias
;
3935 ZEND_API
const char* zend_resolve_method_name(zend_class_entry
*ce
, zend_function
*f
) /* {{{ */
3937 zend_function
*func
;
3938 HashPosition iterator
;
3939 HashTable
*function_table
;
3941 if (f
->common
.type
!= ZEND_USER_FUNCTION
||
3942 *(f
->op_array
.refcount
) < 2 ||
3944 !f
->common
.scope
->trait_aliases
) {
3945 return f
->common
.function_name
;
3948 function_table
= &ce
->function_table
;
3949 zend_hash_internal_pointer_reset_ex(function_table
, &iterator
);
3950 while (zend_hash_get_current_data_ex(function_table
, (void **)&func
, &iterator
) == SUCCESS
) {
3956 if (zend_hash_get_current_key_ex(function_table
, &name
, &len
, &idx
, 0, &iterator
) != HASH_KEY_IS_STRING
) {
3957 return f
->common
.function_name
;
3960 if (len
== strlen(f
->common
.function_name
) &&
3961 !strncasecmp(name
, f
->common
.function_name
, len
)) {
3962 return f
->common
.function_name
;
3964 return zend_find_alias_name(f
->common
.scope
, name
, len
);
3966 zend_hash_move_forward_ex(function_table
, &iterator
);
3968 return f
->common
.function_name
;
3976 * indent-tabs-mode: t