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   +----------------------------------------------------------------------+
19*/
20
21/* $Id$ */
22
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"
30
31#ifdef HAVE_STDARG_H
32#include <stdarg.h>
33#endif
34
35/* these variables are true statics/globals, and have to be mutex'ed on every access */
36ZEND_API HashTable module_registry;
37
38/* this function doesn't check for too many parameters */
39ZEND_API int zend_get_parameters(int ht, int param_count, ...) /* {{{ */
40{
41    void **p;
42    int arg_count;
43    va_list ptr;
44    zval **param, *param_ptr;
45    TSRMLS_FETCH();
46
47    p = zend_vm_stack_top(TSRMLS_C) - 1;
48    arg_count = (int)(zend_uintptr_t) *p;
49
50    if (param_count>arg_count) {
51        return FAILURE;
52    }
53
54    va_start(ptr, param_count);
55
56    while (param_count-->0) {
57        param = va_arg(ptr, zval **);
58        param_ptr = *(p-arg_count);
59        if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
60            zval *new_tmp;
61
62            ALLOC_ZVAL(new_tmp);
63            *new_tmp = *param_ptr;
64            zval_copy_ctor(new_tmp);
65            INIT_PZVAL(new_tmp);
66            param_ptr = new_tmp;
67            Z_DELREF_P((zval *) *(p-arg_count));
68            *(p-arg_count) = param_ptr;
69        }
70        *param = param_ptr;
71        arg_count--;
72    }
73    va_end(ptr);
74
75    return SUCCESS;
76}
77/* }}} */
78
79ZEND_API int _zend_get_parameters_array(int ht, int param_count, zval **argument_array TSRMLS_DC) /* {{{ */
80{
81    void **p;
82    int arg_count;
83    zval *param_ptr;
84
85    p = zend_vm_stack_top(TSRMLS_C) - 1;
86    arg_count = (int)(zend_uintptr_t) *p;
87
88    if (param_count>arg_count) {
89        return FAILURE;
90    }
91
92    while (param_count-->0) {
93        param_ptr = *(p-arg_count);
94        if (!PZVAL_IS_REF(param_ptr) && Z_REFCOUNT_P(param_ptr) > 1) {
95            zval *new_tmp;
96
97            ALLOC_ZVAL(new_tmp);
98            *new_tmp = *param_ptr;
99            zval_copy_ctor(new_tmp);
100            INIT_PZVAL(new_tmp);
101            param_ptr = new_tmp;
102            Z_DELREF_P((zval *) *(p-arg_count));
103            *(p-arg_count) = param_ptr;
104        }
105        *(argument_array++) = param_ptr;
106        arg_count--;
107    }
108
109    return SUCCESS;
110}
111/* }}} */
112
113/* Zend-optimized Extended functions */
114/* this function doesn't check for too many parameters */
115ZEND_API int zend_get_parameters_ex(int param_count, ...) /* {{{ */
116{
117    void **p;
118    int arg_count;
119    va_list ptr;
120    zval ***param;
121    TSRMLS_FETCH();
122
123    p = zend_vm_stack_top(TSRMLS_C) - 1;
124    arg_count = (int)(zend_uintptr_t) *p;
125
126    if (param_count>arg_count) {
127        return FAILURE;
128    }
129
130    va_start(ptr, param_count);
131    while (param_count-->0) {
132        param = va_arg(ptr, zval ***);
133        *param = (zval **) p-(arg_count--);
134    }
135    va_end(ptr);
136
137    return SUCCESS;
138}
139/* }}} */
140
141ZEND_API int _zend_get_parameters_array_ex(int param_count, zval ***argument_array TSRMLS_DC) /* {{{ */
142{
143    void **p;
144    int arg_count;
145
146    p = zend_vm_stack_top(TSRMLS_C) - 1;
147    arg_count = (int)(zend_uintptr_t) *p;
148
149    if (param_count>arg_count) {
150        return FAILURE;
151    }
152
153    while (param_count-->0) {
154        zval **value = (zval**)(p-arg_count);
155
156        *(argument_array++) = value;
157        arg_count--;
158    }
159
160    return SUCCESS;
161}
162/* }}} */
163
164ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array TSRMLS_DC) /* {{{ */
165{
166    void **p;
167    int arg_count;
168
169    p = zend_vm_stack_top(TSRMLS_C) - 1;
170    arg_count = (int)(zend_uintptr_t) *p;
171
172    if (param_count>arg_count) {
173        return FAILURE;
174    }
175
176    while (param_count-->0) {
177        zval **param = (zval **) p-(arg_count--);
178        zval_add_ref(param);
179        add_next_index_zval(argument_array, *param);
180    }
181
182    return SUCCESS;
183}
184/* }}} */
185
186ZEND_API void zend_wrong_param_count(TSRMLS_D) /* {{{ */
187{
188    char *space;
189    char *class_name = get_active_class_name(&space TSRMLS_CC);
190
191    zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
192}
193/* }}} */
194
195/* Argument parsing API -- andrei */
196ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
197{
198    switch(type) {
199        case IS_BOOL:
200            return "boolean";
201        case IS_LONG:
202            return "integer";
203        case IS_DOUBLE:
204            return "double";
205        case IS_STRING:
206            return "string";
207        case IS_OBJECT:
208            return "object";
209        case IS_RESOURCE:
210            return "resource";
211        case IS_NULL:
212            return "null";
213        case IS_ARRAY:
214            return "array";
215        default:
216            return "unknown";
217    }
218}
219/* }}} */
220
221ZEND_API char *zend_zval_type_name(const zval *arg) /* {{{ */
222{
223    return zend_get_type_by_const(Z_TYPE_P(arg));
224}
225/* }}} */
226
227ZEND_API zend_class_entry *zend_get_class_entry(const zval *zobject TSRMLS_DC) /* {{{ */
228{
229    if (Z_OBJ_HT_P(zobject)->get_class_entry) {
230        return Z_OBJ_HT_P(zobject)->get_class_entry(zobject TSRMLS_CC);
231    } else {
232        zend_error(E_ERROR, "Class entry requested for an object without PHP class");
233        return NULL;
234    }
235}
236/* }}} */
237
238/* returns 1 if you need to copy result, 0 if it's already a copy */
239ZEND_API int zend_get_object_classname(const zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC) /* {{{ */
240{
241    if (Z_OBJ_HT_P(object)->get_class_name == NULL ||
242        Z_OBJ_HT_P(object)->get_class_name(object, class_name, class_name_len, 0 TSRMLS_CC) != SUCCESS) {
243        zend_class_entry *ce = Z_OBJCE_P(object);
244
245        *class_name = ce->name;
246        *class_name_len = ce->name_length;
247        return 1;
248    }
249    return 0;
250}
251/* }}} */
252
253static int parse_arg_object_to_string(zval **arg TSRMLS_DC) /* {{{ */
254{
255    if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
256        zval *obj;
257        MAKE_STD_ZVAL(obj);
258        if (Z_OBJ_HANDLER_P(*arg, cast_object)(*arg, obj, IS_STRING TSRMLS_CC) == SUCCESS) {
259            zval_ptr_dtor(arg);
260            *arg = obj;
261            return SUCCESS;
262        }
263        efree(obj);
264    }
265    /* Standard PHP objects */
266    if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) {
267        SEPARATE_ZVAL_IF_NOT_REF(arg);
268        if (zend_std_cast_object_tostring(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
269            return SUCCESS;
270        }
271    }
272    if (!Z_OBJ_HANDLER_PP(arg, cast_object) && Z_OBJ_HANDLER_PP(arg, get)) {
273        int use_copy;
274        zval *z = Z_OBJ_HANDLER_PP(arg, get)(*arg TSRMLS_CC);
275        Z_ADDREF_P(z);
276        if(Z_TYPE_P(z) != IS_OBJECT) {
277            zval_dtor(*arg);
278            Z_TYPE_P(*arg) = IS_NULL;
279            zend_make_printable_zval(z, *arg, &use_copy);
280            if (!use_copy) {
281                ZVAL_ZVAL(*arg, z, 1, 1);
282            }
283            return SUCCESS;
284        }
285        zval_ptr_dtor(&z);
286    }
287    return FAILURE;
288}
289/* }}} */
290
291static char *zend_parse_arg_impl(int arg_num, zval **arg, va_list *va, char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
292{
293    char *spec_walk = *spec;
294    char c = *spec_walk++;
295    int return_null = 0;
296
297    /* scan through modifiers */
298    while (1) {
299        if (*spec_walk == '/') {
300            SEPARATE_ZVAL_IF_NOT_REF(arg);
301        } else if (*spec_walk == '!') {
302            if (Z_TYPE_PP(arg) == IS_NULL) {
303                return_null = 1;
304            }
305        } else {
306            break;
307        }
308        spec_walk++;
309    }
310
311    switch (c) {
312        case 'l':
313        case 'L':
314            {
315                long *p = va_arg(*va, long *);
316                switch (Z_TYPE_PP(arg)) {
317                    case IS_STRING:
318                        {
319                            double d;
320                            int type;
321
322                            if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), p, &d, -1)) == 0) {
323                                return "long";
324                            } else if (type == IS_DOUBLE) {
325                                if (c == 'L') {
326                                    if (d > LONG_MAX) {
327                                        *p = LONG_MAX;
328                                        break;
329                                    } else if (d < LONG_MIN) {
330                                        *p = LONG_MIN;
331                                        break;
332                                    }
333                                }
334
335                                *p = zend_dval_to_lval(d);
336                            }
337                        }
338                        break;
339
340                    case IS_DOUBLE:
341                        if (c == 'L') {
342                            if (Z_DVAL_PP(arg) > LONG_MAX) {
343                                *p = LONG_MAX;
344                                break;
345                            } else if (Z_DVAL_PP(arg) < LONG_MIN) {
346                                *p = LONG_MIN;
347                                break;
348                            }
349                        }
350                    case IS_NULL:
351                    case IS_LONG:
352                    case IS_BOOL:
353                        convert_to_long_ex(arg);
354                        *p = Z_LVAL_PP(arg);
355                        break;
356
357                    case IS_ARRAY:
358                    case IS_OBJECT:
359                    case IS_RESOURCE:
360                    default:
361                        return "long";
362                }
363            }
364            break;
365
366        case 'd':
367            {
368                double *p = va_arg(*va, double *);
369                switch (Z_TYPE_PP(arg)) {
370                    case IS_STRING:
371                        {
372                            long l;
373                            int type;
374
375                            if ((type = is_numeric_string(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &l, p, -1)) == 0) {
376                                return "double";
377                            } else if (type == IS_LONG) {
378                                *p = (double) l;
379                            }
380                        }
381                        break;
382
383                    case IS_NULL:
384                    case IS_LONG:
385                    case IS_DOUBLE:
386                    case IS_BOOL:
387                        convert_to_double_ex(arg);
388                        *p = Z_DVAL_PP(arg);
389                        break;
390
391                    case IS_ARRAY:
392                    case IS_OBJECT:
393                    case IS_RESOURCE:
394                    default:
395                        return "double";
396                }
397            }
398            break;
399
400        case 's':
401            {
402                char **p = va_arg(*va, char **);
403                int *pl = va_arg(*va, int *);
404                switch (Z_TYPE_PP(arg)) {
405                    case IS_NULL:
406                        if (return_null) {
407                            *p = NULL;
408                            *pl = 0;
409                            break;
410                        }
411                        /* break omitted intentionally */
412
413                    case IS_STRING:
414                    case IS_LONG:
415                    case IS_DOUBLE:
416                    case IS_BOOL:
417                        convert_to_string_ex(arg);
418                        if (UNEXPECTED(Z_ISREF_PP(arg) != 0)) {
419                            /* it's dangerous to return pointers to string
420                               buffer of referenced variable, because it can
421                               be clobbered throug magic callbacks */
422                            SEPARATE_ZVAL(arg);
423                        }
424                        *p = Z_STRVAL_PP(arg);
425                        *pl = Z_STRLEN_PP(arg);
426                        break;
427
428                    case IS_OBJECT:
429                    case IS_ARRAY:
430                    case IS_RESOURCE:
431                    default:
432                        return "string";
433                }
434            }
435            break;
436
437        case 'b':
438            {
439                zend_bool *p = va_arg(*va, zend_bool *);
440                switch (Z_TYPE_PP(arg)) {
441                    case IS_NULL:
442                    case IS_STRING:
443                    case IS_LONG:
444                    case IS_DOUBLE:
445                    case IS_BOOL:
446                        convert_to_boolean_ex(arg);
447                        *p = Z_BVAL_PP(arg);
448                        break;
449
450                    case IS_ARRAY:
451                    case IS_OBJECT:
452                    case IS_RESOURCE:
453                    default:
454                        return "boolean";
455                }
456            }
457            break;
458
459        case 'r':
460            {
461                zval **p = va_arg(*va, zval **);
462                if (return_null) {
463                    *p = NULL;
464                    break;
465                }
466                if (Z_TYPE_PP(arg) == IS_RESOURCE) {
467                    *p = *arg;
468                } else {
469                    return "resource";
470                }
471            }
472            break;
473        case 'A':
474        case 'a':
475            {
476                zval **p = va_arg(*va, zval **);
477                if (return_null) {
478                    *p = NULL;
479                    break;
480                }
481                if (Z_TYPE_PP(arg) == IS_ARRAY || (c == 'A' && Z_TYPE_PP(arg) == IS_OBJECT)) {
482                    *p = *arg;
483                } else {
484                    return "array";
485                }
486            }
487            break;
488        case 'H':
489        case 'h':
490            {
491                HashTable **p = va_arg(*va, HashTable **);
492                if (return_null) {
493                    *p = NULL;
494                    break;
495                }
496                if (Z_TYPE_PP(arg) == IS_ARRAY) {
497                    *p = Z_ARRVAL_PP(arg);
498                } else if(c == 'H' && Z_TYPE_PP(arg) == IS_OBJECT) {
499                    *p = HASH_OF(*arg);
500                    if(*p == NULL) {
501                        return "array";
502                    }
503                } else {
504                    return "array";
505                }
506            }
507            break;
508
509        case 'o':
510            {
511                zval **p = va_arg(*va, zval **);
512                if (return_null) {
513                    *p = NULL;
514                    break;
515                }
516                if (Z_TYPE_PP(arg) == IS_OBJECT) {
517                    *p = *arg;
518                } else {
519                    return "object";
520                }
521            }
522            break;
523
524        case 'O':
525            {
526                zval **p = va_arg(*va, zval **);
527                zend_class_entry *ce = va_arg(*va, zend_class_entry *);
528
529                if (return_null) {
530                    *p = NULL;
531                    break;
532                }
533                if (Z_TYPE_PP(arg) == IS_OBJECT &&
534                        (!ce || instanceof_function(Z_OBJCE_PP(arg), ce TSRMLS_CC))) {
535                    *p = *arg;
536                } else {
537                    if (ce) {
538                        return ce->name;
539                    } else {
540                        return "object";
541                    }
542                }
543            }
544            break;
545
546        case 'C':
547            {
548                zend_class_entry **lookup, **pce = va_arg(*va, zend_class_entry **);
549                zend_class_entry *ce_base = *pce;
550
551                if (return_null) {
552                    *pce = NULL;
553                    break;
554                }
555                convert_to_string_ex(arg);
556                if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &lookup TSRMLS_CC) == FAILURE) {
557                    *pce = NULL;
558                } else {
559                    *pce = *lookup;
560                }
561                if (ce_base) {
562                    if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
563                        zend_spprintf(error, 0, "to be a class name derived from %s, '%s' given",
564                            ce_base->name, Z_STRVAL_PP(arg));
565                        *pce = NULL;
566                        return "";
567                    }
568                }
569                if (!*pce) {
570                    zend_spprintf(error, 0, "to be a valid class name, '%s' given",
571                        Z_STRVAL_PP(arg));
572                    return "";
573                }
574                break;
575
576            }
577            break;
578
579        case 'f':
580            {
581                zend_fcall_info *fci = va_arg(*va, zend_fcall_info *);
582                zend_fcall_info_cache *fcc = va_arg(*va, zend_fcall_info_cache *);
583                char *is_callable_error = NULL;
584
585                if (return_null) {
586                    fci->size = 0;
587                    fcc->initialized = 0;
588                    break;
589                }
590
591                if (zend_fcall_info_init(*arg, 0, fci, fcc, NULL, &is_callable_error TSRMLS_CC) == SUCCESS) {
592                    if (is_callable_error) {
593                        *severity = E_STRICT;
594                        zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
595                        efree(is_callable_error);
596                        *spec = spec_walk;
597                        return "";
598                    }
599                    break;
600                } else {
601                    if (is_callable_error) {
602                        *severity = E_WARNING;
603                        zend_spprintf(error, 0, "to be a valid callback, %s", is_callable_error);
604                        efree(is_callable_error);
605                        return "";
606                    } else {
607                        return "valid callback";
608                    }
609                }
610            }
611
612        case 'z':
613            {
614                zval **p = va_arg(*va, zval **);
615                if (return_null) {
616                    *p = NULL;
617                } else {
618                    *p = *arg;
619                }
620            }
621            break;
622
623        case 'Z':
624            {
625                zval ***p = va_arg(*va, zval ***);
626                if (return_null) {
627                    *p = NULL;
628                } else {
629                    *p = arg;
630                }
631            }
632            break;
633
634        default:
635            return "unknown";
636    }
637
638    *spec = spec_walk;
639
640    return NULL;
641}
642/* }}} */
643
644static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) /* {{{ */
645{
646    char *expected_type = NULL, *error = NULL;
647    int severity = E_WARNING;
648
649    expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity TSRMLS_CC);
650    if (expected_type) {
651        if (!quiet && (*expected_type || error)) {
652            char *space;
653            char *class_name = get_active_class_name(&space TSRMLS_CC);
654
655            if (error) {
656                zend_error(severity, "%s%s%s() expects parameter %d %s",
657                        class_name, space, get_active_function_name(TSRMLS_C), arg_num, error);
658                efree(error);
659            } else {
660                zend_error(severity, "%s%s%s() expects parameter %d to be %s, %s given",
661                        class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
662                        zend_zval_type_name(*arg));
663            }
664        }
665        if (severity != E_STRICT) {
666            return FAILURE;
667        }
668    }
669
670    return SUCCESS;
671}
672/* }}} */
673
674static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int flags TSRMLS_DC) /* {{{ */
675{
676    char *spec_walk;
677    int c, i;
678    int min_num_args = -1;
679    int max_num_args = 0;
680    int post_varargs = 0;
681    zval **arg;
682    int arg_count = (int)(zend_uintptr_t) *(zend_vm_stack_top(TSRMLS_C) - 1);
683    int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
684    zend_bool have_varargs = 0;
685    zval ****varargs = NULL;
686    int *n_varargs = NULL;
687
688    for (spec_walk = type_spec; *spec_walk; spec_walk++) {
689        c = *spec_walk;
690        switch (c) {
691            case 's':
692                if (max_num_args < arg_count) {
693                    arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - max_num_args));
694                    if (Z_TYPE_PP(arg) == IS_OBJECT) {
695                        parse_arg_object_to_string(arg TSRMLS_CC);
696                    }
697                }
698                /* break missing intentionally */
699            case 'l': case 'd':
700            case 'H': case 'b':
701            case 'r': case 'a':
702            case 'o': case 'O':
703            case 'z': case 'Z':
704            case 'C': case 'h':
705            case 'f': case 'A':
706                max_num_args++;
707                break;
708
709            case '|':
710                min_num_args = max_num_args;
711                break;
712
713            case '/':
714            case '!':
715                /* Pass */
716                break;
717
718            case '*':
719            case '+':
720                if (have_varargs) {
721                    if (!quiet) {
722                        zend_function *active_function = EG(current_execute_data)->function_state.function;
723                        char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
724                        zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted",
725                                class_name,
726                                class_name[0] ? "::" : "",
727                                active_function->common.function_name);
728                    }
729                    return FAILURE;
730                }
731                have_varargs = 1;
732                /* we expect at least one parameter in varargs */
733                if (c == '+') {
734                    max_num_args++;
735                }
736                /* mark the beginning of varargs */
737                post_varargs = max_num_args;
738                break;
739
740            default:
741                if (!quiet) {
742                    zend_function *active_function = EG(current_execute_data)->function_state.function;
743                    char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
744                    zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
745                            class_name,
746                            class_name[0] ? "::" : "",
747                            active_function->common.function_name);
748                }
749                return FAILURE;
750        }
751    }
752
753    if (min_num_args < 0) {
754        min_num_args = max_num_args;
755    }
756
757    if (have_varargs) {
758        /* calculate how many required args are at the end of the specifier list */
759        post_varargs = max_num_args - post_varargs;
760        max_num_args = -1;
761    }
762
763    if (num_args < min_num_args || (num_args > max_num_args && max_num_args > 0)) {
764        if (!quiet) {
765            zend_function *active_function = EG(current_execute_data)->function_state.function;
766            char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
767            zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
768                    class_name,
769                    class_name[0] ? "::" : "",
770                    active_function->common.function_name,
771                    min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
772                    num_args < min_num_args ? min_num_args : max_num_args,
773                    (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
774                    num_args);
775        }
776        return FAILURE;
777    }
778
779    if (num_args > arg_count) {
780        zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
781            get_active_function_name(TSRMLS_C));
782        return FAILURE;
783    }
784
785    i = 0;
786    while (num_args-- > 0) {
787        if (*type_spec == '|') {
788            type_spec++;
789        }
790
791        if (*type_spec == '*' || *type_spec == '+') {
792            int num_varargs = num_args + 1 - post_varargs;
793
794            /* eat up the passed in storage even if it won't be filled in with varargs */
795            varargs = va_arg(*va, zval ****);
796            n_varargs = va_arg(*va, int *);
797            type_spec++;
798
799            if (num_varargs > 0) {
800                int iv = 0;
801                zval **p = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count - i));
802
803                *n_varargs = num_varargs;
804
805                /* allocate space for array and store args */
806                *varargs = safe_emalloc(num_varargs, sizeof(zval **), 0);
807                while (num_varargs-- > 0) {
808                    (*varargs)[iv++] = p++;
809                }
810
811                /* adjust how many args we have left and restart loop */
812                num_args = num_args + 1 - iv;
813                i += iv;
814                continue;
815            } else {
816                *varargs = NULL;
817                *n_varargs = 0;
818            }
819        }
820
821        arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (arg_count-i));
822
823        if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
824            /* clean up varargs array if it was used */
825            if (varargs && *varargs) {
826                efree(*varargs);
827                *varargs = NULL;
828            }
829            return FAILURE;
830        }
831        i++;
832    }
833
834    return SUCCESS;
835}
836/* }}} */
837
838#define RETURN_IF_ZERO_ARGS(num_args, type_spec, quiet) { \
839    int __num_args = (num_args); \
840    \
841    if (0 == (type_spec)[0] && 0 != __num_args && !(quiet)) { \
842        char *__space; \
843        char * __class_name = get_active_class_name(&__space TSRMLS_CC); \
844        zend_error(E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \
845            __class_name, __space, \
846            get_active_function_name(TSRMLS_C), __num_args); \
847        return FAILURE; \
848    }\
849}
850
851ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
852{
853    va_list va;
854    int retval;
855
856    RETURN_IF_ZERO_ARGS(num_args, type_spec, flags & ZEND_PARSE_PARAMS_QUIET);
857
858    va_start(va, type_spec);
859    retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
860    va_end(va);
861
862    return retval;
863}
864/* }}} */
865
866ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...) /* {{{ */
867{
868    va_list va;
869    int retval;
870
871    RETURN_IF_ZERO_ARGS(num_args, type_spec, 0);
872
873    va_start(va, type_spec);
874    retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
875    va_end(va);
876
877    return retval;
878}
879/* }}} */
880
881ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
882{
883    va_list va;
884    int retval;
885    char *p = type_spec;
886    zval **object;
887    zend_class_entry *ce;
888
889    if (!this_ptr) {
890        RETURN_IF_ZERO_ARGS(num_args, p, 0);
891
892        va_start(va, type_spec);
893        retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC);
894        va_end(va);
895    } else {
896        p++;
897        RETURN_IF_ZERO_ARGS(num_args, p, 0);
898
899        va_start(va, type_spec);
900
901        object = va_arg(va, zval **);
902        ce = va_arg(va, zend_class_entry *);
903        *object = this_ptr;
904
905        if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
906            zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
907                ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
908        }
909
910        retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC);
911        va_end(va);
912    }
913    return retval;
914}
915/* }}} */
916
917ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) /* {{{ */
918{
919    va_list va;
920    int retval;
921    char *p = type_spec;
922    zval **object;
923    zend_class_entry *ce;
924    int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
925
926    if (!this_ptr) {
927        RETURN_IF_ZERO_ARGS(num_args, p, quiet);
928
929        va_start(va, type_spec);
930        retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC);
931        va_end(va);
932    } else {
933        p++;
934        RETURN_IF_ZERO_ARGS(num_args, p, quiet);
935
936        va_start(va, type_spec);
937
938        object = va_arg(va, zval **);
939        ce = va_arg(va, zend_class_entry *);
940        *object = this_ptr;
941
942        if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
943            if (!quiet) {
944                zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
945                    ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
946            }
947            va_end(va);
948            return FAILURE;
949        }
950
951        retval = zend_parse_va_args(num_args, p, &va, flags TSRMLS_CC);
952        va_end(va);
953    }
954    return retval;
955}
956/* }}} */
957
958/* Argument parsing API -- andrei */
959ZEND_API int _array_init(zval *arg, uint size ZEND_FILE_LINE_DC) /* {{{ */
960{
961    ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));
962
963    _zend_hash_init(Z_ARRVAL_P(arg), size, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
964    Z_TYPE_P(arg) = IS_ARRAY;
965    return SUCCESS;
966}
967/* }}} */
968
969static int zend_merge_property(zval **value TSRMLS_DC, int num_args, va_list args, const zend_hash_key *hash_key) /* {{{ */
970{
971    /* which name should a numeric property have ? */
972    if (hash_key->nKeyLength) {
973        zval *obj = va_arg(args, zval *);
974        zend_object_handlers *obj_ht = va_arg(args, zend_object_handlers *);
975        zval *member;
976
977        MAKE_STD_ZVAL(member);
978        ZVAL_STRINGL(member, hash_key->arKey, hash_key->nKeyLength-1, 1);
979        obj_ht->write_property(obj, member, *value TSRMLS_CC);
980        zval_ptr_dtor(&member);
981    }
982    return ZEND_HASH_APPLY_KEEP;
983}
984/* }}} */
985
986/* This function should be called after the constructor has been called
987 * because it may call __set from the uninitialized object otherwise. */
988ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destroy_ht TSRMLS_DC) /* {{{ */
989{
990    zend_object_handlers *obj_ht = Z_OBJ_HT_P(obj);
991    zend_class_entry *old_scope = EG(scope);
992
993    EG(scope) = Z_OBJCE_P(obj);
994    zend_hash_apply_with_arguments(properties TSRMLS_CC, (apply_func_args_t)zend_merge_property, 2, obj, obj_ht);
995    EG(scope) = old_scope;
996
997    if (destroy_ht) {
998        zend_hash_destroy(properties);
999        FREE_HASHTABLE(properties);
1000    }
1001}
1002/* }}} */
1003
1004ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
1005{
1006    if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) {
1007        zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry);
1008        zend_class_entry *old_scope = *scope;
1009
1010        *scope = class_type;
1011        zend_hash_apply_with_argument(&class_type->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
1012        zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
1013
1014        if (!CE_STATIC_MEMBERS(class_type)) {
1015            HashPosition pos;
1016            zval **p;
1017
1018            if (class_type->parent) {
1019                zend_update_class_constants(class_type->parent TSRMLS_CC);
1020            }
1021#if ZTS
1022            ALLOC_HASHTABLE(CG(static_members)[(zend_intptr_t)(class_type->static_members)]);
1023#else
1024            ALLOC_HASHTABLE(class_type->static_members);
1025#endif
1026            zend_hash_init(CE_STATIC_MEMBERS(class_type), zend_hash_num_elements(&class_type->default_static_members), NULL, ZVAL_PTR_DTOR, 0);
1027
1028            zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos);
1029            while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) {
1030                char *str_index;
1031                uint str_length;
1032                ulong num_index;
1033                zval **q;
1034
1035                zend_hash_get_current_key_ex(&class_type->default_static_members, &str_index, &str_length, &num_index, 0, &pos);
1036                if (Z_ISREF_PP(p) &&
1037                    class_type->parent &&
1038                    zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
1039                    *p == *q &&
1040                    zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS
1041                ) {
1042                    Z_ADDREF_PP(q);
1043                    Z_SET_ISREF_PP(q);
1044                    zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL);
1045                } else {
1046                    zval *r;
1047
1048                    ALLOC_ZVAL(r);
1049                    *r = **p;
1050                    INIT_PZVAL(r);
1051                    zval_copy_ctor(r);
1052                    zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)&r, sizeof(zval*), NULL);
1053                }
1054                zend_hash_move_forward_ex(&class_type->default_static_members, &pos);
1055            }
1056        }
1057        zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
1058
1059        *scope = old_scope;
1060        class_type->constants_updated = 1;
1061    }
1062}
1063/* }}} */
1064
1065/* This function requires 'properties' to contain all props declared in the
1066 * class and all props being public. If only a subset is given or the class
1067 * has protected members then you need to merge the properties seperately by
1068 * calling zend_merge_properties(). */
1069ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type, HashTable *properties ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1070{
1071    zval *tmp;
1072    zend_object *object;
1073
1074    if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
1075        char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class";
1076        zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
1077    }
1078
1079    zend_update_class_constants(class_type TSRMLS_CC);
1080
1081    Z_TYPE_P(arg) = IS_OBJECT;
1082    if (class_type->create_object == NULL) {
1083        Z_OBJVAL_P(arg) = zend_objects_new(&object, class_type TSRMLS_CC);
1084        if (properties) {
1085            object->properties = properties;
1086        } else {
1087            ALLOC_HASHTABLE_REL(object->properties);
1088            zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0);
1089            zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void *) &tmp, sizeof(zval *));
1090        }
1091    } else {
1092        Z_OBJVAL_P(arg) = class_type->create_object(class_type TSRMLS_CC);
1093    }
1094    return SUCCESS;
1095}
1096/* }}} */
1097
1098ZEND_API int _object_init_ex(zval *arg, zend_class_entry *class_type ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1099{
1100    return _object_and_properties_init(arg, class_type, 0 ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
1101}
1102/* }}} */
1103
1104ZEND_API int _object_init(zval *arg ZEND_FILE_LINE_DC TSRMLS_DC) /* {{{ */
1105{
1106    return _object_init_ex(arg, zend_standard_class_def ZEND_FILE_LINE_RELAY_CC TSRMLS_CC);
1107}
1108/* }}} */
1109
1110ZEND_API int add_assoc_function(zval *arg, const char *key, void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) /* {{{ */
1111{
1112    zend_error(E_WARNING, "add_assoc_function() is no longer supported");
1113    return FAILURE;
1114}
1115/* }}} */
1116
1117ZEND_API int add_assoc_long_ex(zval *arg, const char *key, uint key_len, long n) /* {{{ */
1118{
1119    zval *tmp;
1120
1121    MAKE_STD_ZVAL(tmp);
1122    ZVAL_LONG(tmp, n);
1123
1124    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1125}
1126/* }}} */
1127
1128ZEND_API int add_assoc_null_ex(zval *arg, const char *key, uint key_len) /* {{{ */
1129{
1130    zval *tmp;
1131
1132    MAKE_STD_ZVAL(tmp);
1133    ZVAL_NULL(tmp);
1134
1135    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1136}
1137/* }}} */
1138
1139ZEND_API int add_assoc_bool_ex(zval *arg, const char *key, uint key_len, int b) /* {{{ */
1140{
1141    zval *tmp;
1142
1143    MAKE_STD_ZVAL(tmp);
1144    ZVAL_BOOL(tmp, b);
1145
1146    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1147}
1148/* }}} */
1149
1150ZEND_API int add_assoc_resource_ex(zval *arg, const char *key, uint key_len, int r) /* {{{ */
1151{
1152    zval *tmp;
1153
1154    MAKE_STD_ZVAL(tmp);
1155    ZVAL_RESOURCE(tmp, r);
1156
1157    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1158}
1159/* }}} */
1160
1161ZEND_API int add_assoc_double_ex(zval *arg, const char *key, uint key_len, double d) /* {{{ */
1162{
1163    zval *tmp;
1164
1165    MAKE_STD_ZVAL(tmp);
1166    ZVAL_DOUBLE(tmp, d);
1167
1168    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1169}
1170/* }}} */
1171
1172ZEND_API int add_assoc_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate) /* {{{ */
1173{
1174    zval *tmp;
1175
1176    MAKE_STD_ZVAL(tmp);
1177    ZVAL_STRING(tmp, str, duplicate);
1178
1179    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1180}
1181/* }}} */
1182
1183ZEND_API int add_assoc_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate) /* {{{ */
1184{
1185    zval *tmp;
1186
1187    MAKE_STD_ZVAL(tmp);
1188    ZVAL_STRINGL(tmp, str, length, duplicate);
1189
1190    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
1191}
1192/* }}} */
1193
1194ZEND_API int add_assoc_zval_ex(zval *arg, const char *key, uint key_len, zval *value) /* {{{ */
1195{
1196    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL);
1197}
1198/* }}} */
1199
1200ZEND_API int add_index_long(zval *arg, ulong index, long n) /* {{{ */
1201{
1202    zval *tmp;
1203
1204    MAKE_STD_ZVAL(tmp);
1205    ZVAL_LONG(tmp, n);
1206
1207    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1208}
1209/* }}} */
1210
1211ZEND_API int add_index_null(zval *arg, ulong index) /* {{{ */
1212{
1213    zval *tmp;
1214
1215    MAKE_STD_ZVAL(tmp);
1216    ZVAL_NULL(tmp);
1217
1218    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1219}
1220/* }}} */
1221
1222ZEND_API int add_index_bool(zval *arg, ulong index, int b) /* {{{ */
1223{
1224    zval *tmp;
1225
1226    MAKE_STD_ZVAL(tmp);
1227    ZVAL_BOOL(tmp, b);
1228
1229    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1230}
1231/* }}} */
1232
1233ZEND_API int add_index_resource(zval *arg, ulong index, int r) /* {{{ */
1234{
1235    zval *tmp;
1236
1237    MAKE_STD_ZVAL(tmp);
1238    ZVAL_RESOURCE(tmp, r);
1239
1240    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1241}
1242/* }}} */
1243
1244ZEND_API int add_index_double(zval *arg, ulong index, double d) /* {{{ */
1245{
1246    zval *tmp;
1247
1248    MAKE_STD_ZVAL(tmp);
1249    ZVAL_DOUBLE(tmp, d);
1250
1251    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1252}
1253/* }}} */
1254
1255ZEND_API int add_index_string(zval *arg, ulong index, const char *str, int duplicate) /* {{{ */
1256{
1257    zval *tmp;
1258
1259    MAKE_STD_ZVAL(tmp);
1260    ZVAL_STRING(tmp, str, duplicate);
1261
1262    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1263}
1264/* }}} */
1265
1266ZEND_API int add_index_stringl(zval *arg, ulong index, const char *str, uint length, int duplicate) /* {{{ */
1267{
1268    zval *tmp;
1269
1270    MAKE_STD_ZVAL(tmp);
1271    ZVAL_STRINGL(tmp, str, length, duplicate);
1272
1273    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
1274}
1275/* }}} */
1276
1277ZEND_API int add_index_zval(zval *arg, ulong index, zval *value) /* {{{ */
1278{
1279    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL);
1280}
1281/* }}} */
1282
1283ZEND_API int add_next_index_long(zval *arg, long n) /* {{{ */
1284{
1285    zval *tmp;
1286
1287    MAKE_STD_ZVAL(tmp);
1288    ZVAL_LONG(tmp, n);
1289
1290    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1291}
1292/* }}} */
1293
1294ZEND_API int add_next_index_null(zval *arg) /* {{{ */
1295{
1296    zval *tmp;
1297
1298    MAKE_STD_ZVAL(tmp);
1299    ZVAL_NULL(tmp);
1300
1301    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1302}
1303/* }}} */
1304
1305ZEND_API int add_next_index_bool(zval *arg, int b) /* {{{ */
1306{
1307    zval *tmp;
1308
1309    MAKE_STD_ZVAL(tmp);
1310    ZVAL_BOOL(tmp, b);
1311
1312    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1313}
1314/* }}} */
1315
1316ZEND_API int add_next_index_resource(zval *arg, int r) /* {{{ */
1317{
1318    zval *tmp;
1319
1320    MAKE_STD_ZVAL(tmp);
1321    ZVAL_RESOURCE(tmp, r);
1322
1323    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1324}
1325/* }}} */
1326
1327ZEND_API int add_next_index_double(zval *arg, double d) /* {{{ */
1328{
1329    zval *tmp;
1330
1331    MAKE_STD_ZVAL(tmp);
1332    ZVAL_DOUBLE(tmp, d);
1333
1334    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1335}
1336/* }}} */
1337
1338ZEND_API int add_next_index_string(zval *arg, const char *str, int duplicate) /* {{{ */
1339{
1340    zval *tmp;
1341
1342    MAKE_STD_ZVAL(tmp);
1343    ZVAL_STRING(tmp, str, duplicate);
1344
1345    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1346}
1347/* }}} */
1348
1349ZEND_API int add_next_index_stringl(zval *arg, const char *str, uint length, int duplicate) /* {{{ */
1350{
1351    zval *tmp;
1352
1353    MAKE_STD_ZVAL(tmp);
1354    ZVAL_STRINGL(tmp, str, length, duplicate);
1355
1356    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
1357}
1358/* }}} */
1359
1360ZEND_API int add_next_index_zval(zval *arg, zval *value) /* {{{ */
1361{
1362    return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
1363}
1364/* }}} */
1365
1366ZEND_API int add_get_assoc_string_ex(zval *arg, const char *key, uint key_len, const char *str, void **dest, int duplicate) /* {{{ */
1367{
1368    zval *tmp;
1369
1370    MAKE_STD_ZVAL(tmp);
1371    ZVAL_STRING(tmp, str, duplicate);
1372
1373    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
1374}
1375/* }}} */
1376
1377ZEND_API int add_get_assoc_stringl_ex(zval *arg, const char *key, uint key_len, const char *str, uint length, void **dest, int duplicate) /* {{{ */
1378{
1379    zval *tmp;
1380
1381    MAKE_STD_ZVAL(tmp);
1382    ZVAL_STRINGL(tmp, str, length, duplicate);
1383
1384    return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), dest);
1385}
1386/* }}} */
1387
1388ZEND_API int add_get_index_long(zval *arg, ulong index, long l, void **dest) /* {{{ */
1389{
1390    zval *tmp;
1391
1392    MAKE_STD_ZVAL(tmp);
1393    ZVAL_LONG(tmp, l);
1394
1395    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1396}
1397/* }}} */
1398
1399ZEND_API int add_get_index_double(zval *arg, ulong index, double d, void **dest) /* {{{ */
1400{
1401    zval *tmp;
1402
1403    MAKE_STD_ZVAL(tmp);
1404    ZVAL_DOUBLE(tmp, d);
1405
1406    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1407}
1408/* }}} */
1409
1410ZEND_API int add_get_index_string(zval *arg, ulong index, const char *str, void **dest, int duplicate) /* {{{ */
1411{
1412    zval *tmp;
1413
1414    MAKE_STD_ZVAL(tmp);
1415    ZVAL_STRING(tmp, str, duplicate);
1416
1417    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1418}
1419/* }}} */
1420
1421ZEND_API int add_get_index_stringl(zval *arg, ulong index, const char *str, uint length, void **dest, int duplicate) /* {{{ */
1422{
1423    zval *tmp;
1424
1425    MAKE_STD_ZVAL(tmp);
1426    ZVAL_STRINGL(tmp, str, length, duplicate);
1427
1428    return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
1429}
1430/* }}} */
1431
1432ZEND_API int add_property_long_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
1433{
1434    zval *tmp;
1435    zval *z_key;
1436
1437    MAKE_STD_ZVAL(tmp);
1438    ZVAL_LONG(tmp, n);
1439
1440    MAKE_STD_ZVAL(z_key);
1441    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1442
1443    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1444    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1445    zval_ptr_dtor(&z_key);
1446    return SUCCESS;
1447}
1448/* }}} */
1449
1450ZEND_API int add_property_bool_ex(zval *arg, const char *key, uint key_len, int b TSRMLS_DC) /* {{{ */
1451{
1452    zval *tmp;
1453    zval *z_key;
1454
1455    MAKE_STD_ZVAL(tmp);
1456    ZVAL_BOOL(tmp, b);
1457
1458    MAKE_STD_ZVAL(z_key);
1459    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1460
1461    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1462    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1463    zval_ptr_dtor(&z_key);
1464    return SUCCESS;
1465}
1466/* }}} */
1467
1468ZEND_API int add_property_null_ex(zval *arg, const char *key, uint key_len TSRMLS_DC) /* {{{ */
1469{
1470    zval *tmp;
1471    zval *z_key;
1472
1473    MAKE_STD_ZVAL(tmp);
1474    ZVAL_NULL(tmp);
1475
1476    MAKE_STD_ZVAL(z_key);
1477    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1478
1479    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1480    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1481    zval_ptr_dtor(&z_key);
1482    return SUCCESS;
1483}
1484/* }}} */
1485
1486ZEND_API int add_property_resource_ex(zval *arg, const char *key, uint key_len, long n TSRMLS_DC) /* {{{ */
1487{
1488    zval *tmp;
1489    zval *z_key;
1490
1491    MAKE_STD_ZVAL(tmp);
1492    ZVAL_RESOURCE(tmp, n);
1493
1494    MAKE_STD_ZVAL(z_key);
1495    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1496
1497    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1498    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1499    zval_ptr_dtor(&z_key);
1500    return SUCCESS;
1501}
1502/* }}} */
1503
1504ZEND_API int add_property_double_ex(zval *arg, const char *key, uint key_len, double d TSRMLS_DC) /* {{{ */
1505{
1506    zval *tmp;
1507    zval *z_key;
1508
1509    MAKE_STD_ZVAL(tmp);
1510    ZVAL_DOUBLE(tmp, d);
1511
1512    MAKE_STD_ZVAL(z_key);
1513    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1514
1515    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1516    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1517    zval_ptr_dtor(&z_key);
1518    return SUCCESS;
1519}
1520/* }}} */
1521
1522ZEND_API int add_property_string_ex(zval *arg, const char *key, uint key_len, char *str, int duplicate TSRMLS_DC) /* {{{ */
1523{
1524    zval *tmp;
1525    zval *z_key;
1526
1527    MAKE_STD_ZVAL(tmp);
1528    ZVAL_STRING(tmp, str, duplicate);
1529
1530    MAKE_STD_ZVAL(z_key);
1531    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1532
1533    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1534    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1535    zval_ptr_dtor(&z_key);
1536    return SUCCESS;
1537}
1538/* }}} */
1539
1540ZEND_API int add_property_stringl_ex(zval *arg, const char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) /* {{{ */
1541{
1542    zval *tmp;
1543    zval *z_key;
1544
1545    MAKE_STD_ZVAL(tmp);
1546    ZVAL_STRINGL(tmp, str, length, duplicate);
1547
1548    MAKE_STD_ZVAL(z_key);
1549    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1550
1551    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, tmp TSRMLS_CC);
1552    zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */
1553    zval_ptr_dtor(&z_key);
1554    return SUCCESS;
1555}
1556/* }}} */
1557
1558ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval *value TSRMLS_DC) /* {{{ */
1559{
1560    zval *z_key;
1561
1562    MAKE_STD_ZVAL(z_key);
1563    ZVAL_STRINGL(z_key, key, key_len-1, 1);
1564
1565    Z_OBJ_HANDLER_P(arg, write_property)(arg, z_key, value TSRMLS_CC);
1566    zval_ptr_dtor(&z_key);
1567    return SUCCESS;
1568}
1569/* }}} */
1570
1571ZEND_API int zend_startup_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1572{
1573    int name_len;
1574    char *lcname;
1575
1576    if (module->module_started) {
1577        return SUCCESS;
1578    }
1579    module->module_started = 1;
1580
1581    /* Check module dependencies */
1582    if (module->deps) {
1583        const zend_module_dep *dep = module->deps;
1584
1585        while (dep->name) {
1586            if (dep->type == MODULE_DEP_REQUIRED) {
1587                zend_module_entry *req_mod;
1588
1589                name_len = strlen(dep->name);
1590                lcname = zend_str_tolower_dup(dep->name, name_len);
1591
1592                if (zend_hash_find(&module_registry, lcname, name_len+1, (void**)&req_mod) == FAILURE || !req_mod->module_started) {
1593                    efree(lcname);
1594                    /* TODO: Check version relationship */
1595                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because required module '%s' is not loaded", module->name, dep->name);
1596                    module->module_started = 0;
1597                    return FAILURE;
1598                }
1599                efree(lcname);
1600            }
1601            ++dep;
1602        }
1603    }
1604
1605    /* Initialize module globals */
1606    if (module->globals_size) {
1607#ifdef ZTS
1608        ts_allocate_id(module->globals_id_ptr, module->globals_size, (ts_allocate_ctor) module->globals_ctor, (ts_allocate_dtor) module->globals_dtor);
1609#else
1610        if (module->globals_ctor) {
1611            module->globals_ctor(module->globals_ptr TSRMLS_CC);
1612        }
1613#endif
1614    }
1615    if (module->module_startup_func) {
1616        EG(current_module) = module;
1617        if (module->module_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
1618            zend_error(E_CORE_ERROR,"Unable to start %s module", module->name);
1619            EG(current_module) = NULL;
1620            return FAILURE;
1621        }
1622        EG(current_module) = NULL;
1623    }
1624    return SUCCESS;
1625}
1626/* }}} */
1627
1628static void zend_sort_modules(void *base, size_t count, size_t siz, compare_func_t compare TSRMLS_DC) /* {{{ */
1629{
1630    Bucket **b1 = base;
1631    Bucket **b2;
1632    Bucket **end = b1 + count;
1633    Bucket *tmp;
1634    zend_module_entry *m, *r;
1635
1636    while (b1 < end) {
1637try_again:
1638        m = (zend_module_entry*)(*b1)->pData;
1639        if (!m->module_started && m->deps) {
1640            const zend_module_dep *dep = m->deps;
1641            while (dep->name) {
1642                if (dep->type == MODULE_DEP_REQUIRED || dep->type == MODULE_DEP_OPTIONAL) {
1643                    b2 = b1 + 1;
1644                    while (b2 < end) {
1645                        r = (zend_module_entry*)(*b2)->pData;
1646                        if (strcasecmp(dep->name, r->name) == 0) {
1647                            tmp = *b1;
1648                            *b1 = *b2;
1649                            *b2 = tmp;
1650                            goto try_again;
1651                        }
1652                        b2++;
1653                    }
1654                }
1655                dep++;
1656            }
1657        }
1658        b1++;
1659    }
1660}
1661/* }}} */
1662
1663ZEND_API int zend_startup_modules(TSRMLS_D) /* {{{ */
1664{
1665    zend_hash_sort(&module_registry, zend_sort_modules, NULL, 0 TSRMLS_CC);
1666    zend_hash_apply(&module_registry, (apply_func_t)zend_startup_module_ex TSRMLS_CC);
1667    return SUCCESS;
1668}
1669/* }}} */
1670
1671ZEND_API zend_module_entry* zend_register_module_ex(zend_module_entry *module TSRMLS_DC) /* {{{ */
1672{
1673    int name_len;
1674    char *lcname;
1675    zend_module_entry *module_ptr;
1676
1677    if (!module) {
1678        return NULL;
1679    }
1680
1681#if 0
1682    zend_printf("%s: Registering module %d\n", module->name, module->module_number);
1683#endif
1684
1685    /* Check module dependencies */
1686    if (module->deps) {
1687        const zend_module_dep *dep = module->deps;
1688
1689        while (dep->name) {
1690            if (dep->type == MODULE_DEP_CONFLICTS) {
1691                name_len = strlen(dep->name);
1692                lcname = zend_str_tolower_dup(dep->name, name_len);
1693
1694                if (zend_hash_exists(&module_registry, lcname, name_len+1)) {
1695                    efree(lcname);
1696                    /* TODO: Check version relationship */
1697                    zend_error(E_CORE_WARNING, "Cannot load module '%s' because conflicting module '%s' is already loaded", module->name, dep->name);
1698                    return NULL;
1699                }
1700                efree(lcname);
1701            }
1702            ++dep;
1703        }
1704    }
1705
1706    name_len = strlen(module->name);
1707    lcname = zend_str_tolower_dup(module->name, name_len);
1708
1709    if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) {
1710        zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);
1711        efree(lcname);
1712        return NULL;
1713    }
1714    efree(lcname);
1715    module = module_ptr;
1716    EG(current_module) = module;
1717
1718    if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) {
1719        EG(current_module) = NULL;
1720        zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name);
1721        return NULL;
1722    }
1723
1724    EG(current_module) = NULL;
1725    return module;
1726}
1727/* }}} */
1728
1729ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *module TSRMLS_DC) /* {{{ */
1730{
1731    module->module_number = zend_next_free_module();
1732    module->type = MODULE_PERSISTENT;
1733    return zend_register_module_ex(module TSRMLS_CC);
1734}
1735/* }}} */
1736
1737ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, int error_type TSRMLS_DC) /* {{{ */
1738{
1739    char lcname[16];
1740    int name_len;
1741
1742    /* we don't care if the function name is longer, in fact lowercasing only
1743     * the beginning of the name speeds up the check process */
1744    name_len = strlen(fptr->common.function_name);
1745    zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
1746    lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
1747
1748    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) {
1749        zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
1750    } 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) {
1751        zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
1752    } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
1753        if (fptr->common.num_args != 1) {
1754            zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
1755        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
1756            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_GET_FUNC_NAME);
1757        }
1758    } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
1759        if (fptr->common.num_args != 2) {
1760            zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
1761        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
1762            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_SET_FUNC_NAME);
1763        }
1764    } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) {
1765        if (fptr->common.num_args != 1) {
1766            zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME);
1767        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
1768            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_UNSET_FUNC_NAME);
1769        }
1770    } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
1771        if (fptr->common.num_args != 1) {
1772            zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME);
1773        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
1774            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_ISSET_FUNC_NAME);
1775        }
1776    } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
1777        if (fptr->common.num_args != 2) {
1778            zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
1779        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
1780            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME);
1781        }
1782    } else if (name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME) - 1 &&
1783        !memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1)
1784    ) {
1785        if (fptr->common.num_args != 2) {
1786            zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
1787        } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
1788            zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALLSTATIC_FUNC_NAME);
1789        }
1790    } else if (name_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 &&
1791        !memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0
1792    ) {
1793        zend_error(error_type, "Method %s::%s() cannot take arguments", ce->name, ZEND_TOSTRING_FUNC_NAME);
1794    }
1795}
1796/* }}} */
1797
1798/* registers all functions in *library_functions in the function hash */
1799ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */
1800{
1801    const zend_function_entry *ptr = functions;
1802    zend_function function, *reg_function;
1803    zend_internal_function *internal_function = (zend_internal_function *)&function;
1804    int count=0, unload=0;
1805    HashTable *target_function_table = function_table;
1806    int error_type;
1807    zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic = NULL, *__tostring = NULL;
1808    char *lowercase_name;
1809    int fname_len;
1810    char *lc_class_name = NULL;
1811    int class_name_len = 0;
1812
1813    if (type==MODULE_PERSISTENT) {
1814        error_type = E_CORE_WARNING;
1815    } else {
1816        error_type = E_WARNING;
1817    }
1818
1819    if (!target_function_table) {
1820        target_function_table = CG(function_table);
1821    }
1822    internal_function->type = ZEND_INTERNAL_FUNCTION;
1823    internal_function->module = EG(current_module);
1824
1825    if (scope) {
1826        class_name_len = strlen(scope->name);
1827        if ((lc_class_name = zend_memrchr(scope->name, '\\', class_name_len))) {
1828            ++lc_class_name;
1829            class_name_len -= (lc_class_name - scope->name);
1830            lc_class_name = zend_str_tolower_dup(lc_class_name, class_name_len);
1831        } else {
1832            lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
1833        }
1834    }
1835
1836    while (ptr->fname) {
1837        internal_function->handler = ptr->handler;
1838        internal_function->function_name = (char*)ptr->fname;
1839        internal_function->scope = scope;
1840        internal_function->prototype = NULL;
1841        if (ptr->arg_info) {
1842            internal_function->arg_info = (zend_arg_info*)ptr->arg_info+1;
1843            internal_function->num_args = ptr->num_args;
1844            /* Currently you cannot denote that the function can accept less arguments than num_args */
1845            if (ptr->arg_info[0].required_num_args == -1) {
1846                internal_function->required_num_args = ptr->num_args;
1847            } else {
1848                internal_function->required_num_args = ptr->arg_info[0].required_num_args;
1849            }
1850            internal_function->pass_rest_by_reference = ptr->arg_info[0].pass_by_reference;
1851            internal_function->return_reference = ptr->arg_info[0].return_reference;
1852        } else {
1853            internal_function->arg_info = NULL;
1854            internal_function->num_args = 0;
1855            internal_function->required_num_args = 0;
1856            internal_function->pass_rest_by_reference = 0;
1857            internal_function->return_reference = 0;
1858        }
1859        if (ptr->flags) {
1860            if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
1861                if (ptr->flags != ZEND_ACC_DEPRECATED || scope) {
1862                    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);
1863                }
1864                internal_function->fn_flags = ZEND_ACC_PUBLIC | ptr->flags;
1865            } else {
1866                internal_function->fn_flags = ptr->flags;
1867            }
1868        } else {
1869            internal_function->fn_flags = ZEND_ACC_PUBLIC;
1870        }
1871        if (ptr->flags & ZEND_ACC_ABSTRACT) {
1872            if (scope) {
1873                /* This is a class that must be abstract itself. Here we set the check info. */
1874                scope->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1875                if (!(scope->ce_flags & ZEND_ACC_INTERFACE)) {
1876                    /* Since the class is not an interface it needs to be declared as a abstract class. */
1877                    /* Since here we are handling internal functions only we can add the keyword flag. */
1878                    /* This time we set the flag for the keyword 'abstract'. */
1879                    scope->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
1880                }
1881            }
1882            if (ptr->flags & ZEND_ACC_STATIC && (!scope || !(scope->ce_flags & ZEND_ACC_INTERFACE))) {
1883                zend_error(error_type, "Static function %s%s%s() cannot be abstract", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
1884            }
1885        } else {
1886            if (scope && (scope->ce_flags & ZEND_ACC_INTERFACE)) {
1887                efree(lc_class_name);
1888                zend_error(error_type, "Interface %s cannot contain non abstract method %s()", scope->name, ptr->fname);
1889                return FAILURE;
1890            }
1891            if (!internal_function->handler) {
1892                if (scope) {
1893                    efree(lc_class_name);
1894                }
1895                zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
1896                zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
1897                return FAILURE;
1898            }
1899        }
1900        fname_len = strlen(ptr->fname);
1901        lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
1902        if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
1903            unload=1;
1904            efree(lowercase_name);
1905            break;
1906        }
1907        if (scope) {
1908            /* Look for ctor, dtor, clone
1909             * If it's an old-style constructor, store it only if we don't have
1910             * a constructor already.
1911             */
1912            if ((fname_len == class_name_len) && !memcmp(lowercase_name, lc_class_name, class_name_len+1) && !ctor) {
1913                ctor = reg_function;
1914            } else if ((fname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
1915                ctor = reg_function;
1916            } else if ((fname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME))) {
1917                dtor = reg_function;
1918                if (internal_function->num_args) {
1919                    zend_error(error_type, "Destructor %s::%s() cannot take arguments", scope->name, ptr->fname);
1920                }
1921            } else if ((fname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) {
1922                clone = reg_function;
1923            } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) {
1924                __call = reg_function;
1925            } else if ((fname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME))) {
1926                __callstatic = reg_function;
1927            } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) {
1928                __tostring = reg_function;
1929            } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) {
1930                __get = reg_function;
1931            } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) {
1932                __set = reg_function;
1933            } else if ((fname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) {
1934                __unset = reg_function;
1935            } else if ((fname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
1936                __isset = reg_function;
1937            } else {
1938                reg_function = NULL;
1939            }
1940            if (reg_function) {
1941                zend_check_magic_method_implementation(scope, reg_function, error_type TSRMLS_CC);
1942            }
1943        }
1944        ptr++;
1945        count++;
1946        efree(lowercase_name);
1947    }
1948    if (unload) { /* before unloading, display all remaining bad function in the module */
1949        if (scope) {
1950            efree(lc_class_name);
1951        }
1952        while (ptr->fname) {
1953            fname_len = strlen(ptr->fname);
1954            lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
1955            if (zend_hash_exists(target_function_table, lowercase_name, fname_len+1)) {
1956                zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
1957            }
1958            efree(lowercase_name);
1959            ptr++;
1960        }
1961        zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
1962        return FAILURE;
1963    }
1964    if (scope) {
1965        scope->constructor = ctor;
1966        scope->destructor = dtor;
1967        scope->clone = clone;
1968        scope->__call = __call;
1969        scope->__callstatic = __callstatic;
1970        scope->__tostring = __tostring;
1971        scope->__get = __get;
1972        scope->__set = __set;
1973        scope->__unset = __unset;
1974        scope->__isset = __isset;
1975        if (ctor) {
1976            ctor->common.fn_flags |= ZEND_ACC_CTOR;
1977            if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
1978                zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, ctor->common.function_name);
1979            }
1980            ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
1981        }
1982        if (dtor) {
1983            dtor->common.fn_flags |= ZEND_ACC_DTOR;
1984            if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
1985                zend_error(error_type, "Destructor %s::%s() cannot be static", scope->name, dtor->common.function_name);
1986            }
1987            dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
1988        }
1989        if (clone) {
1990            clone->common.fn_flags |= ZEND_ACC_CLONE;
1991            if (clone->common.fn_flags & ZEND_ACC_STATIC) {
1992                zend_error(error_type, "Constructor %s::%s() cannot be static", scope->name, clone->common.function_name);
1993            }
1994            clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
1995        }
1996        if (__call) {
1997            if (__call->common.fn_flags & ZEND_ACC_STATIC) {
1998                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __call->common.function_name);
1999            }
2000            __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2001        }
2002        if (__callstatic) {
2003            if (!(__callstatic->common.fn_flags & ZEND_ACC_STATIC)) {
2004                zend_error(error_type, "Method %s::%s() must be static", scope->name, __callstatic->common.function_name);
2005            }
2006            __callstatic->common.fn_flags |= ZEND_ACC_STATIC;
2007        }
2008        if (__tostring) {
2009            if (__tostring->common.fn_flags & ZEND_ACC_STATIC) {
2010                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name);
2011            }
2012            __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2013        }
2014        if (__get) {
2015            if (__get->common.fn_flags & ZEND_ACC_STATIC) {
2016                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name);
2017            }
2018            __get->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2019        }
2020        if (__set) {
2021            if (__set->common.fn_flags & ZEND_ACC_STATIC) {
2022                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __set->common.function_name);
2023            }
2024            __set->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2025        }
2026        if (__unset) {
2027            if (__unset->common.fn_flags & ZEND_ACC_STATIC) {
2028                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __unset->common.function_name);
2029            }
2030            __unset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2031        }
2032        if (__isset) {
2033            if (__isset->common.fn_flags & ZEND_ACC_STATIC) {
2034                zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __isset->common.function_name);
2035            }
2036            __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
2037        }
2038        efree(lc_class_name);
2039    }
2040    return SUCCESS;
2041}
2042/* }}} */
2043
2044/* count=-1 means erase all functions, otherwise,
2045 * erase the first count functions
2046 */
2047ZEND_API void zend_unregister_functions(const zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC) /* {{{ */
2048{
2049    const zend_function_entry *ptr = functions;
2050    int i=0;
2051    HashTable *target_function_table = function_table;
2052
2053    if (!target_function_table) {
2054        target_function_table = CG(function_table);
2055    }
2056    while (ptr->fname) {
2057        if (count!=-1 && i>=count) {
2058            break;
2059        }
2060#if 0
2061        zend_printf("Unregistering %s()\n", ptr->fname);
2062#endif
2063        zend_hash_del(target_function_table, ptr->fname, strlen(ptr->fname)+1);
2064        ptr++;
2065        i++;
2066    }
2067}
2068/* }}} */
2069
2070ZEND_API int zend_startup_module(zend_module_entry *module) /* {{{ */
2071{
2072    TSRMLS_FETCH();
2073
2074    if ((module = zend_register_internal_module(module TSRMLS_CC)) != NULL && zend_startup_module_ex(module TSRMLS_CC) == SUCCESS) {
2075        return SUCCESS;
2076    }
2077    return FAILURE;
2078}
2079/* }}} */
2080
2081ZEND_API int zend_get_module_started(const char *module_name) /* {{{ */
2082{
2083    zend_module_entry *module;
2084
2085    return (zend_hash_find(&module_registry, module_name, strlen(module_name)+1, (void**)&module) == SUCCESS && module->module_started) ? SUCCESS : FAILURE;
2086}
2087/* }}} */
2088
2089static int clean_module_class(const zend_class_entry **ce, int *module_number TSRMLS_DC) /* {{{ */
2090{
2091    if ((*ce)->type == ZEND_INTERNAL_CLASS && (*ce)->module->module_number == *module_number) {
2092        return ZEND_HASH_APPLY_REMOVE;
2093    } else {
2094        return ZEND_HASH_APPLY_KEEP;
2095    }
2096}
2097/* }}} */
2098
2099static void clean_module_classes(int module_number TSRMLS_DC) /* {{{ */
2100{
2101    zend_hash_apply_with_argument(EG(class_table), (apply_func_arg_t) clean_module_class, (void *) &module_number TSRMLS_CC);
2102}
2103/* }}} */
2104
2105void module_destructor(zend_module_entry *module) /* {{{ */
2106{
2107    TSRMLS_FETCH();
2108
2109    if (module->type == MODULE_TEMPORARY) {
2110        zend_clean_module_rsrc_dtors(module->module_number TSRMLS_CC);
2111        clean_module_constants(module->module_number TSRMLS_CC);
2112        clean_module_classes(module->module_number TSRMLS_CC);
2113    }
2114
2115    if (module->module_started && module->module_shutdown_func) {
2116#if 0
2117        zend_printf("%s: Module shutdown\n", module->name);
2118#endif
2119        module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);
2120    }
2121
2122    /* Deinitilaise module globals */
2123    if (module->globals_size) {
2124#ifdef ZTS
2125        if (*module->globals_id_ptr) {
2126            ts_free_id(*module->globals_id_ptr);
2127        }
2128#else
2129        if (module->globals_dtor) {
2130            module->globals_dtor(module->globals_ptr TSRMLS_CC);
2131        }
2132#endif
2133    }
2134
2135    module->module_started=0;
2136    if (module->functions) {
2137        zend_unregister_functions(module->functions, -1, NULL TSRMLS_CC);
2138    }
2139
2140#if HAVE_LIBDL
2141#if !(defined(NETWARE) && defined(APACHE_1_BUILD))
2142    if (module->handle && !getenv("ZEND_DONT_UNLOAD_MODULES")) {
2143        DL_UNLOAD(module->handle);
2144    }
2145#endif
2146#endif
2147}
2148/* }}} */
2149
2150/* call request startup for all modules */
2151int module_registry_request_startup(zend_module_entry *module TSRMLS_DC) /* {{{ */
2152{
2153    if (module->request_startup_func) {
2154#if 0
2155        zend_printf("%s: Request startup\n", module->name);
2156#endif
2157        if (module->request_startup_func(module->type, module->module_number TSRMLS_CC)==FAILURE) {
2158            zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
2159            exit(1);
2160        }
2161    }
2162    return 0;
2163}
2164/* }}} */
2165
2166/* call request shutdown for all modules */
2167int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) /* {{{ */
2168{
2169    if (module->request_shutdown_func) {
2170#if 0
2171        zend_printf("%s: Request shutdown\n", module->name);
2172#endif
2173        module->request_shutdown_func(module->type, module->module_number TSRMLS_CC);
2174    }
2175    return 0;
2176}
2177/* }}} */
2178
2179int module_registry_unload_temp(const zend_module_entry *module TSRMLS_DC) /* {{{ */
2180{
2181    return (module->type == MODULE_TEMPORARY) ? ZEND_HASH_APPLY_REMOVE : ZEND_HASH_APPLY_STOP;
2182}
2183/* }}} */
2184
2185/* return the next free module number */
2186int zend_next_free_module(void) /* {{{ */
2187{
2188    return zend_hash_num_elements(&module_registry) + 1;
2189}
2190/* }}} */
2191
2192static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */
2193{
2194    zend_class_entry *class_entry = malloc(sizeof(zend_class_entry));
2195    char *lowercase_name = malloc(orig_class_entry->name_length + 1);
2196    *class_entry = *orig_class_entry;
2197
2198    class_entry->type = ZEND_INTERNAL_CLASS;
2199    zend_initialize_class_data(class_entry, 0 TSRMLS_CC);
2200    class_entry->ce_flags = ce_flags;
2201    class_entry->module = EG(current_module);
2202
2203    if (class_entry->builtin_functions) {
2204        zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC);
2205    }
2206
2207    zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length);
2208    zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL);
2209    free(lowercase_name);
2210    return class_entry;
2211}
2212/* }}} */
2213
2214/* If parent_ce is not NULL then it inherits from parent_ce
2215 * If parent_ce is NULL and parent_name isn't then it looks for the parent and inherits from it
2216 * If both parent_ce and parent_name are NULL it does a regular class registration
2217 * If parent_name is specified but not found NULL is returned
2218 */
2219ZEND_API zend_class_entry *zend_register_internal_class_ex(zend_class_entry *class_entry, zend_class_entry *parent_ce, char *parent_name TSRMLS_DC) /* {{{ */
2220{
2221    zend_class_entry *register_class;
2222
2223    if (!parent_ce && parent_name) {
2224        zend_class_entry **pce;
2225        if (zend_hash_find(CG(class_table), parent_name, strlen(parent_name)+1, (void **) &pce)==FAILURE) {
2226            return NULL;
2227        } else {
2228            parent_ce = *pce;
2229        }
2230    }
2231
2232    register_class = zend_register_internal_class(class_entry TSRMLS_CC);
2233
2234    if (parent_ce) {
2235        zend_do_inheritance(register_class, parent_ce TSRMLS_CC);
2236    }
2237    return register_class;
2238}
2239/* }}} */
2240
2241ZEND_API void zend_class_implements(zend_class_entry *class_entry TSRMLS_DC, int num_interfaces, ...) /* {{{ */
2242{
2243    zend_class_entry *interface_entry;
2244    va_list interface_list;
2245    va_start(interface_list, num_interfaces);
2246
2247    while (num_interfaces--) {
2248        interface_entry = va_arg(interface_list, zend_class_entry *);
2249        zend_do_implement_interface(class_entry, interface_entry TSRMLS_CC);
2250    }
2251
2252    va_end(interface_list);
2253}
2254/* }}} */
2255
2256/* A class that contains at least one abstract method automatically becomes an abstract class.
2257 */
2258ZEND_API zend_class_entry *zend_register_internal_class(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
2259{
2260    return do_register_internal_class(orig_class_entry, 0 TSRMLS_CC);
2261}
2262/* }}} */
2263
2264ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *orig_class_entry TSRMLS_DC) /* {{{ */
2265{
2266    return do_register_internal_class(orig_class_entry, ZEND_ACC_INTERFACE TSRMLS_CC);
2267}
2268/* }}} */
2269
2270ZEND_API int zend_register_class_alias_ex(const char *name, int name_len, zend_class_entry *ce TSRMLS_DC) /* {{{ */
2271{
2272    char *lcname = zend_str_tolower_dup(name, name_len);
2273    int ret;
2274
2275    ret = zend_hash_add(CG(class_table), lcname, name_len+1, &ce, sizeof(zend_class_entry *), NULL);
2276    efree(lcname);
2277    if (ret == SUCCESS) {
2278        ce->refcount++;
2279    }
2280    return ret;
2281}
2282/* }}} */
2283
2284ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_length, zend_bool is_ref, int num_symbol_tables, ...) /* {{{ */
2285{
2286    HashTable *symbol_table;
2287    va_list symbol_table_list;
2288
2289    if (num_symbol_tables <= 0) return FAILURE;
2290
2291    Z_SET_ISREF_TO_P(symbol, is_ref);
2292
2293    va_start(symbol_table_list, num_symbol_tables);
2294    while (num_symbol_tables-- > 0) {
2295        symbol_table = va_arg(symbol_table_list, HashTable *);
2296        zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
2297        zval_add_ref(&symbol);
2298    }
2299    va_end(symbol_table_list);
2300    return SUCCESS;
2301}
2302/* }}} */
2303
2304/* Disabled functions support */
2305
2306/* {{{ proto void display_disabled_function(void)
2307Dummy function which displays an error when a disabled function is called. */
2308ZEND_API ZEND_FUNCTION(display_disabled_function)
2309{
2310    zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
2311}
2312/* }}} */
2313
2314static zend_function_entry disabled_function[] = {
2315    ZEND_FE(display_disabled_function,          NULL)
2316    ZEND_FE_END
2317};
2318
2319ZEND_API int zend_disable_function(char *function_name, uint function_name_length TSRMLS_DC) /* {{{ */
2320{
2321    if (zend_hash_del(CG(function_table), function_name, function_name_length+1)==FAILURE) {
2322        return FAILURE;
2323    }
2324    disabled_function[0].fname = function_name;
2325    return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC);
2326}
2327/* }}} */
2328
2329static zend_object_value display_disabled_class(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
2330{
2331    zend_object_value retval;
2332    zend_object *intern;
2333    retval = zend_objects_new(&intern, class_type TSRMLS_CC);
2334    ALLOC_HASHTABLE(intern->properties);
2335    zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
2336    zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
2337    return retval;
2338}
2339/* }}} */
2340
2341static const zend_function_entry disabled_class_new[] = {
2342    ZEND_FE_END
2343};
2344
2345ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_DC) /* {{{ */
2346{
2347    zend_class_entry **disabled_class;
2348
2349    zend_str_tolower(class_name, class_name_length);
2350    if (zend_hash_find(CG(class_table), class_name, class_name_length+1, (void **)&disabled_class)==FAILURE) {
2351        return FAILURE;
2352    }
2353    INIT_CLASS_ENTRY_INIT_METHODS((**disabled_class), disabled_class_new, NULL, NULL, NULL, NULL, NULL);
2354    (*disabled_class)->create_object = display_disabled_class;
2355    zend_hash_clean(&((*disabled_class)->function_table));
2356    return SUCCESS;
2357}
2358/* }}} */
2359
2360static int zend_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error TSRMLS_DC) /* {{{ */
2361{
2362    int ret = 0;
2363    zend_class_entry **pce;
2364    char *lcname = zend_str_tolower_dup(name, name_len);
2365
2366    *strict_class = 0;
2367    if (name_len == sizeof("self") - 1 &&
2368        !memcmp(lcname, "self", sizeof("self") - 1)) {
2369        if (!EG(scope)) {
2370            if (error) *error = estrdup("cannot access self:: when no class scope is active");
2371        } else {
2372            fcc->called_scope = EG(called_scope);
2373            fcc->calling_scope = EG(scope);
2374            if (!fcc->object_ptr) {
2375                fcc->object_ptr = EG(This);
2376            }
2377            ret = 1;
2378        }
2379    } else if (name_len == sizeof("parent") - 1 &&
2380               !memcmp(lcname, "parent", sizeof("parent") - 1)) {
2381        if (!EG(scope)) {
2382            if (error) *error = estrdup("cannot access parent:: when no class scope is active");
2383        } else if (!EG(scope)->parent) {
2384            if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
2385        } else {
2386            fcc->called_scope = EG(called_scope);
2387            fcc->calling_scope = EG(scope)->parent;
2388            if (!fcc->object_ptr) {
2389                fcc->object_ptr = EG(This);
2390            }
2391            *strict_class = 1;
2392            ret = 1;
2393        }
2394    } else if (name_len == sizeof("static") - 1 &&
2395               !memcmp(lcname, "static", sizeof("static") - 1)) {
2396        if (!EG(called_scope)) {
2397            if (error) *error = estrdup("cannot access static:: when no class scope is active");
2398        } else {
2399            fcc->called_scope = EG(called_scope);
2400            fcc->calling_scope = EG(called_scope);
2401            if (!fcc->object_ptr) {
2402                fcc->object_ptr = EG(This);
2403            }
2404            *strict_class = 1;
2405            ret = 1;
2406        }
2407    } else if (zend_lookup_class_ex(name, name_len, 1, &pce TSRMLS_CC) == SUCCESS) {
2408        zend_class_entry *scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
2409
2410        fcc->calling_scope = *pce;
2411        if (scope && !fcc->object_ptr && EG(This) &&
2412            instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
2413            instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) {
2414            fcc->object_ptr = EG(This);
2415            fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
2416        } else {
2417            fcc->called_scope = fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : fcc->calling_scope;
2418        }
2419        *strict_class = 1;
2420        ret = 1;
2421    } else {
2422        if (error) zend_spprintf(error, 0, "class '%.*s' not found", name_len, name);
2423    }
2424    efree(lcname);
2425    return ret;
2426}
2427/* }}} */
2428
2429static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fcall_info_cache *fcc, int strict_class, char **error TSRMLS_DC) /* {{{ */
2430{
2431    zend_class_entry *ce_org = fcc->calling_scope;
2432    int retval = 0;
2433    char *mname, *lmname, *colon;
2434    int clen, mlen;
2435    zend_class_entry *last_scope;
2436    HashTable *ftable;
2437    int call_via_handler = 0;
2438
2439    if (error) {
2440        *error = NULL;
2441    }
2442
2443    fcc->calling_scope = NULL;
2444    fcc->function_handler = NULL;
2445
2446    if (!ce_org) {
2447        /* Skip leading \ */
2448        if (Z_STRVAL_P(callable)[0] == '\\') {
2449            mlen = Z_STRLEN_P(callable) - 1;
2450            lmname = zend_str_tolower_dup(Z_STRVAL_P(callable) + 1, mlen);
2451        } else {
2452            mlen = Z_STRLEN_P(callable);
2453            lmname = zend_str_tolower_dup(Z_STRVAL_P(callable), mlen);
2454        }
2455        /* Check if function with given name exists.
2456         * This may be a compound name that includes namespace name */
2457        if (zend_hash_find(EG(function_table), lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
2458            efree(lmname);
2459            return 1;
2460        }
2461        efree(lmname);
2462    }
2463
2464    /* Split name into class/namespace and method/function names */
2465    if ((colon = zend_memrchr(Z_STRVAL_P(callable), ':', Z_STRLEN_P(callable))) != NULL &&
2466        colon > Z_STRVAL_P(callable) &&
2467        *(colon-1) == ':'
2468    ) {
2469        colon--;
2470        clen = colon - Z_STRVAL_P(callable);
2471        mlen = Z_STRLEN_P(callable) - clen - 2;
2472
2473        if (colon == Z_STRVAL_P(callable)) {
2474            if (error) zend_spprintf(error, 0, "invalid function name");
2475            return 0;
2476        }
2477
2478        /* This is a compound name.
2479         * Try to fetch class and then find static method. */
2480        last_scope = EG(scope);
2481        if (ce_org) {
2482            EG(scope) = ce_org;
2483        }
2484
2485        if (!zend_is_callable_check_class(Z_STRVAL_P(callable), clen, fcc, &strict_class, error TSRMLS_CC)) {
2486            EG(scope) = last_scope;
2487            return 0;
2488        }
2489        EG(scope) = last_scope;
2490
2491        ftable = &fcc->calling_scope->function_table;
2492        if (ce_org && !instanceof_function(ce_org, fcc->calling_scope TSRMLS_CC)) {
2493            if (error) zend_spprintf(error, 0, "class '%s' is not a subclass of '%s'", ce_org->name, fcc->calling_scope->name);
2494            return 0;
2495        }
2496        mname = Z_STRVAL_P(callable) + clen + 2;
2497    } else if (ce_org) {
2498        /* Try to fetch find static method of given class. */
2499        mlen = Z_STRLEN_P(callable);
2500        mname = Z_STRVAL_P(callable);
2501        ftable = &ce_org->function_table;
2502        fcc->calling_scope = ce_org;
2503    } else {
2504        /* We already checked for plain function before. */
2505        if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
2506            zend_spprintf(error, 0, "function '%s' not found or invalid function name", Z_STRVAL_P(callable));
2507        }
2508        return 0;
2509    }
2510
2511    lmname = zend_str_tolower_dup(mname, mlen);
2512    if (strict_class &&
2513        fcc->calling_scope &&
2514        mlen == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1 &&
2515        !memcmp(lmname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
2516        fcc->function_handler = fcc->calling_scope->constructor;
2517        if (fcc->function_handler) {
2518            retval = 1;
2519        }
2520    } else if (zend_hash_find(ftable, lmname, mlen+1, (void**)&fcc->function_handler) == SUCCESS) {
2521        retval = 1;
2522        if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
2523            !strict_class && EG(scope) &&
2524            instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
2525            zend_function *priv_fbc;
2526
2527            if (zend_hash_find(&EG(scope)->function_table, lmname, mlen+1, (void **) &priv_fbc)==SUCCESS
2528                && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
2529                && priv_fbc->common.scope == EG(scope)) {
2530                fcc->function_handler = priv_fbc;
2531            }
2532        }
2533        if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
2534            (fcc->calling_scope &&
2535             (fcc->calling_scope->__call ||
2536              fcc->calling_scope->__callstatic))) {
2537            if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
2538                if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
2539                    retval = 0;
2540                    fcc->function_handler = NULL;
2541                    goto get_function_via_handler;
2542                }
2543            } else if (fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED) {
2544                if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
2545                    retval = 0;
2546                    fcc->function_handler = NULL;
2547                    goto get_function_via_handler;
2548                }
2549            }
2550        }
2551    } else {
2552get_function_via_handler:
2553        if (fcc->object_ptr && fcc->calling_scope == ce_org) {
2554            if (strict_class && ce_org->__call) {
2555                fcc->function_handler = emalloc(sizeof(zend_internal_function));
2556                fcc->function_handler->internal_function.type = ZEND_INTERNAL_FUNCTION;
2557                fcc->function_handler->internal_function.module = ce_org->module;
2558                fcc->function_handler->internal_function.handler = zend_std_call_user_call;
2559                fcc->function_handler->internal_function.arg_info = NULL;
2560                fcc->function_handler->internal_function.num_args = 0;
2561                fcc->function_handler->internal_function.scope = ce_org;
2562                fcc->function_handler->internal_function.fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
2563                fcc->function_handler->internal_function.function_name = estrndup(mname, mlen);
2564                fcc->function_handler->internal_function.pass_rest_by_reference = 0;
2565                fcc->function_handler->internal_function.return_reference = ZEND_RETURN_VALUE;
2566                call_via_handler = 1;
2567                retval = 1;
2568            } else if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
2569                fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, mname, mlen TSRMLS_CC);
2570                if (fcc->function_handler) {
2571                    if (strict_class &&
2572                        (!fcc->function_handler->common.scope ||
2573                         !instanceof_function(ce_org, fcc->function_handler->common.scope TSRMLS_CC))) {
2574                        if ((fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0) {
2575                            if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
2576                                efree(fcc->function_handler->common.function_name);
2577                            }
2578                            efree(fcc->function_handler);
2579                        }
2580                    } else {
2581                        retval = 1;
2582                        call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
2583                    }
2584                }
2585            }
2586        } else if (fcc->calling_scope) {
2587            if (fcc->calling_scope->get_static_method) {
2588                fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
2589            } else {
2590                fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, mname, mlen TSRMLS_CC);
2591            }
2592            if (fcc->function_handler) {
2593                retval = 1;
2594                call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
2595                if (call_via_handler && !fcc->object_ptr && EG(This) &&
2596                    Z_OBJ_HT_P(EG(This))->get_class_entry &&
2597                    instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
2598                    fcc->object_ptr = EG(This);
2599                }
2600            }
2601        }
2602    }
2603
2604    if (retval) {
2605        if (fcc->calling_scope && !call_via_handler) {
2606            if (!fcc->object_ptr && (fcc->function_handler->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2607                if (error) {
2608                    zend_spprintf(error, 0, "cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2609                    retval = 0;
2610                } else {
2611                    zend_error(E_ERROR, "Cannot call abstract method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2612                }
2613            } else if (!fcc->object_ptr && !(fcc->function_handler->common.fn_flags & ZEND_ACC_STATIC)) {
2614                int severity;
2615                char *verb;
2616                if (fcc->function_handler->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2617                    severity = E_STRICT;
2618                    verb = "should not";
2619                } else {
2620                    /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2621                    severity = E_ERROR;
2622                    verb = "cannot";
2623                }
2624                if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
2625                    retval = 0;
2626                }
2627                if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), fcc->calling_scope TSRMLS_CC)) {
2628                    fcc->object_ptr = EG(This);
2629                    if (error) {
2630                        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);
2631                        if (severity == E_ERROR) {
2632                            retval = 0;
2633                        }
2634                    } else if (retval) {
2635                        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);
2636                    }
2637                } else {
2638                    if (error) {
2639                        zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
2640                        if (severity == E_ERROR) {
2641                            retval = 0;
2642                        }
2643                    } else if (retval) {
2644                        zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name, fcc->function_handler->common.function_name, verb);
2645                    }
2646                }
2647            }
2648            if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
2649                if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
2650                    if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, mlen TSRMLS_CC)) {
2651                        if (error) {
2652                            if (*error) {
2653                                efree(*error);
2654                            }
2655                            zend_spprintf(error, 0, "cannot access private method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2656                        }
2657                        retval = 0;
2658                    }
2659                } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
2660                    if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
2661                        if (error) {
2662                            if (*error) {
2663                                efree(*error);
2664                            }
2665                            zend_spprintf(error, 0, "cannot access protected method %s::%s()", fcc->calling_scope->name, fcc->function_handler->common.function_name);
2666                        }
2667                        retval = 0;
2668                    }
2669                }
2670            }
2671        }
2672    } else if (error && !(check_flags & IS_CALLABLE_CHECK_SILENT)) {
2673        if (fcc->calling_scope) {
2674            if (error) zend_spprintf(error, 0, "class '%s' does not have a method '%s'", fcc->calling_scope->name, mname);
2675        } else {
2676            if (error) zend_spprintf(error, 0, "function '%s' does not exist", mname);
2677        }
2678    }
2679    efree(lmname);
2680
2681    if (fcc->object_ptr) {
2682        fcc->called_scope = Z_OBJCE_P(fcc->object_ptr);
2683    }
2684    if (retval) {
2685        fcc->initialized = 1;
2686    }
2687    return retval;
2688}
2689/* }}} */
2690
2691ZEND_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) /* {{{ */
2692{
2693    zend_bool ret;
2694    int callable_name_len_local;
2695    zend_fcall_info_cache fcc_local;
2696
2697    if (callable_name) {
2698        *callable_name = NULL;
2699    }
2700    if (callable_name_len == NULL) {
2701        callable_name_len = &callable_name_len_local;
2702    }
2703    if (fcc == NULL) {
2704        fcc = &fcc_local;
2705    }
2706    if (error) {
2707        *error = NULL;
2708    }
2709
2710    fcc->initialized = 0;
2711    fcc->calling_scope = NULL;
2712    fcc->called_scope = NULL;
2713    fcc->function_handler = NULL;
2714    fcc->calling_scope = NULL;
2715    fcc->object_ptr = NULL;
2716
2717    if (object_ptr && Z_TYPE_P(object_ptr) != IS_OBJECT) {
2718        object_ptr = NULL;
2719    }
2720    if (object_ptr &&
2721        (!EG(objects_store).object_buckets ||
2722         !EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(object_ptr)].valid)) {
2723        return 0;
2724    }
2725
2726    switch (Z_TYPE_P(callable)) {
2727        case IS_STRING:
2728            if (object_ptr) {
2729                fcc->object_ptr = object_ptr;
2730                fcc->calling_scope = Z_OBJCE_P(object_ptr);
2731                if (callable_name) {
2732                    char *ptr;
2733
2734                    *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_P(callable) + sizeof("::") - 1;
2735                    ptr = *callable_name = emalloc(*callable_name_len + 1);
2736                    memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
2737                    ptr += fcc->calling_scope->name_length;
2738                    memcpy(ptr, "::", sizeof("::") - 1);
2739                    ptr += sizeof("::") - 1;
2740                    memcpy(ptr, Z_STRVAL_P(callable), Z_STRLEN_P(callable) + 1);
2741                }
2742            } else if (callable_name) {
2743                *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
2744                *callable_name_len = Z_STRLEN_P(callable);
2745            }
2746            if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
2747                fcc->called_scope = fcc->calling_scope;
2748                return 1;
2749            }
2750
2751            ret = zend_is_callable_check_func(check_flags, callable, fcc, 0, error TSRMLS_CC);
2752            if (fcc == &fcc_local &&
2753                fcc->function_handler &&
2754                ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
2755                  (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
2756                 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
2757                 fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
2758                if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
2759                    efree(fcc->function_handler->common.function_name);
2760                }
2761                efree(fcc->function_handler);
2762            }
2763            return ret;
2764
2765        case IS_ARRAY:
2766            {
2767                zval **method = NULL;
2768                zval **obj = NULL;
2769                int strict_class = 0;
2770
2771                if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
2772                    zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj);
2773                    zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method);
2774                }
2775                if (obj && method &&
2776                    (Z_TYPE_PP(obj) == IS_OBJECT ||
2777                    Z_TYPE_PP(obj) == IS_STRING) &&
2778                    Z_TYPE_PP(method) == IS_STRING) {
2779
2780                    if (Z_TYPE_PP(obj) == IS_STRING) {
2781                        if (callable_name) {
2782                            char *ptr;
2783
2784                            *callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::") - 1;
2785                            ptr = *callable_name = emalloc(*callable_name_len + 1);
2786                            memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
2787                            ptr += Z_STRLEN_PP(obj);
2788                            memcpy(ptr, "::", sizeof("::") - 1);
2789                            ptr += sizeof("::") - 1;
2790                            memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
2791                        }
2792
2793                        if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
2794                            return 1;
2795                        }
2796
2797                        if (!zend_is_callable_check_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), fcc, &strict_class, error TSRMLS_CC)) {
2798                            return 0;
2799                        }
2800
2801                    } else {
2802                        if (!EG(objects_store).object_buckets ||
2803                            !EG(objects_store).object_buckets[Z_OBJ_HANDLE_PP(obj)].valid) {
2804                            return 0;
2805                        }
2806
2807                        fcc->calling_scope = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
2808
2809                        fcc->object_ptr = *obj;
2810
2811                        if (callable_name) {
2812                            char *ptr;
2813
2814                            *callable_name_len = fcc->calling_scope->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
2815                            ptr = *callable_name = emalloc(*callable_name_len + 1);
2816                            memcpy(ptr, fcc->calling_scope->name, fcc->calling_scope->name_length);
2817                            ptr += fcc->calling_scope->name_length;
2818                            memcpy(ptr, "::", sizeof("::") - 1);
2819                            ptr += sizeof("::") - 1;
2820                            memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
2821                        }
2822
2823                        if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
2824                            fcc->called_scope = fcc->calling_scope;
2825                            return 1;
2826                        }
2827                    }
2828
2829                    ret = zend_is_callable_check_func(check_flags, *method, fcc, strict_class, error TSRMLS_CC);
2830                    if (fcc == &fcc_local &&
2831                        fcc->function_handler &&
2832                        ((fcc->function_handler->type == ZEND_INTERNAL_FUNCTION &&
2833                          (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
2834                         fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
2835                         fcc->function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
2836                        if (fcc->function_handler->type != ZEND_OVERLOADED_FUNCTION) {
2837                            efree(fcc->function_handler->common.function_name);
2838                        }
2839                        efree(fcc->function_handler);
2840                    }
2841                    return ret;
2842
2843                } else {
2844                    if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2) {
2845                        if (!obj || (Z_TYPE_PP(obj) != IS_STRING && Z_TYPE_PP(obj) != IS_OBJECT)) {
2846                            if (error) zend_spprintf(error, 0, "first array member is not a valid class name or object");
2847                        } else {
2848                            if (error) zend_spprintf(error, 0, "second array member is not a valid method");
2849                        }
2850                    } else {
2851                        if (error) zend_spprintf(error, 0, "array must have exactly two members");
2852                    }
2853                    if (callable_name) {
2854                        *callable_name = estrndup("Array", sizeof("Array")-1);
2855                        *callable_name_len = sizeof("Array") - 1;
2856                    }
2857                }
2858            }
2859            return 0;
2860
2861        case IS_OBJECT:
2862            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) {
2863                fcc->called_scope = fcc->calling_scope;
2864                if (callable_name) {
2865                    zend_class_entry *ce = Z_OBJCE_P(callable); /* TBFixed: what if it's overloaded? */
2866
2867                    *callable_name_len = ce->name_length + sizeof("::__invoke") - 1;
2868                    *callable_name = emalloc(*callable_name_len + 1);
2869                    memcpy(*callable_name, ce->name, ce->name_length);
2870                    memcpy((*callable_name) + ce->name_length, "::__invoke", sizeof("::__invoke"));
2871                }
2872                return 1;
2873            }
2874            /* break missing intentionally */
2875
2876        default:
2877            if (callable_name) {
2878                zval expr_copy;
2879                int use_copy;
2880
2881                zend_make_printable_zval(callable, &expr_copy, &use_copy);
2882                *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
2883                *callable_name_len = Z_STRLEN(expr_copy);
2884                zval_dtor(&expr_copy);
2885            }
2886            if (error) zend_spprintf(error, 0, "no array or string given");
2887            return 0;
2888    }
2889}
2890/* }}} */
2891
2892ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name TSRMLS_DC) /* {{{ */
2893{
2894    return zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
2895}
2896/* }}} */
2897
2898ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC) /* {{{ */
2899{
2900    zend_fcall_info_cache fcc;
2901
2902    if (zend_is_callable_ex(callable, NULL, IS_CALLABLE_STRICT, callable_name, NULL, &fcc, NULL TSRMLS_CC)) {
2903        if (Z_TYPE_P(callable) == IS_STRING && fcc.calling_scope) {
2904            zval_dtor(callable);
2905            array_init(callable);
2906            add_next_index_string(callable, fcc.calling_scope->name, 1);
2907            add_next_index_string(callable, fcc.function_handler->common.function_name, 1);
2908        }
2909        if (fcc.function_handler &&
2910            ((fcc.function_handler->type == ZEND_INTERNAL_FUNCTION &&
2911              (fcc.function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER)) ||
2912             fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY ||
2913             fcc.function_handler->type == ZEND_OVERLOADED_FUNCTION)) {
2914            if (fcc.function_handler->type != ZEND_OVERLOADED_FUNCTION) {
2915                efree(fcc.function_handler->common.function_name);
2916            }
2917            efree(fcc.function_handler);
2918        }
2919        return 1;
2920    }
2921    return 0;
2922}
2923/* }}} */
2924
2925ZEND_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) /* {{{ */
2926{
2927    if (!zend_is_callable_ex(callable, NULL, check_flags, callable_name, NULL, fcc, error TSRMLS_CC)) {
2928        return FAILURE;
2929    }
2930
2931    fci->size = sizeof(*fci);
2932    fci->function_table = fcc->calling_scope ? &fcc->calling_scope->function_table : EG(function_table);
2933    fci->object_ptr = fcc->object_ptr;
2934    fci->function_name = callable;
2935    fci->retval_ptr_ptr = NULL;
2936    fci->param_count = 0;
2937    fci->params = NULL;
2938    fci->no_separation = 1;
2939    fci->symbol_table = NULL;
2940
2941    return SUCCESS;
2942}
2943/* }}} */
2944
2945ZEND_API void zend_fcall_info_args_clear(zend_fcall_info *fci, int free_mem) /* {{{ */
2946{
2947    if (fci->params) {
2948        if (free_mem) {
2949            efree(fci->params);
2950            fci->params = NULL;
2951        }
2952    }
2953    fci->param_count = 0;
2954}
2955/* }}} */
2956
2957ZEND_API void zend_fcall_info_args_save(zend_fcall_info *fci, int *param_count, zval ****params) /* {{{ */
2958{
2959    *param_count = fci->param_count;
2960    *params = fci->params;
2961    fci->param_count = 0;
2962    fci->params = NULL;
2963}
2964/* }}} */
2965
2966ZEND_API void zend_fcall_info_args_restore(zend_fcall_info *fci, int param_count, zval ***params) /* {{{ */
2967{
2968    zend_fcall_info_args_clear(fci, 1);
2969    fci->param_count = param_count;
2970    fci->params = params;
2971}
2972/* }}} */
2973
2974ZEND_API int zend_fcall_info_args(zend_fcall_info *fci, zval *args TSRMLS_DC) /* {{{ */
2975{
2976    HashPosition pos;
2977    zval **arg, ***params;
2978
2979    zend_fcall_info_args_clear(fci, !args);
2980
2981    if (!args) {
2982        return SUCCESS;
2983    }
2984
2985    if (Z_TYPE_P(args) != IS_ARRAY) {
2986        return FAILURE;
2987    }
2988
2989    fci->param_count = zend_hash_num_elements(Z_ARRVAL_P(args));
2990    fci->params = params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
2991
2992    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
2993    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void *) &arg, &pos) == SUCCESS) {
2994        *params++ = arg;
2995        zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos);
2996    }
2997
2998    return SUCCESS;
2999}
3000/* }}} */
3001
3002ZEND_API int zend_fcall_info_argp(zend_fcall_info *fci TSRMLS_DC, int argc, zval ***argv) /* {{{ */
3003{
3004    int i;
3005
3006    if (argc < 0) {
3007        return FAILURE;
3008    }
3009
3010    zend_fcall_info_args_clear(fci, !argc);
3011
3012    if (argc) {
3013        fci->param_count = argc;
3014        fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
3015
3016        for (i = 0; i < argc; ++i) {
3017            fci->params[i] = argv[i];
3018        }
3019    }
3020
3021    return SUCCESS;
3022}
3023/* }}} */
3024
3025ZEND_API int zend_fcall_info_argv(zend_fcall_info *fci TSRMLS_DC, int argc, va_list *argv) /* {{{ */
3026{
3027    int i;
3028    zval **arg;
3029
3030    if (argc < 0) {
3031        return FAILURE;
3032    }
3033
3034    zend_fcall_info_args_clear(fci, !argc);
3035
3036    if (argc) {
3037        fci->param_count = argc;
3038        fci->params = (zval ***) erealloc(fci->params, fci->param_count * sizeof(zval **));
3039
3040        for (i = 0; i < argc; ++i) {
3041            arg = va_arg(*argv, zval **);
3042            fci->params[i] = arg;
3043        }
3044    }
3045
3046    return SUCCESS;
3047}
3048/* }}} */
3049
3050ZEND_API int zend_fcall_info_argn(zend_fcall_info *fci TSRMLS_DC, int argc, ...) /* {{{ */
3051{
3052    int ret;
3053    va_list argv;
3054
3055    va_start(argv, argc);
3056    ret = zend_fcall_info_argv(fci TSRMLS_CC, argc, &argv);
3057    va_end(argv);
3058
3059    return ret;
3060}
3061/* }}} */
3062
3063ZEND_API int zend_fcall_info_call(zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval **retval_ptr_ptr, zval *args TSRMLS_DC) /* {{{ */
3064{
3065    zval *retval, ***org_params = NULL;
3066    int result, org_count = 0;
3067
3068    fci->retval_ptr_ptr = retval_ptr_ptr ? retval_ptr_ptr : &retval;
3069    if (args) {
3070        zend_fcall_info_args_save(fci, &org_count, &org_params);
3071        zend_fcall_info_args(fci, args TSRMLS_CC);
3072    }
3073    result = zend_call_function(fci, fcc TSRMLS_CC);
3074
3075    if (!retval_ptr_ptr && retval) {
3076        zval_ptr_dtor(&retval);
3077    }
3078    if (args) {
3079        zend_fcall_info_args_restore(fci, org_count, org_params);
3080    }
3081    return result;
3082}
3083/* }}} */
3084
3085ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */
3086{
3087    char *lname;
3088    int name_len = strlen(module_name);
3089    zend_module_entry *module;
3090
3091    lname = zend_str_tolower_dup(module_name, name_len);
3092    if (zend_hash_find(&module_registry, lname, name_len + 1, (void**)&module) == FAILURE) {
3093        efree(lname);
3094        return NULL;
3095    }
3096    efree(lname);
3097    return module->version;
3098}
3099/* }}} */
3100
3101ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC) /* {{{ */
3102{
3103    zend_property_info property_info;
3104    HashTable *target_symbol_table;
3105
3106    if (!(access_type & ZEND_ACC_PPP_MASK)) {
3107        access_type |= ZEND_ACC_PUBLIC;
3108    }
3109    if (access_type & ZEND_ACC_STATIC) {
3110        target_symbol_table = &ce->default_static_members;
3111    } else {
3112        target_symbol_table = &ce->default_properties;
3113    }
3114    if (ce->type & ZEND_INTERNAL_CLASS) {
3115        switch(Z_TYPE_P(property)) {
3116            case IS_ARRAY:
3117            case IS_CONSTANT_ARRAY:
3118            case IS_OBJECT:
3119            case IS_RESOURCE:
3120                zend_error(E_CORE_ERROR, "Internal zval's can't be arrays, objects or resources");
3121                break;
3122            default:
3123                break;
3124        }
3125    }
3126    switch (access_type & ZEND_ACC_PPP_MASK) {
3127        case ZEND_ACC_PRIVATE: {
3128                char *priv_name;
3129                int priv_name_length;
3130
3131                zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3132                zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
3133                property_info.name = priv_name;
3134                property_info.name_length = priv_name_length;
3135            }
3136            break;
3137        case ZEND_ACC_PROTECTED: {
3138                char *prot_name;
3139                int prot_name_length;
3140
3141                zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3142                zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
3143                property_info.name = prot_name;
3144                property_info.name_length = prot_name_length;
3145            }
3146            break;
3147        case ZEND_ACC_PUBLIC:
3148            if (ce->parent) {
3149                char *prot_name;
3150                int prot_name_length;
3151
3152                zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
3153                zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
3154                pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
3155            }
3156            zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
3157            property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
3158            property_info.name_length = name_length;
3159            break;
3160    }
3161    property_info.flags = access_type;
3162    property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
3163
3164    property_info.doc_comment = doc_comment;
3165    property_info.doc_comment_len = doc_comment_len;
3166
3167    property_info.ce = ce;
3168
3169    zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
3170
3171    return SUCCESS;
3172}
3173/* }}} */
3174
3175ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC) /* {{{ */
3176{
3177    return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
3178}
3179/* }}} */
3180
3181ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC) /* {{{ */
3182{
3183    zval *property;
3184
3185    if (ce->type & ZEND_INTERNAL_CLASS) {
3186        ALLOC_PERMANENT_ZVAL(property);
3187    } else {
3188        ALLOC_ZVAL(property);
3189    }
3190    INIT_ZVAL(*property);
3191    return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3192}
3193/* }}} */
3194
3195ZEND_API int zend_declare_property_bool(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
3196{
3197    zval *property;
3198
3199    if (ce->type & ZEND_INTERNAL_CLASS) {
3200        ALLOC_PERMANENT_ZVAL(property);
3201    } else {
3202        ALLOC_ZVAL(property);
3203    }
3204    INIT_PZVAL(property);
3205    ZVAL_BOOL(property, value);
3206    return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3207}
3208/* }}} */
3209
3210ZEND_API int zend_declare_property_long(zend_class_entry *ce, char *name, int name_length, long value, int access_type TSRMLS_DC) /* {{{ */
3211{
3212    zval *property;
3213
3214    if (ce->type & ZEND_INTERNAL_CLASS) {
3215        ALLOC_PERMANENT_ZVAL(property);
3216    } else {
3217        ALLOC_ZVAL(property);
3218    }
3219    INIT_PZVAL(property);
3220    ZVAL_LONG(property, value);
3221    return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3222}
3223/* }}} */
3224
3225ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int name_length, double value, int access_type TSRMLS_DC) /* {{{ */
3226{
3227    zval *property;
3228
3229    if (ce->type & ZEND_INTERNAL_CLASS) {
3230        ALLOC_PERMANENT_ZVAL(property);
3231    } else {
3232        ALLOC_ZVAL(property);
3233    }
3234    INIT_PZVAL(property);
3235    ZVAL_DOUBLE(property, value);
3236    return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3237}
3238/* }}} */
3239
3240ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC) /* {{{ */
3241{
3242    zval *property;
3243    int len = strlen(value);
3244
3245    if (ce->type & ZEND_INTERNAL_CLASS) {
3246        ALLOC_PERMANENT_ZVAL(property);
3247        ZVAL_STRINGL(property, zend_strndup(value, len), len, 0);
3248    } else {
3249        ALLOC_ZVAL(property);
3250        ZVAL_STRINGL(property, value, len, 1);
3251    }
3252    INIT_PZVAL(property);
3253    return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3254}
3255/* }}} */
3256
3257ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC) /* {{{ */
3258{
3259    zval *property;
3260
3261    if (ce->type & ZEND_INTERNAL_CLASS) {
3262        ALLOC_PERMANENT_ZVAL(property);
3263        ZVAL_STRINGL(property, zend_strndup(value, value_len), value_len, 0);
3264    } else {
3265        ALLOC_ZVAL(property);
3266        ZVAL_STRINGL(property, value, value_len, 1);
3267    }
3268    INIT_PZVAL(property);
3269    return zend_declare_property(ce, name, name_length, property, access_type TSRMLS_CC);
3270}
3271/* }}} */
3272
3273ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value TSRMLS_DC) /* {{{ */
3274{
3275    return zend_hash_update(&ce->constants_table, name, name_length+1, &value, sizeof(zval *), NULL);
3276}
3277/* }}} */
3278
3279ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length TSRMLS_DC) /* {{{ */
3280{
3281    zval *constant;
3282
3283    if (ce->type & ZEND_INTERNAL_CLASS) {
3284        ALLOC_PERMANENT_ZVAL(constant);
3285    } else {
3286        ALLOC_ZVAL(constant);
3287    }
3288    ZVAL_NULL(constant);
3289    INIT_PZVAL(constant);
3290    return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3291}
3292/* }}} */
3293
3294ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, long value TSRMLS_DC) /* {{{ */
3295{
3296    zval *constant;
3297
3298    if (ce->type & ZEND_INTERNAL_CLASS) {
3299        ALLOC_PERMANENT_ZVAL(constant);
3300    } else {
3301        ALLOC_ZVAL(constant);
3302    }
3303    ZVAL_LONG(constant, value);
3304    INIT_PZVAL(constant);
3305    return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3306}
3307/* }}} */
3308
3309ZEND_API int zend_declare_class_constant_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_bool value TSRMLS_DC) /* {{{ */
3310{
3311    zval *constant;
3312
3313    if (ce->type & ZEND_INTERNAL_CLASS) {
3314        ALLOC_PERMANENT_ZVAL(constant);
3315    } else {
3316        ALLOC_ZVAL(constant);
3317    }
3318    ZVAL_BOOL(constant, value);
3319    INIT_PZVAL(constant);
3320    return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3321}
3322/* }}} */
3323
3324ZEND_API int zend_declare_class_constant_double(zend_class_entry *ce, const char *name, size_t name_length, double value TSRMLS_DC) /* {{{ */
3325{
3326    zval *constant;
3327
3328    if (ce->type & ZEND_INTERNAL_CLASS) {
3329        ALLOC_PERMANENT_ZVAL(constant);
3330    } else {
3331        ALLOC_ZVAL(constant);
3332    }
3333    ZVAL_DOUBLE(constant, value);
3334    INIT_PZVAL(constant);
3335    return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3336}
3337/* }}} */
3338
3339ZEND_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) /* {{{ */
3340{
3341    zval *constant;
3342
3343    if (ce->type & ZEND_INTERNAL_CLASS) {
3344        ALLOC_PERMANENT_ZVAL(constant);
3345        ZVAL_STRINGL(constant, zend_strndup(value, value_length), value_length, 0);
3346    } else {
3347        ALLOC_ZVAL(constant);
3348        ZVAL_STRINGL(constant, value, value_length, 1);
3349    }
3350    INIT_PZVAL(constant);
3351    return zend_declare_class_constant(ce, name, name_length, constant TSRMLS_CC);
3352}
3353/* }}} */
3354
3355ZEND_API int zend_declare_class_constant_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value TSRMLS_DC) /* {{{ */
3356{
3357    return zend_declare_class_constant_stringl(ce, name, name_length, value, strlen(value) TSRMLS_CC);
3358}
3359/* }}} */
3360
3361ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
3362{
3363    zval *property;
3364    zend_class_entry *old_scope = EG(scope);
3365
3366    EG(scope) = scope;
3367
3368    if (!Z_OBJ_HT_P(object)->write_property) {
3369        char *class_name;
3370        zend_uint class_name_len;
3371
3372        zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
3373
3374        zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name);
3375    }
3376    MAKE_STD_ZVAL(property);
3377    ZVAL_STRINGL(property, name, name_length, 1);
3378    Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
3379    zval_ptr_dtor(&property);
3380
3381    EG(scope) = old_scope;
3382}
3383/* }}} */
3384
3385ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC) /* {{{ */
3386{
3387    zval *tmp;
3388
3389    ALLOC_ZVAL(tmp);
3390    Z_UNSET_ISREF_P(tmp);
3391    Z_SET_REFCOUNT_P(tmp, 0);
3392    ZVAL_NULL(tmp);
3393    zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3394}
3395/* }}} */
3396
3397ZEND_API void zend_update_property_bool(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3398{
3399    zval *tmp;
3400
3401    ALLOC_ZVAL(tmp);
3402    Z_UNSET_ISREF_P(tmp);
3403    Z_SET_REFCOUNT_P(tmp, 0);
3404    ZVAL_BOOL(tmp, value);
3405    zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3406}
3407/* }}} */
3408
3409ZEND_API void zend_update_property_long(zend_class_entry *scope, zval *object, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3410{
3411    zval *tmp;
3412
3413    ALLOC_ZVAL(tmp);
3414    Z_UNSET_ISREF_P(tmp);
3415    Z_SET_REFCOUNT_P(tmp, 0);
3416    ZVAL_LONG(tmp, value);
3417    zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3418}
3419/* }}} */
3420
3421ZEND_API void zend_update_property_double(zend_class_entry *scope, zval *object, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
3422{
3423    zval *tmp;
3424
3425    ALLOC_ZVAL(tmp);
3426    Z_UNSET_ISREF_P(tmp);
3427    Z_SET_REFCOUNT_P(tmp, 0);
3428    ZVAL_DOUBLE(tmp, value);
3429    zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3430}
3431/* }}} */
3432
3433ZEND_API void zend_update_property_string(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
3434{
3435    zval *tmp;
3436
3437    ALLOC_ZVAL(tmp);
3438    Z_UNSET_ISREF_P(tmp);
3439    Z_SET_REFCOUNT_P(tmp, 0);
3440    ZVAL_STRING(tmp, value, 1);
3441    zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3442}
3443/* }}} */
3444
3445ZEND_API void zend_update_property_stringl(zend_class_entry *scope, zval *object, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
3446{
3447    zval *tmp;
3448
3449    ALLOC_ZVAL(tmp);
3450    Z_UNSET_ISREF_P(tmp);
3451    Z_SET_REFCOUNT_P(tmp, 0);
3452    ZVAL_STRINGL(tmp, value, value_len, 1);
3453    zend_update_property(scope, object, name, name_length, tmp TSRMLS_CC);
3454}
3455/* }}} */
3456
3457ZEND_API int zend_update_static_property(zend_class_entry *scope, char *name, int name_length, zval *value TSRMLS_DC) /* {{{ */
3458{
3459    zval **property;
3460    zend_class_entry *old_scope = EG(scope);
3461
3462    EG(scope) = scope;
3463    property = zend_std_get_static_property(scope, name, name_length, 0 TSRMLS_CC);
3464    EG(scope) = old_scope;
3465    if (!property) {
3466        return FAILURE;
3467    } else {
3468        if (*property != value) {
3469            if (PZVAL_IS_REF(*property)) {
3470                zval_dtor(*property);
3471                Z_TYPE_PP(property) = Z_TYPE_P(value);
3472                (*property)->value = value->value;
3473                if (Z_REFCOUNT_P(value) > 0) {
3474                    zval_copy_ctor(*property);
3475                } else {
3476                    efree(value);
3477                }
3478            } else {
3479                zval *garbage = *property;
3480
3481                Z_ADDREF_P(value);
3482                if (PZVAL_IS_REF(value)) {
3483                    SEPARATE_ZVAL(&value);
3484                }
3485                *property = value;
3486                zval_ptr_dtor(&garbage);
3487            }
3488        }
3489        return SUCCESS;
3490    }
3491}
3492/* }}} */
3493
3494ZEND_API int zend_update_static_property_null(zend_class_entry *scope, char *name, int name_length TSRMLS_DC) /* {{{ */
3495{
3496    zval *tmp;
3497
3498    ALLOC_ZVAL(tmp);
3499    Z_UNSET_ISREF_P(tmp);
3500    Z_SET_REFCOUNT_P(tmp, 0);
3501    ZVAL_NULL(tmp);
3502    return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3503}
3504/* }}} */
3505
3506ZEND_API int zend_update_static_property_bool(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3507{
3508    zval *tmp;
3509
3510    ALLOC_ZVAL(tmp);
3511    Z_UNSET_ISREF_P(tmp);
3512    Z_SET_REFCOUNT_P(tmp, 0);
3513    ZVAL_BOOL(tmp, value);
3514    return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3515}
3516/* }}} */
3517
3518ZEND_API int zend_update_static_property_long(zend_class_entry *scope, char *name, int name_length, long value TSRMLS_DC) /* {{{ */
3519{
3520    zval *tmp;
3521
3522    ALLOC_ZVAL(tmp);
3523    Z_UNSET_ISREF_P(tmp);
3524    Z_SET_REFCOUNT_P(tmp, 0);
3525    ZVAL_LONG(tmp, value);
3526    return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3527}
3528/* }}} */
3529
3530ZEND_API int zend_update_static_property_double(zend_class_entry *scope, char *name, int name_length, double value TSRMLS_DC) /* {{{ */
3531{
3532    zval *tmp;
3533
3534    ALLOC_ZVAL(tmp);
3535    Z_UNSET_ISREF_P(tmp);
3536    Z_SET_REFCOUNT_P(tmp, 0);
3537    ZVAL_DOUBLE(tmp, value);
3538    return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3539}
3540/* }}} */
3541
3542ZEND_API int zend_update_static_property_string(zend_class_entry *scope, char *name, int name_length, const char *value TSRMLS_DC) /* {{{ */
3543{
3544    zval *tmp;
3545
3546    ALLOC_ZVAL(tmp);
3547    Z_UNSET_ISREF_P(tmp);
3548    Z_SET_REFCOUNT_P(tmp, 0);
3549    ZVAL_STRING(tmp, value, 1);
3550    return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3551}
3552/* }}} */
3553
3554ZEND_API int zend_update_static_property_stringl(zend_class_entry *scope, char *name, int name_length, const char *value, int value_len TSRMLS_DC) /* {{{ */
3555{
3556    zval *tmp;
3557
3558    ALLOC_ZVAL(tmp);
3559    Z_UNSET_ISREF_P(tmp);
3560    Z_SET_REFCOUNT_P(tmp, 0);
3561    ZVAL_STRINGL(tmp, value, value_len, 1);
3562    return zend_update_static_property(scope, name, name_length, tmp TSRMLS_CC);
3563}
3564/* }}} */
3565
3566ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3567{
3568    zval *property, *value;
3569    zend_class_entry *old_scope = EG(scope);
3570
3571    EG(scope) = scope;
3572
3573    if (!Z_OBJ_HT_P(object)->read_property) {
3574        char *class_name;
3575        zend_uint class_name_len;
3576
3577        zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
3578        zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name);
3579    }
3580
3581    MAKE_STD_ZVAL(property);
3582    ZVAL_STRINGL(property, name, name_length, 1);
3583    value = Z_OBJ_HT_P(object)->read_property(object, property, silent?BP_VAR_IS:BP_VAR_R TSRMLS_CC);
3584    zval_ptr_dtor(&property);
3585
3586    EG(scope) = old_scope;
3587    return value;
3588}
3589/* }}} */
3590
3591ZEND_API zval *zend_read_static_property(zend_class_entry *scope, char *name, int name_length, zend_bool silent TSRMLS_DC) /* {{{ */
3592{
3593    zval **property;
3594    zend_class_entry *old_scope = EG(scope);
3595
3596    EG(scope) = scope;
3597    property = zend_std_get_static_property(scope, name, name_length, silent TSRMLS_CC);
3598    EG(scope) = old_scope;
3599
3600    return property?*property:NULL;
3601}
3602/* }}} */
3603
3604ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */
3605{
3606    current->handling = EG(error_handling);
3607    current->exception = EG(exception_class);
3608    current->user_handler = EG(user_error_handler);
3609    if (current->user_handler) {
3610        Z_ADDREF_P(current->user_handler);
3611    }
3612}
3613/* }}} */
3614
3615ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */
3616{
3617    if (current) {
3618        zend_save_error_handling(current TSRMLS_CC);
3619        if (error_handling != EH_NORMAL && EG(user_error_handler)) {
3620            zval_ptr_dtor(&EG(user_error_handler));
3621            EG(user_error_handler) = NULL;
3622        }
3623    }
3624    EG(error_handling) = error_handling;
3625    EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL;
3626}
3627/* }}} */
3628
3629ZEND_API void zend_restore_error_handling(zend_error_handling *saved TSRMLS_DC) /* {{{ */
3630{
3631    EG(error_handling) = saved->handling;
3632    EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL;
3633    if (saved->user_handler && saved->user_handler != EG(user_error_handler)) {
3634        if (EG(user_error_handler)) {
3635            zval_ptr_dtor(&EG(user_error_handler));
3636        }
3637        EG(user_error_handler) = saved->user_handler;
3638    } else if (saved->user_handler) {
3639        zval_ptr_dtor(&saved->user_handler);
3640    }
3641    saved->user_handler = NULL;
3642}
3643/* }}} */
3644
3645/*
3646 * Local variables:
3647 * tab-width: 4
3648 * c-basic-offset: 4
3649 * indent-tabs-mode: t
3650 * End:
3651 */
3652