Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / php / Zend / zend_API.c
blob529092ab925b60493f9cab7c7da9e435378180fc
1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
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 +----------------------------------------------------------------------+
21 /* $Id$ */
23 #include "zend.h"
24 #include "zend_execute.h"
25 #include "zend_API.h"
26 #include "zend_modules.h"
27 #include "zend_constants.h"
28 #include "zend_exceptions.h"
29 #include "zend_closures.h"
31 #ifdef HAVE_STDARG_H
32 #include <stdarg.h>
33 #endif
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, ...) /* {{{ */
47 void **p;
48 int arg_count;
49 va_list ptr;
50 zval **param, *param_ptr;
51 TSRMLS_FETCH();
53 p = zend_vm_stack_top(TSRMLS_C) - 1;
54 arg_count = (int)(zend_uintptr_t) *p;
56 if (param_count>arg_count) {
57 return FAILURE;
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) {
66 zval *new_tmp;
68 ALLOC_ZVAL(new_tmp);
69 *new_tmp = *param_ptr;
70 zval_copy_ctor(new_tmp);
71 INIT_PZVAL(new_tmp);
72 param_ptr = new_tmp;
73 Z_DELREF_P((zval *) *(p-arg_count));
74 *(p-arg_count) = param_ptr;
76 *param = param_ptr;
77 arg_count--;
79 va_end(ptr);
81 return SUCCESS;
83 /* }}} */
85 ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */
87 void **p;
88 int arg_count;
89 zval *param_ptr;
91 p = zend_vm_stack_top(TSRMLS_C) - 1;
92 arg_count = (int)(zend_uintptr_t) *p;
94 if (param_count>arg_count) {
95 return FAILURE;
98 while (param_count-->0) {
99 param_ptr = *(p-arg_count);
100 if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
101 zval *new_tmp;
103 ALLOC_ZVAL(new_tmp);
104 *new_tmp = *param_ptr;
105 zval_copy_ctor(new_tmp);
106 INIT_PZVAL(new_tmp);
107 param_ptr = new_tmp;
108 Z_DELREF_P((zval *) *(p-arg_count));
109 *(p-arg_count) = param_ptr;
111 *(argument_array++) = param_ptr;
112 arg_count--;
115 return SUCCESS;
117 /* }}} */
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, ...) /* {{{ */
123 void **p;
124 int arg_count;
125 va_list ptr;
126 zval ***param;
127 TSRMLS_FETCH();
129 p = zend_vm_stack_top(TSRMLS_C) - 1;
130 arg_count = (int)(zend_uintptr_t) *p;
132 if (param_count>arg_count) {
133 return FAILURE;
136 va_start(ptr, param_count);
137 while (param_count-->0) {
138 param = va_arg(ptr, zval ***);
139 *param = (zval **) p-(arg_count--);
141 va_end(ptr);
143 return SUCCESS;
145 /* }}} */
147 ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */
149 void **p;
150 int arg_count;
152 p = zend_vm_stack_top(TSRMLS_C) - 1;
153 arg_count = (int)(zend_uintptr_t) *p;
155 if (param_count>arg_count) {
156 return FAILURE;
159 while (param_count-->0) {
160 zval **value = (zval**)(p-arg_count);
162 *(argument_array++) = value;
163 arg_count--;
166 return SUCCESS;
168 /* }}} */
170 ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
172 void **p;
173 int arg_count;
175 p = zend_vm_stack_top(TSRMLS_C) - 1;
176 arg_count = (int)(zend_uintptr_t) *p;
178 if (param_count>arg_count) {
179 return FAILURE;
182 while (param_count-->0) {
183 zval **param = (zval **) p-(arg_count--);
184 zval_add_ref(param);
185 add_next_index_zval(argument_array, *param);
188 return SUCCESS;
190 /* }}} */
192 ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */
194 const char *space;
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));
199 /* }}} */
201 /* Argument parsing API -- andrei */
202 ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
204 switch(type) {
205 case IS_BOOL:
206 return "boolean";
207 case IS_LONG:
208 return "integer";
209 case IS_DOUBLE:
210 return "double";
211 case IS_STRING:
212 return "string";
213 case IS_OBJECT:
214 return "object";
215 case IS_RESOURCE:
216 return "resource";
217 case IS_NULL:
218 return "null";
219 case IS_CALLABLE:
220 return "callable";
221 case IS_ARRAY:
222 return "array";
223 default:
224 return "unknown";
227 /* }}} */
229 ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
231 return zend_get_type_by_const(Z_TYPE_P(arg));
233 /* }}} */
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);
239 } else {
240 zend_error(E_ERROR, "Class entry requested for an object without PHP class");
241 return NULL;
244 /* }}} */
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;
255 return 1;
257 return 0;
259 /* }}} */
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)) {
264 zval *obj;
265 MAKE_STD_ZVAL(obj);
266 if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, type TSRMLS_CC) == SUCCESS) {
267 zval_ptr_dtor(arg);
268 *arg = obj;
269 *pl = Z_STRLEN_PP(arg);
270 *p = Z_STRVAL_PP(arg);
271 return SUCCESS;
273 efree(obj);
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);
281 return SUCCESS;
284 if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
285 int use_copy;
286 zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
287 Z_ADDREF_P(z);
288 if(Z_TYPE_P(z) != IS_OBJECT) {
289 zval_dtor(*arg);
290 Z_TYPE_P(*arg) = IS_NULL;
291 zend_make_printable_zval(z, *arg, &use_copy);
292 if (!use_copy) {
293 ZVAL_ZVAL(*arg, z, 1, 1);
295 *pl = Z_STRLEN_PP(arg);
296 *p = Z_STRVAL_PP(arg);
297 return SUCCESS;
299 zval_ptr_dtor(&z);
301 return FAILURE;
303 /* }}} */
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++;
309 int return_null = 0;
311 /* scan through modifiers */
312 while (1) {
313 if (*spec_walk == '/') {
314 SEPARATE_ZVAL_IF_NOT_REF(arg);
315 } else if (*spec_walk == '!') {
316 if (Z_TYPE_PP(arg) == IS_NULL) {
317 return_null = 1;
319 } else {
320 break;
322 spec_walk++;
325 switch (c) {
326 case 'l':
327 case 'L':
329 long *p = va_arg(*va, long *);
330 switch (Z_TYPE_PP(arg)) {
331 case IS_STRING:
333 double d;
334 int type;
336 if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) {
337 return "long";
338 } else if (type == IS_DOUBLE) {
339 if (c == 'L') {
340 if (d > LONG_MAX) {
341 *p = LONG_MAX;
342 break;
343 } else if (d < LONG_MIN) {
344 *p = LONG_MIN;
345 break;
349 *p = zend_dval_to_lval(d);
352 break;
354 case IS_DOUBLE:
355 if (c == 'L') {
356 if (Z_DVAL_PP(arg) > LONG_MAX) {
357 *p = LONG_MAX;
358 break;
359 } else if (Z_DVAL_PP(arg) < LONG_MIN) {
360 *p = LONG_MIN;
361 break;
364 case IS_NULL:
365 case IS_LONG:
366 case IS_BOOL:
367 convert_to_long_ex(arg);
368 *p = Z_LVAL_PP(arg);
369 break;
371 case IS_ARRAY:
372 case IS_OBJECT:
373 case IS_RESOURCE:
374 default:
375 return "long";
378 break;
380 case 'd':
382 double *p = va_arg(*va, double *);
383 switch (Z_TYPE_PP(arg)) {
384 case IS_STRING:
386 long l;
387 int type;
389 if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) {
390 return "double";
391 } else if (type == IS_LONG) {
392 *p = (double) l;
395 break;
397 case IS_NULL:
398 case IS_LONG:
399 case IS_DOUBLE:
400 case IS_BOOL:
401 convert_to_double_ex(arg);
402 *p = Z_DVAL_PP(arg);
403 break;
405 case IS_ARRAY:
406 case IS_OBJECT:
407 case IS_RESOURCE:
408 default:
409 return "double";
412 break;
414 case 'p':
415 case 's':
417 char **p = va_arg(*va, char **);
418 int *pl = va_arg(*va, int *);
419 switch (Z_TYPE_PP(arg)) {
420 case IS_NULL:
421 if (return_null) {
422 *p = NULL;
423 *pl = 0;
424 break;
426 /* break omitted intentionally */
428 case IS_STRING:
429 case IS_LONG:
430 case IS_DOUBLE:
431 case IS_BOOL:
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 */
437 SEPARATE_ZVAL(arg);
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";
444 break;
446 case IS_OBJECT:
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";
451 break;
454 case IS_ARRAY:
455 case IS_RESOURCE:
456 default:
457 return c == 's' ? "string" : "a valid path";
460 break;
462 case 'b':
464 zend_bool *p = va_arg(*va, zend_bool *);
465 switch (Z_TYPE_PP(arg)) {
466 case IS_NULL:
467 case IS_STRING:
468 case IS_LONG:
469 case IS_DOUBLE:
470 case IS_BOOL:
471 convert_to_boolean_ex(arg);
472 *p = Z_BVAL_PP(arg);
473 break;
475 case IS_ARRAY:
476 case IS_OBJECT:
477 case IS_RESOURCE:
478 default:
479 return "boolean";
482 break;
484 case 'r':
486 zval **p = va_arg(*va, zval **);
487 if (return_null) {
488 *p = NULL;
489 break;
491 if (Z_TYPE_PP(arg) == IS_RESOURCE) {
492 *p = *arg;
493 } else {
494 return "resource";
497 break;
498 case 'A':
499 case 'a':
501 zval **p = va_arg(*va, zval **);
502 if (return_null) {
503 *p = NULL;
504 break;
506 if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) {
507 *p = *arg;
508 } else {
509 return "array";
512 break;
513 case 'H':
514 case 'h':
516 HashTable **p = va_arg(*va, HashTable **);
517 if (return_null) {
518 *p = NULL;
519 break;
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) {
524 *p = HASH_OF(*arg);
525 if(*p == NULL) {
526 return "array";
528 } else {
529 return "array";
532 break;
534 case 'o':
536 zval **p = va_arg(*va, zval **);
537 if (return_null) {
538 *p = NULL;
539 break;
541 if (Z_TYPE_PP(arg) == IS_OBJECT) {
542 *p = *arg;
543 } else {
544 return "object";
547 break;
549 case 'O':
551 zval **p = va_arg(*va, zval **);
552 zend_class_entry *ce = va_arg(*va, zend_class_entry *);
554 if (return_null) {
555 *p = NULL;
556 break;
558 if (Z_TYPE_PP(arg) == IS_OBJECT &&
559 (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
560 *p = *arg;
561 } else {
562 if (ce) {
563 return ce->name;
564 } else {
565 return "object";
569 break;
571 case 'C':
573 zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
574 zend_class_entry *ce_base = *pce;
576 if (return_null) {
577 *pce = NULL;
578 break;
580 convert_to_string_ex(arg);
581 if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) {
582 *pce = NULL;
583 } else {
584 *pce = *lookup;
586 if (ce_base) {
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));
590 *pce = NULL;
591 return "";
594 if (!*pce) {
595 zend_spprintf(error, 0, "to be a valid class name, '%s' given",
596 Z_STRVAL_PP(arg));
597 return "";
599 break;
602 break;
604 case 'f':
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;
610 if (return_null) {
611 fci->size = 0;
612 fcc->initialized = 0;
613 break;
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);
621 *spec = spec_walk;
622 return "";
624 break;
625 } else {
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);
630 return "";
631 } else {
632 return "valid callback";
637 case 'z':
639 zval **p = va_arg(*va, zval **);
640 if (return_null) {
641 *p = NULL;
642 } else {
643 *p = *arg;
646 break;
648 case 'Z':
650 zval ***p = va_arg(*va, zval ***);
651 if (return_null) {
652 *p = NULL;
653 } else {
654 *p = arg;
657 break;
659 default:
660 return "unknown";
663 *spec = spec_walk;
665 return NULL;
667 /* }}} */
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;
672 char *error = NULL;
673 int severity = E_WARNING;
675 expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
676 if (expected_type) {
677 if (!quiet && (*expected_type || error)) {
678 const char *space;
679 const char *class_name = get_active_class_name(&space TSRMLS_CC);
681 if (error) {
682 zend_error(severity, "%s%s%s() expects parameter %d %s",
683 class_name, space, get_active_function_name(TSRMLS_C), arg_num, error);
684 efree(error);
685 } else {
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) {
692 return FAILURE;
696 return SUCCESS;
698 /* }}} */
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;
703 int c, i;
704 int min_num_args = -1;
705 int max_num_args = 0;
706 int post_varargs = 0;
707 zval **arg;
708 int arg_count;
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++) {
715 c = *spec_walk;
716 switch (c) {
717 case 'l': case 'd':
718 case 's': case 'b':
719 case 'r': case 'a':
720 case 'o': case 'O':
721 case 'z': case 'Z':
722 case 'C': case 'h':
723 case 'f': case 'A':
724 case 'H': case 'p':
725 max_num_args++;
726 break;
728 case '|':
729 min_num_args = max_num_args;
730 break;
732 case '/':
733 case '!':
734 /* Pass */
735 break;
737 case '*':
738 case '+':
739 if (have_varargs) {
740 if (!quiet) {
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",
744 class_name,
745 class_name[0] ? "::" : "",
746 active_function->common.function_name);
748 return FAILURE;
750 have_varargs = 1;
751 /* we expect at least one parameter in varargs */
752 if (c == '+') {
753 max_num_args++;
755 /* mark the beginning of varargs */
756 post_varargs = max_num_args;
757 break;
759 default:
760 if (!quiet) {
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",
764 class_name,
765 class_name[0] ? "::" : "",
766 active_function->common.function_name);
768 return FAILURE;
772 if (min_num_args < 0) {
773 min_num_args = max_num_args;
776 if (have_varargs) {
777 /* calculate how many required args are at the end of the specifier list */
778 post_varargs = max_num_args - post_varargs;
779 max_num_args = -1;
782 if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
783 if (!quiet) {
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",
787 class_name,
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",
793 num_args);
795 return FAILURE;
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));
803 return FAILURE;
806 i = 0;
807 while (num_args-- > 0) {
808 if (*type_spec == '|') {
809 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 *);
818 type_spec++;
820 if (num_varargs > 0) {
821 int iv = 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;
834 i += iv;
835 continue;
836 } else {
837 *varargs = NULL;
838 *n_varargs = 0;
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) {
847 efree(*varargs);
848 *varargs = NULL;
850 return FAILURE;
852 i++;
855 return SUCCESS;
857 /* }}} */
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); \
868 return FAILURE; \
872 ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, const char *type_spec, ...) /* {{{ */
874 va_list va;
875 int retval;
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);
881 va_end(va);
883 return retval;
885 /* }}} */
887 ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, ...) /* {{{ */
889 va_list va;
890 int retval;
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);
896 va_end(va);
898 return retval;
900 /* }}} */
902 ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
904 va_list va;
905 int retval;
906 const char *p = type_spec;
907 zval **object;
908 zend_class_entry *ce;
910 if (!this_ptr) {
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);
915 va_end(va);
916 } else {
917 p++;
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 *);
924 *object = this_ptr;
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);
932 va_end(va);
934 return retval;
936 /* }}} */
938 ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, const char *type_spec, ...) /* {{{ */
940 va_list va;
941 int retval;
942 const char *p = type_spec;
943 zval **object;
944 zend_class_entry *ce;
945 int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
947 if (!this_ptr) {
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);
952 va_end(va);
953 } else {
954 p++;
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 *);
961 *object = this_ptr;
963 if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
964 if (!quiet) {
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));
968 va_end(va);
969 return FAILURE;
972 retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
973 va_end(va);
975 return retval;
977 /* }}} */
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;
986 return SUCCESS;
988 /* }}} */
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 *);
996 zval *member;
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;
1005 /* }}} */
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;
1018 if (destroy_ht) {
1019 zend_hash_destroy(properties);
1020 FREE_HASHTABLE(properties);
1023 /* }}} */
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;
1033 HashPosition pos;
1034 zend_property_info *prop_info;
1036 do {
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) {
1042 int ret;
1043 zend_class_entry *old_scope = *scope;
1044 *scope = prop_info->ce;
1045 ret = zval_update_constant(pp, (void*)1 TSRMLS_CC);
1046 *scope = old_scope;
1047 return ret;
1050 ce = ce->parent;
1051 } while (ce);
1054 return zval_update_constant(pp, (void*)1 TSRMLS_CC);
1056 return 0;
1058 /* }}} */
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;
1065 int i;
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) {
1077 zval **p;
1079 if (class_type->parent) {
1080 zend_update_class_constants(class_type->parent TSRMLS_CC);
1082 #if ZTS
1083 CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval*) * class_type->default_static_members_count);
1084 #else
1085 class_type->static_members_table = emalloc(sizeof(zval*) * class_type->default_static_members_count);
1086 #endif
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];
1097 Z_ADDREF_P(q);
1098 Z_SET_ISREF_P(q);
1099 CE_STATIC_MEMBERS(class_type)[i] = q;
1100 } else {
1101 zval *r;
1103 ALLOC_ZVAL(r);
1104 *r = **p;
1105 INIT_PZVAL(r);
1106 zval_copy_ctor(r);
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);
1116 *scope = old_scope;
1117 class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
1120 /* }}} */
1122 ZEND_API void object_properties_init(zend_object *object, zend_class_entry *class_type) /* {{{ */
1124 int i;
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]) {
1131 #if ZTS
1132 ALLOC_ZVAL( object->properties_table[i]);
1133 MAKE_COPY_ZVAL(&class_type->default_properties_table[i], object->properties_table[i]);
1134 #else
1135 Z_ADDREF_P(object->properties_table[i]);
1136 #endif
1139 object->properties = NULL;
1142 /* }}} */
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"
1155 : "abstract class";
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);
1164 if (properties) {
1165 object->properties = properties;
1166 object->properties_table = NULL;
1167 } else {
1168 object_properties_init(object, class_type);
1170 } else {
1171 Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
1173 return SUCCESS;
1175 /* }}} */
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);
1181 /* }}} */
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);
1187 /* }}} */
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");
1192 return FAILURE;
1194 /* }}} */
1196 ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
1198 zval *tmp;
1200 MAKE_STD_ZVAL(tmp);
1201 ZVAL_LONG(tmp, n);
1203 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1205 /* }}} */
1207 ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */
1209 zval *tmp;
1211 MAKE_STD_ZVAL(tmp);
1212 ZVAL_NULL(tmp);
1214 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1216 /* }}} */
1218 ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */
1220 zval *tmp;
1222 MAKE_STD_ZVAL(tmp);
1223 ZVAL_BOOL(tmp, b);
1225 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1227 /* }}} */
1229 ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */
1231 zval *tmp;
1233 MAKE_STD_ZVAL(tmp);
1234 ZVAL_RESOURCE(tmp, r);
1236 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1238 /* }}} */
1240 ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */
1242 zval *tmp;
1244 MAKE_STD_ZVAL(tmp);
1245 ZVAL_DOUBLE(tmp, d);
1247 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1249 /* }}} */
1251 ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */
1253 zval *tmp;
1255 MAKE_STD_ZVAL(tmp);
1256 ZVAL_STRING(tmp, str, duplicate);
1258 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1260 /* }}} */
1262 ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */
1264 zval *tmp;
1266 MAKE_STD_ZVAL(tmp);
1267 ZVAL_STRINGL(tmp, str, length, duplicate);
1269 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1271 /* }}} */
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);
1277 /* }}} */
1279 ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
1281 zval *tmp;
1283 MAKE_STD_ZVAL(tmp);
1284 ZVAL_LONG(tmp, n);
1286 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1288 /* }}} */
1290 ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
1292 zval *tmp;
1294 MAKE_STD_ZVAL(tmp);
1295 ZVAL_NULL(tmp);
1297 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1299 /* }}} */
1301 ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
1303 zval *tmp;
1305 MAKE_STD_ZVAL(tmp);
1306 ZVAL_BOOL(tmp, b);
1308 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1310 /* }}} */
1312 ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */
1314 zval *tmp;
1316 MAKE_STD_ZVAL(tmp);
1317 ZVAL_RESOURCE(tmp, r);
1319 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1321 /* }}} */
1323 ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
1325 zval *tmp;
1327 MAKE_STD_ZVAL(tmp);
1328 ZVAL_DOUBLE(tmp, d);
1330 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1332 /* }}} */
1334 ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */
1336 zval *tmp;
1338 MAKE_STD_ZVAL(tmp);
1339 ZVAL_STRING(tmp, str, duplicate);
1341 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1343 /* }}} */
1345 ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */
1347 zval *tmp;
1349 MAKE_STD_ZVAL(tmp);
1350 ZVAL_STRINGL(tmp, str, length, duplicate);
1352 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1354 /* }}} */
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);
1360 /* }}} */
1362 ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
1364 zval *tmp;
1366 MAKE_STD_ZVAL(tmp);
1367 ZVAL_LONG(tmp, n);
1369 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1371 /* }}} */
1373 ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1375 zval *tmp;
1377 MAKE_STD_ZVAL(tmp);
1378 ZVAL_NULL(tmp);
1380 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1382 /* }}} */
1384 ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1386 zval *tmp;
1388 MAKE_STD_ZVAL(tmp);
1389 ZVAL_BOOL(tmp, b);
1391 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1393 /* }}} */
1395 ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */
1397 zval *tmp;
1399 MAKE_STD_ZVAL(tmp);
1400 ZVAL_RESOURCE(tmp, r);
1402 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1404 /* }}} */
1406 ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1408 zval *tmp;
1410 MAKE_STD_ZVAL(tmp);
1411 ZVAL_DOUBLE(tmp, d);
1413 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1415 /* }}} */
1417 ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */
1419 zval *tmp;
1421 MAKE_STD_ZVAL(tmp);
1422 ZVAL_STRING(tmp, str, duplicate);
1424 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1426 /* }}} */
1428 ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */
1430 zval *tmp;
1432 MAKE_STD_ZVAL(tmp);
1433 ZVAL_STRINGL(tmp, str, length, duplicate);
1435 return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1437 /* }}} */
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);
1443 /* }}} */
1445 ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */
1447 zval *tmp;
1449 MAKE_STD_ZVAL(tmp);
1450 ZVAL_STRING(tmp, str, duplicate);
1452 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
1454 /* }}} */
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) /* {{{ */
1458 zval *tmp;
1460 MAKE_STD_ZVAL(tmp);
1461 ZVAL_STRINGL(tmp, str, length, duplicate);
1463 return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
1465 /* }}} */
1467 ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */
1469 zval *tmp;
1471 MAKE_STD_ZVAL(tmp);
1472 ZVAL_LONG(tmp, l);
1474 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1476 /* }}} */
1478 ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */
1480 zval *tmp;
1482 MAKE_STD_ZVAL(tmp);
1483 ZVAL_DOUBLE(tmp, d);
1485 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1487 /* }}} */
1489 ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */
1491 zval *tmp;
1493 MAKE_STD_ZVAL(tmp);
1494 ZVAL_STRING(tmp, str, duplicate);
1496 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1498 /* }}} */
1500 ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */
1502 zval *tmp;
1504 MAKE_STD_ZVAL(tmp);
1505 ZVAL_STRINGL(tmp, str, length, duplicate);
1507 return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1509 /* }}} */
1511 ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
1513 zval *tmp;
1514 zval *z_key;
1516 MAKE_STD_ZVAL(tmp);
1517 ZVAL_LONG(tmp, n);
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);
1525 return SUCCESS;
1527 /* }}} */
1529 ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */
1531 zval *tmp;
1532 zval *z_key;
1534 MAKE_STD_ZVAL(tmp);
1535 ZVAL_BOOL(tmp, b);
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);
1543 return SUCCESS;
1545 /* }}} */
1547 ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */
1549 zval *tmp;
1550 zval *z_key;
1552 MAKE_STD_ZVAL(tmp);
1553 ZVAL_NULL(tmp);
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);
1561 return SUCCESS;
1563 /* }}} */
1565 ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
1567 zval *tmp;
1568 zval *z_key;
1570 MAKE_STD_ZVAL(tmp);
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);
1579 return SUCCESS;
1581 /* }}} */
1583 ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */
1585 zval *tmp;
1586 zval *z_key;
1588 MAKE_STD_ZVAL(tmp);
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);
1597 return SUCCESS;
1599 /* }}} */
1601 ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, const char *str, int duplicate TSRMLS_DC) /* {{{ */
1603 zval *tmp;
1604 zval *z_key;
1606 MAKE_STD_ZVAL(tmp);
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);
1615 return SUCCESS;
1617 /* }}} */
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) /* {{{ */
1621 zval *tmp;
1622 zval *z_key;
1624 MAKE_STD_ZVAL(tmp);
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);
1633 return SUCCESS;
1635 /* }}} */
1637 ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */
1639 zval *z_key;
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);
1646 return SUCCESS;
1648 /* }}} */
1650 ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1652 int name_len;
1653 char *lcname;
1655 if (module->module_started) {
1656 return SUCCESS;
1658 module->module_started = 1;
1660 /* Check module dependencies */
1661 if (module->deps) {
1662 const zend_module_dep *dep = module->deps;
1664 while (dep->name) {
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) {
1672 efree(lcname);
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;
1676 return FAILURE;
1678 efree(lcname);
1680 ++dep;
1684 /* Initialize module globals */
1685 if (module->globals_size) {
1686 #ifdef ZTS
1687 ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1688 #else
1689 if (module->globals_ctor) {
1690 module->globals_ctor(module->globals_ptr TSRMLS_CC);
1692 #endif
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;
1699 return FAILURE;
1701 EG(current_module) = NULL;
1703 return SUCCESS;
1705 /* }}} */
1707 static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */
1709 Bucket **b1 = base;
1710 Bucket **b2;
1711 Bucket **end = b1 + count;
1712 Bucket *tmp;
1713 zend_module_entry *m, *r;
1715 while (b1 < end) {
1716 try_again:
1717 m = (zend_module_entry*)(*b1)->pData;
1718 if (!m->module_started && m->deps) {
1719 const zend_module_dep *dep = m->deps;
1720 while (dep->name) {
1721 if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1722 b2 = b1 + 1;
1723 while (b2 < end) {
1724 r = (zend_module_entry*)(*b2)->pData;
1725 if (strcasecmp(dep->name, r->name) == 0) {
1726 tmp = *b1;
1727 *b1 = *b2;
1728 *b2 = tmp;
1729 goto try_again;
1731 b2++;
1734 dep++;
1737 b1++;
1740 /* }}} */
1742 ZEND_API void zend_collect_module_handlers(TSRMLS_D) /* {{{ */
1744 HashPosition pos;
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) {
1757 startup_count++;
1759 if (module->request_shutdown_func) {
1760 shutdown_count++;
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;
1776 startup_count = 0;
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) {
1798 class_count++;
1802 class_cleanup_handlers = (zend_class_entry**)malloc(
1803 sizeof(zend_class_entry*) *
1804 (class_count + 1));
1805 class_cleanup_handlers[class_count] = NULL;
1807 if (class_count) {
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;
1818 /* }}} */
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);
1824 return SUCCESS;
1826 /* }}} */
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);
1834 /* }}} */
1836 ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1838 int name_len;
1839 char *lcname;
1840 zend_module_entry *module_ptr;
1842 if (!module) {
1843 return NULL;
1846 #if 0
1847 zend_printf("%s: Registering module %d\n", module->name, module->module_number);
1848 #endif
1850 /* Check module dependencies */
1851 if (module->deps) {
1852 const zend_module_dep *dep = module->deps;
1854 while (dep->name) {
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)) {
1860 efree(lcname);
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);
1863 return NULL;
1865 efree(lcname);
1867 ++dep;
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);
1876 efree(lcname);
1877 return NULL;
1879 efree(lcname);
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);
1886 return NULL;
1889 EG(current_module) = NULL;
1890 return module;
1892 /* }}} */
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);
1900 /* }}} */
1902 ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */
1904 char lcname[16];
1905 int name_len;
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);
1961 /* }}} */
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;
1971 int error_type;
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;
1974 int fname_len;
1975 const char *lc_class_name = NULL;
1976 int class_name_len = 0;
1978 if (type==MODULE_PERSISTENT) {
1979 error_type = E_CORE_WARNING;
1980 } else {
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);
1990 if (scope) {
1991 class_name_len = strlen(scope->name);
1992 if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) {
1993 ++lc_class_name;
1994 class_name_len -= (lc_class_name - scope->name);
1995 lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
1996 } else {
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;
2006 if (ptr->flags) {
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;
2012 } else {
2013 internal_function->fn_flags = ptr->flags;
2015 } else {
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;
2026 } else {
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;
2032 } else {
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;
2039 } else {
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) {
2045 if (scope) {
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);
2058 } else {
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);
2062 return FAILURE;
2064 if (!internal_function->handler) {
2065 if (scope) {
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);
2070 return FAILURE;
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**)&reg_function);
2077 } else {
2078 result = zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function);
2080 if (result == FAILURE) {
2081 unload=1;
2082 str_efree(lowercase_name);
2083 break;
2085 if (scope) {
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;
2115 } else {
2116 reg_function = NULL;
2118 if (reg_function) {
2119 zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
2122 ptr++;
2123 count++;
2124 str_efree(lowercase_name);
2126 if (unload) { /* before unloading, display all remaining bad function in the module */
2127 if (scope) {
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);
2137 ptr++;
2139 zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
2140 return FAILURE;
2142 if (scope) {
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;
2153 if (ctor) {
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;
2160 if (dtor) {
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;
2167 if (clone) {
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;
2174 if (__call) {
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;
2180 if (__callstatic) {
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;
2186 if (__tostring) {
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;
2192 if (__get) {
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;
2198 if (__set) {
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;
2204 if (__unset) {
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;
2210 if (__isset) {
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);
2218 return SUCCESS;
2220 /* }}} */
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;
2228 int i=0;
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) {
2236 break;
2238 #if 0
2239 zend_printf("Unregistering %s()\n", ptr->fname);
2240 #endif
2241 zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1);
2242 ptr++;
2243 i++;
2246 /* }}} */
2248 ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
2250 TSRMLS_FETCH();
2252 if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) {
2253 return SUCCESS;
2255 return FAILURE;
2257 /* }}} */
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;
2265 /* }}} */
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;
2271 } else {
2272 return ZEND_HASH_APPLY_KEEP;
2275 /* }}} */
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);
2281 /* }}} */
2283 void module_destructor(zend_module_entry *module) /* {{{ */
2285 TSRMLS_FETCH();
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) {
2294 #if 0
2295 zend_printf("%s: Module shutdown\n", module->name);
2296 #endif
2297 module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
2300 /* Deinitilaise module globals */
2301 if (module->globals_size) {
2302 #ifdef ZTS
2303 if (*module->globals_id_ptr) {
2304 ts_free_id(*module->globals_id_ptr);
2306 #else
2307 if (module->globals_dtor) {
2308 module->globals_dtor(module->globals_ptr TSRMLS_CC);
2310 #endif
2313 module->module_started=0;
2314 if (module->functions) {
2315 zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
2318 #if HAVE_LIBDL
2319 #if !(defined(NETWARE) && defined(APACHE_1_BUILD))
2320 if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2321 DL_UNLOAD(module->handle);
2323 #endif
2324 #endif
2326 /* }}} */
2328 void zend_activate_modules(TSRMLS_D) /* {{{ */
2330 zend_module_entry **p = module_request_startup_handlers;
2332 while (*p) {
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);
2337 exit(1);
2339 p++;
2342 /* }}} */
2344 /* call request shutdown for all modules */
2345 int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
2347 if (module->request_shutdown_func) {
2348 #if 0
2349 zend_printf("%s: Request shutdown\n", module->name);
2350 #endif
2351 module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2353 return 0;
2355 /* }}} */
2357 void zend_deactivate_modules(TSRMLS_D) /* {{{ */
2359 EG(opline_ptr) = NULL; /* we're no longer executing anything */
2361 zend_try {
2362 if (EG(full_tables_cleanup)) {
2363 zend_hash_reverse_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC);
2364 } else {
2365 zend_module_entry **p = module_request_shutdown_handlers;
2367 while (*p) {
2368 zend_module_entry *module = *p;
2370 module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2371 p++;
2374 } zend_end_try();
2376 /* }}} */
2378 ZEND_API void zend_cleanup_internal_classes(TSRMLS_D) /* {{{ */
2380 zend_class_entry **p = class_cleanup_handlers;
2382 while (*p) {
2383 zend_cleanup_internal_class_data(*p TSRMLS_CC);
2384 p++;
2387 /* }}} */
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;
2393 /* }}} */
2395 static int exec_done_cb(zend_module_entry *module TSRMLS_DC) /* {{{ */
2397 if (module->post_deactivate_func) {
2398 module->post_deactivate_func();
2400 return 0;
2402 /* }}} */
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);
2409 } else {
2410 zend_module_entry **p = module_post_deactivate_handlers;
2412 while (*p) {
2413 zend_module_entry *module = *p;
2415 module->post_deactivate_func();
2416 p++;
2420 /* }}} */
2422 /* return the next free module number */
2423 int zend_next_free_module(void) /* {{{ */
2425 return zend_hash_num_elements(&module_registry) + 1;
2427 /* }}} */
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);
2448 } else {
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);
2452 return class_entry;
2454 /* }}} */
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) {
2468 return NULL;
2469 } else {
2470 parent_ce = *pce;
2474 register_class = zend_register_internal_class(class_entry TSRMLS_CC);
2476 if (parent_ce) {
2477 zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
2479 return register_class;
2481 /* }}} */
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);
2496 /* }}} */
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);
2504 /* }}} */
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);
2510 /* }}} */
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);
2515 int ret;
2517 ret = zend_hash_add(CG(class_table), lcname, name_len+1, &ce, sizeof(zend_class_entry *), NULL);
2518 efree(lcname);
2519 if (ret == SUCCESS) {
2520 ce->refcount++;
2522 return ret;
2524 /* }}} */
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);
2542 return SUCCESS;
2544 /* }}} */
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));
2554 /* }}} */
2556 static zend_function_entry disabled_function[] = {
2557 ZEND_FE(display_disabled_function, NULL)
2558 ZEND_FE_END
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) {
2564 return FAILURE;
2566 disabled_function[0].fname = function_name;
2567 return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC);
2569 /* }}} */
2571 #ifdef ZEND_WIN32
2572 #pragma optimize("", off)
2573 #endif
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);
2580 return retval;
2582 #ifdef ZEND_WIN32
2583 #pragma optimize("", on)
2584 #endif
2585 /* }}} */
2587 static const zend_function_entry disabled_class_new[] = {
2588 ZEND_FE_END
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) {
2597 return 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));
2602 return SUCCESS;
2604 /* }}} */
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) /* {{{ */
2608 int ret = 0;
2609 zend_class_entry **pce;
2610 char *lcname = zend_str_tolower_dup(name, name_len);
2612 *strict_class = 0;
2613 if (name_len == sizeof("self") - 1 &&
2614 !memcmp(lcname, "self", sizeof("self") - 1)) {
2615 if (!EG(scope)) {
2616 if (error) *error = estrdup("cannot access self:: when no class scope is active");
2617 } else {
2618 fcc->called_scope = EG(called_scope);
2619 fcc->calling_scope = EG(scope);
2620 if (!fcc->object_ptr) {
2621 fcc->object_ptr = EG(This);
2623 ret = 1;
2625 } else if (name_len == sizeof("parent") - 1 &&
2626 !memcmp(lcname, "parent", sizeof("parent") - 1)) {
2627 if (!EG(scope)) {
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");
2631 } else {
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);
2637 *strict_class = 1;
2638 ret = 1;
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");
2644 } else {
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);
2650 *strict_class = 1;
2651 ret = 1;
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);
2662 } else {
2663 fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
2665 *strict_class = 1;
2666 ret = 1;
2667 } else {
2668 if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
2670 efree(lcname);
2671 return ret;
2673 /* }}} */
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;
2678 int retval = 0;
2679 char *mname, *lmname;
2680 const char *colon;
2681 int clen, mlen;
2682 zend_class_entry *last_scope;
2683 HashTable *ftable;
2684 int call_via_handler = 0;
2686 if (error) {
2687 *error = NULL;
2690 fcc->calling_scope = NULL;
2691 fcc->function_handler = NULL;
2693 if (!ce_org) {
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);
2698 } else {
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) {
2705 efree(lmname);
2706 return 1;
2708 efree(lmname);
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) &&
2714 *(colon-1) == ':'
2716 colon--;
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");
2722 return 0;
2725 /* This is a compound name.
2726 * Try to fetch class and then find static method. */
2727 last_scope = EG(scope);
2728 if (ce_org) {
2729 EG(scope) = ce_org;
2732 if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
2733 EG(scope) = last_scope;
2734 return 0;
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);
2741 return 0;
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;
2750 } else {
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));
2755 return 0;
2758 lmname = zend_str_tolower_dup(mname, mlen);
2759 if (strict_class &&
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) {
2765 retval = 1;
2767 } else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
2768 retval = 1;
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)) {
2786 retval = 0;
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))) {
2792 retval = 0;
2793 fcc->function_handler = NULL;
2794 goto get_function_via_handler;
2798 } else {
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;
2812 retval = 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) {
2816 if (strict_class &&
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);
2825 } else {
2826 retval = 1;
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);
2834 } else {
2835 fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen, NULL TSRMLS_CC);
2837 if (fcc->function_handler) {
2838 retval = 1;
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);
2849 if (retval) {
2850 if (fcc->calling_scope && !call_via_handler) {
2851 if (!fcc->object_ptr && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2852 if (error) {
2853 zend_spprintf(error, 0, "cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2854 retval = 0;
2855 } else {
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)) {
2859 int severity;
2860 char *verb;
2861 if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2862 severity = E_STRICT;
2863 verb = "should not";
2864 } else {
2865 /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2866 severity = E_ERROR;
2867 verb = "cannot";
2869 if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
2870 retval = 0;
2872 if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
2873 fcc->object_ptr = EG(This);
2874 if (error) {
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) {
2877 retval = 0;
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);
2882 } else {
2883 if (error) {
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) {
2886 retval = 0;
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)) {
2896 if (error) {
2897 if (*error) {
2898 efree(*error);
2900 zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2902 retval = 0;
2904 } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
2905 if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
2906 if (error) {
2907 if (*error) {
2908 efree(*error);
2910 zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2912 retval = 0;
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);
2920 } else {
2921 if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname);
2924 efree(lmname);
2926 if (fcc->object_ptr) {
2927 fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
2929 if (retval) {
2930 fcc->initialized = 1;
2932 return retval;
2934 /* }}} */
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) /* {{{ */
2938 zend_bool ret;
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;
2948 if (fcc == NULL) {
2949 fcc = &fcc_local;
2951 if (error) {
2952 *error = NULL;
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) {
2963 object_ptr = NULL;
2965 if (object_ptr &&
2966 (!EG(objects_store).object_buckets ||
2967 !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) {
2968 return 0;
2971 switch (Z_TYPE_P(callable)) {
2972 case IS_STRING:
2973 if (object_ptr) {
2974 fcc->object_ptr = object_ptr;
2975 fcc->calling_scope = Z_OBJCE_P(object_ptr);
2976 if (callable_name) {
2977 char *ptr;
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;
2993 return 1;
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);
3008 return ret;
3010 case IS_ARRAY:
3012 zval **method = NULL;
3013 zval **obj = 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) {
3027 char *ptr;
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) {
3039 return 1;
3042 if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
3043 return 0;
3046 } else {
3047 if (!EG(objects_store).object_buckets ||
3048 !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) {
3049 return 0;
3052 fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
3054 fcc->object_ptr = *obj;
3056 if (callable_name) {
3057 char *ptr;
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;
3070 return 1;
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);
3086 return ret;
3088 } else {
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");
3092 } else {
3093 if (error) zend_spprintf(error, 0, "second array member is not a valid method");
3095 } else {
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;
3104 return 0;
3106 case IS_OBJECT:
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"));
3117 return 1;
3119 /* break missing intentionally */
3121 default:
3122 if (callable_name) {
3123 zval expr_copy;
3124 int use_copy;
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");
3132 return 0;
3135 /* }}} */
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);
3141 /* }}} */
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);
3164 return 1;
3166 return 0;
3168 /* }}} */
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)) {
3173 return FAILURE;
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;
3182 fci->params = NULL;
3183 fci->no_separation = 1;
3184 fci->symbol_table = NULL;
3186 return SUCCESS;
3188 /* }}} */
3190 ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
3192 if (fci->params) {
3193 if (free_mem) {
3194 efree(fci->params);
3195 fci->params = NULL;
3198 fci->param_count = 0;
3200 /* }}} */
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;
3207 fci->params = NULL;
3209 /* }}} */
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;
3217 /* }}} */
3219 ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
3221 HashPosition pos;
3222 zval **arg, ***params;
3224 zend_fcall_info_args_clear(fci, !args);
3226 if (!args) {
3227 return SUCCESS;
3230 if (Z_TYPE_P(args) != IS_ARRAY) {
3231 return FAILURE;
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) {
3239 *params++ = arg;
3240 zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
3243 return SUCCESS;
3245 /* }}} */
3247 ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */
3249 int i;
3251 if (argc < 0) {
3252 return FAILURE;
3255 zend_fcall_info_args_clear(fci, !argc);
3257 if (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];
3266 return SUCCESS;
3268 /* }}} */
3270 ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */
3272 int i;
3273 zval **arg;
3275 if (argc < 0) {
3276 return FAILURE;
3279 zend_fcall_info_args_clear(fci, !argc);
3281 if (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;
3291 return SUCCESS;
3293 /* }}} */
3295 ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */
3297 int ret;
3298 va_list argv;
3300 va_start(argv, argc);
3301 ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv);
3302 va_end(argv);
3304 return ret;
3306 /* }}} */
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;
3314 if (args) {
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);
3323 if (args) {
3324 zend_fcall_info_args_restore(fci, org_count, org_params);
3326 return result;
3328 /* }}} */
3330 ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
3332 char *lname;
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) {
3338 efree(lname);
3339 return NULL;
3341 efree(lname);
3342 return module->version;
3344 /* }}} */
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);
3361 } else {
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;
3369 } else {
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);
3375 } else {
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)) {
3383 case IS_ARRAY:
3384 case IS_CONSTANT_ARRAY:
3385 case IS_OBJECT:
3386 case IS_RESOURCE:
3387 zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
3388 break;
3389 default:
3390 break;
3393 switch (access_type & ZEND_ACC_PPP_MASK) {
3394 case ZEND_ACC_PRIVATE: {
3395 char *priv_name;
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;
3402 break;
3403 case ZEND_ACC_PROTECTED: {
3404 char *prot_name;
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;
3411 break;
3412 case ZEND_ACC_PUBLIC:
3413 if (IS_INTERNED(name)) {
3414 property_info.name = (char*)name;
3415 } else {
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;
3419 break;
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);
3426 } else {
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);
3442 return SUCCESS;
3444 /* }}} */
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);
3450 /* }}} */
3452 ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
3454 zval *property;
3456 if (ce->type & ZEND_INTERNAL_CLASS) {
3457 ALLOC_PERMANENT_ZVAL(property);
3458 } else {
3459 ALLOC_ZVAL(property);
3461 INIT_ZVAL(*property);
3462 return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3464 /* }}} */
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) /* {{{ */
3468 zval *property;
3470 if (ce->type & ZEND_INTERNAL_CLASS) {
3471 ALLOC_PERMANENT_ZVAL(property);
3472 } else {
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);
3479 /* }}} */
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) /* {{{ */
3483 zval *property;
3485 if (ce->type & ZEND_INTERNAL_CLASS) {
3486 ALLOC_PERMANENT_ZVAL(property);
3487 } else {
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);
3494 /* }}} */
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) /* {{{ */
3498 zval *property;
3500 if (ce->type & ZEND_INTERNAL_CLASS) {
3501 ALLOC_PERMANENT_ZVAL(property);
3502 } else {
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);
3509 /* }}} */
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) /* {{{ */
3513 zval *property;
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);
3519 } else {
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);
3526 /* }}} */
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) /* {{{ */
3530 zval *property;
3532 if (ce->type & ZEND_INTERNAL_CLASS) {
3533 ALLOC_PERMANENT_ZVAL(property);
3534 ZVAL_STRINGL(property, zend_strndup(value, value_len), value_len, 0);
3535 } else {
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);
3542 /* }}} */
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);
3548 /* }}} */
3550 ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
3552 zval *constant;
3554 if (ce->type & ZEND_INTERNAL_CLASS) {
3555 ALLOC_PERMANENT_ZVAL(constant);
3556 } else {
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);
3563 /* }}} */
3565 ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
3567 zval *constant;
3569 if (ce->type & ZEND_INTERNAL_CLASS) {
3570 ALLOC_PERMANENT_ZVAL(constant);
3571 } else {
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);
3578 /* }}} */
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) /* {{{ */
3582 zval *constant;
3584 if (ce->type & ZEND_INTERNAL_CLASS) {
3585 ALLOC_PERMANENT_ZVAL(constant);
3586 } else {
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);
3593 /* }}} */
3595 ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
3597 zval *constant;
3599 if (ce->type & ZEND_INTERNAL_CLASS) {
3600 ALLOC_PERMANENT_ZVAL(constant);
3601 } else {
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);
3608 /* }}} */
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) /* {{{ */
3612 zval *constant;
3614 if (ce->type & ZEND_INTERNAL_CLASS) {
3615 ALLOC_PERMANENT_ZVAL(constant);
3616 ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
3617 } else {
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);
3624 /* }}} */
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);
3630 /* }}} */
3632 ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
3634 zval *property;
3635 zend_class_entry *old_scope = EG(scope);
3637 EG(scope) = 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;
3654 /* }}} */
3656 ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, const char *name, int name_length TSRMLS_DC) /* {{{ */
3658 zval *tmp;
3660 ALLOC_ZVAL(tmp);
3661 Z_UNSET_ISREF_P(tmp);
3662 Z_SET_REFCOUNT_P(tmp, 0);
3663 ZVAL_NULL(tmp);
3664 zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3666 /* }}} */
3668 ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3670 zval *tmp;
3672 ALLOC_ZVAL(tmp);
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);
3678 /* }}} */
3680 ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3682 zval *tmp;
3684 ALLOC_ZVAL(tmp);
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);
3690 /* }}} */
3692 ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
3694 zval *tmp;
3696 ALLOC_ZVAL(tmp);
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);
3702 /* }}} */
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) /* {{{ */
3706 zval *tmp;
3708 ALLOC_ZVAL(tmp);
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);
3714 /* }}} */
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) /* {{{ */
3718 zval *tmp;
3720 ALLOC_ZVAL(tmp);
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);
3726 /* }}} */
3728 ZEND_API int zend_update_static_property(zend_class_entry *scope, const char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
3730 zval **property;
3731 zend_class_entry *old_scope = EG(scope);
3733 EG(scope) = scope;
3734 property = zend_std_get_static_property(scope, name, name_length, 0, NULL TSRMLS_CC);
3735 EG(scope) = old_scope;
3736 if (!property) {
3737 return FAILURE;
3738 } else {
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);
3746 } else {
3747 efree(value);
3749 } else {
3750 zval *garbage = *property;
3752 Z_ADDREF_P(value);
3753 if (PZVAL_IS_REF(value)) {
3754 SEPARATE_ZVAL(&value);
3756 *property = value;
3757 zval_ptr_dtor(&garbage);
3760 return SUCCESS;
3763 /* }}} */
3765 ZEND_API int zend_update_static_property_null(zend_class_entry *scope, const char *name, int name_length TSRMLS_DC) /* {{{ */
3767 zval *tmp;
3769 ALLOC_ZVAL(tmp);
3770 Z_UNSET_ISREF_P(tmp);
3771 Z_SET_REFCOUNT_P(tmp, 0);
3772 ZVAL_NULL(tmp);
3773 return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3775 /* }}} */
3777 ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3779 zval *tmp;
3781 ALLOC_ZVAL(tmp);
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);
3787 /* }}} */
3789 ZEND_API int zend_update_static_property_long(zend_class_entry *scope, const char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3791 zval *tmp;
3793 ALLOC_ZVAL(tmp);
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);
3799 /* }}} */
3801 ZEND_API int zend_update_static_property_double(zend_class_entry *scope, const char *name, int name_length, double value TSRMLS_DC) /* {{{ */
3803 zval *tmp;
3805 ALLOC_ZVAL(tmp);
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);
3811 /* }}} */
3813 ZEND_API int zend_update_static_property_string(zend_class_entry *scope, const char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
3815 zval *tmp;
3817 ALLOC_ZVAL(tmp);
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);
3823 /* }}} */
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) /* {{{ */
3827 zval *tmp;
3829 ALLOC_ZVAL(tmp);
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);
3835 /* }}} */
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);
3842 EG(scope) = 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;
3858 return value;
3860 /* }}} */
3862 ZEND_API zval *zend_read_static_property(zend_class_entry *scope, const char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3864 zval **property;
3865 zend_class_entry *old_scope = EG(scope);
3867 EG(scope) = 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;
3873 /* }}} */
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);
3884 /* }}} */
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) /* {{{ */
3888 if (current) {
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;
3898 /* }}} */
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;
3914 /* }}} */
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;
3921 alias = *alias_ptr;
3922 while (alias) {
3923 if (alias->alias_len == len &&
3924 !strncasecmp(name, alias->alias, alias->alias_len)) {
3925 return alias->alias;
3927 alias_ptr++;
3928 alias = *alias_ptr;
3931 return name;
3933 /* }}} */
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 ||
3943 !f->common.scope ||
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) {
3951 if (func == f) {
3952 char *name;
3953 uint len;
3954 ulong idx;
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;
3959 --len;
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;
3970 /* }}} */
3973 * Local variables:
3974 * tab-width: 4
3975 * c-basic-offset: 4
3976 * indent-tabs-mode: t
3977 * End: