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