Annotation of embedaddon/php/Zend/zend_compile.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | Zend Engine                                                          |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1998-2012 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:    +----------------------------------------------------------------------+
                     18: */
                     19: 
1.1.1.2 ! misho      20: /* $Id$ */
1.1       misho      21: 
                     22: #include <zend_language_parser.h>
                     23: #include "zend.h"
                     24: #include "zend_compile.h"
                     25: #include "zend_constants.h"
                     26: #include "zend_llist.h"
                     27: #include "zend_API.h"
                     28: #include "zend_exceptions.h"
                     29: #include "tsrm_virtual_cwd.h"
                     30: #include "zend_multibyte.h"
1.1.1.2 ! misho      31: #include "zend_language_scanner.h"
        !            32: 
        !            33: #define CONSTANT_EX(op_array, op) \
        !            34:        (op_array)->literals[op].constant
        !            35: 
        !            36: #define CONSTANT(op) \
        !            37:        CONSTANT_EX(CG(active_op_array), op)
        !            38: 
        !            39: #define SET_NODE(target, src) do { \
        !            40:                target ## _type = (src)->op_type; \
        !            41:                if ((src)->op_type == IS_CONST) { \
        !            42:                        target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant TSRMLS_CC); \
        !            43:                } else { \
        !            44:                        target = (src)->u.op; \
        !            45:                } \
        !            46:        } while (0)
        !            47: 
        !            48: #define GET_NODE(target, src) do { \
        !            49:                (target)->op_type = src ## _type; \
        !            50:                if ((target)->op_type == IS_CONST) { \
        !            51:                        (target)->u.constant = CONSTANT(src.constant); \
        !            52:                } else { \
        !            53:                        (target)->u.op = src; \
        !            54:                        (target)->EA = 0; \
        !            55:                } \
        !            56:        } while (0)
        !            57: 
        !            58: #define COPY_NODE(target, src) do { \
        !            59:                target ## _type = src ## _type; \
        !            60:                target = src; \
        !            61:        } while (0)
        !            62: 
        !            63: #define CALCULATE_LITERAL_HASH(num) do { \
        !            64:                if (IS_INTERNED(Z_STRVAL(CONSTANT(num)))) { \
        !            65:                        Z_HASH_P(&CONSTANT(num)) = INTERNED_HASH(Z_STRVAL(CONSTANT(num))); \
        !            66:                } else { \
        !            67:                        Z_HASH_P(&CONSTANT(num)) = zend_hash_func(Z_STRVAL(CONSTANT(num)), Z_STRLEN(CONSTANT(num))+1); \
        !            68:                } \
        !            69:        } while (0)
        !            70: 
        !            71: #define GET_CACHE_SLOT(literal) do { \
        !            72:                CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
        !            73:                if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
        !            74:                        CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
        !            75:                        CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
        !            76:                } \
        !            77:        } while (0)
        !            78: 
        !            79: #define POLYMORPHIC_CACHE_SLOT_SIZE 2
        !            80: 
        !            81: #define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
        !            82:                CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
        !            83:                CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
        !            84:                if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
        !            85:                        CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
        !            86:                        CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
        !            87:                        CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 2] = NULL; \
        !            88:                } \
        !            89:        } while (0)
        !            90: 
        !            91: #define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
        !            92:                if (CG(active_op_array)->literals[literal].cache_slot != -1 && \
        !            93:                    CG(active_op_array)->literals[literal].cache_slot == \
        !            94:                    CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
        !            95:                        CG(active_op_array)->literals[literal].cache_slot = -1; \
        !            96:                        CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
        !            97:                } \
        !            98:        } while (0)
1.1       misho      99: 
                    100: ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
                    101: ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
                    102: 
                    103: #ifndef ZTS
                    104: ZEND_API zend_compiler_globals compiler_globals;
                    105: ZEND_API zend_executor_globals executor_globals;
                    106: #endif
                    107: 
                    108: static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
                    109: {
1.1.1.2 ! misho     110:        if (!IS_INTERNED(property_info->name)) {                
        !           111:                property_info->name = estrndup(property_info->name, property_info->name_length);
        !           112:        }
1.1       misho     113:        if (property_info->doc_comment) {
                    114:                property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
                    115:        }
                    116: }
                    117: /* }}} */
                    118: 
                    119: static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
                    120: {
1.1.1.2 ! misho     121:        if (!IS_INTERNED(property_info->name)) {                
        !           122:                property_info->name = zend_strndup(property_info->name, property_info->name_length);
        !           123:        }
1.1       misho     124: }
                    125: /* }}} */
                    126: 
                    127: static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
                    128: {
1.1.1.2 ! misho     129:        str_efree(property_info->name);
1.1       misho     130:        if (property_info->doc_comment) {
1.1.1.2 ! misho     131:                efree((char*)property_info->doc_comment);
1.1       misho     132:        }
                    133: }
                    134: /* }}} */
                    135: 
                    136: static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
                    137: {
1.1.1.2 ! misho     138:        str_free((char*)property_info->name);
1.1       misho     139: }
                    140: /* }}} */
                    141: 
                    142: static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
                    143: {
                    144:        char char_pos_buf[32];
                    145:        uint char_pos_len;
1.1.1.2 ! misho     146:        const char *filename;
1.1       misho     147: 
                    148:        char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
                    149:        if (CG(active_op_array)->filename) {
                    150:                filename = CG(active_op_array)->filename;
                    151:        } else {
                    152:                filename = "-";
                    153:        }
                    154: 
                    155:        /* NULL, name length, filename length, last accepting char position length */
                    156:        result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
1.1.1.2 ! misho     157: 
1.1       misho     158:        /* must be binary safe */
                    159:        result->value.str.val = (char *) safe_emalloc(result->value.str.len, 1, 1);
                    160:        result->value.str.val[0] = '\0';
                    161:        sprintf(result->value.str.val+1, "%s%s%s", name, filename, char_pos_buf);
1.1.1.2 ! misho     162: 
1.1       misho     163:        result->type = IS_STRING;
                    164:        Z_SET_REFCOUNT_P(result, 1);
                    165: }
                    166: /* }}} */
                    167: 
                    168: static void init_compiler_declarables(TSRMLS_D) /* {{{ */
                    169: {
                    170:        Z_TYPE(CG(declarables).ticks) = IS_LONG;
                    171:        Z_LVAL(CG(declarables).ticks) = 0;
                    172: }
                    173: /* }}} */
                    174: 
1.1.1.2 ! misho     175: void zend_init_compiler_context(TSRMLS_D) /* {{{ */
        !           176: {
        !           177:        CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
        !           178:        CG(context).vars_size = 0;
        !           179:        CG(context).literals_size = 0;
        !           180:        CG(context).current_brk_cont = -1;
        !           181:        CG(context).backpatch_count = 0;
        !           182:        CG(context).labels = NULL;
        !           183: }
        !           184: /* }}} */
1.1       misho     185: 
                    186: void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
                    187: {
                    188:        zend_stack_init(&CG(bp_stack));
                    189:        zend_stack_init(&CG(function_call_stack));
                    190:        zend_stack_init(&CG(switch_cond_stack));
                    191:        zend_stack_init(&CG(foreach_copy_stack));
                    192:        zend_stack_init(&CG(object_stack));
                    193:        zend_stack_init(&CG(declare_stack));
                    194:        CG(active_class_entry) = NULL;
                    195:        zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
                    196:        zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
                    197:        zend_stack_init(&CG(list_stack));
                    198:        CG(in_compilation) = 0;
                    199:        CG(start_lineno) = 0;
                    200:        CG(current_namespace) = NULL;
                    201:        CG(in_namespace) = 0;
                    202:        CG(has_bracketed_namespaces) = 0;
                    203:        CG(current_import) = NULL;
                    204:        init_compiler_declarables(TSRMLS_C);
1.1.1.2 ! misho     205:        zend_stack_init(&CG(context_stack));
        !           206: 
1.1       misho     207:        CG(encoding_declared) = 0;
                    208: }
                    209: /* }}} */
                    210: 
                    211: ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
                    212: {
                    213:        TSRMLS_FETCH();
                    214: 
                    215:        zend_file_handle_dtor(fh TSRMLS_CC);
                    216: }
                    217: /* }}} */
                    218: 
                    219: void init_compiler(TSRMLS_D) /* {{{ */
                    220: {
                    221:        CG(active_op_array) = NULL;
                    222:        zend_init_compiler_data_structures(TSRMLS_C);
                    223:        zend_init_rsrc_list(TSRMLS_C);
                    224:        zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
                    225:        zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
                    226:        CG(unclean_shutdown) = 0;
                    227: }
                    228: /* }}} */
                    229: 
                    230: void shutdown_compiler(TSRMLS_D) /* {{{ */
                    231: {
                    232:        zend_stack_destroy(&CG(bp_stack));
                    233:        zend_stack_destroy(&CG(function_call_stack));
                    234:        zend_stack_destroy(&CG(switch_cond_stack));
                    235:        zend_stack_destroy(&CG(foreach_copy_stack));
                    236:        zend_stack_destroy(&CG(object_stack));
                    237:        zend_stack_destroy(&CG(declare_stack));
                    238:        zend_stack_destroy(&CG(list_stack));
                    239:        zend_hash_destroy(&CG(filenames_table));
                    240:        zend_llist_destroy(&CG(open_files));
1.1.1.2 ! misho     241:        zend_stack_destroy(&CG(context_stack));
1.1       misho     242: }
                    243: /* }}} */
                    244: 
                    245: ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
                    246: {
                    247:        char **pp, *p;
                    248:        int length = strlen(new_compiled_filename);
                    249: 
                    250:        if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
                    251:                CG(compiled_filename) = *pp;
                    252:                return *pp;
                    253:        }
                    254:        p = estrndup(new_compiled_filename, length);
                    255:        zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
                    256:        CG(compiled_filename) = p;
                    257:        return p;
                    258: }
                    259: /* }}} */
                    260: 
                    261: ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
                    262: {
                    263:        CG(compiled_filename) = original_compiled_filename;
                    264: }
                    265: /* }}} */
                    266: 
                    267: ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
                    268: {
                    269:        return CG(compiled_filename);
                    270: }
                    271: /* }}} */
                    272: 
                    273: ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
                    274: {
                    275:        return CG(zend_lineno);
                    276: }
                    277: /* }}} */
                    278: 
                    279: ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
                    280: {
                    281:        return CG(in_compilation);
                    282: }
                    283: /* }}} */
                    284: 
                    285: static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
                    286: {
                    287:        return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
                    288: }
                    289: /* }}} */
                    290: 
1.1.1.2 ! misho     291: static int lookup_cv(zend_op_array *op_array, char* name, int name_len, ulong hash TSRMLS_DC) /* {{{ */
1.1       misho     292: {
                    293:        int i = 0;
1.1.1.2 ! misho     294:        ulong hash_value = hash ? hash : zend_inline_hash_func(name, name_len+1);
1.1       misho     295: 
                    296:        while (i < op_array->last_var) {
1.1.1.2 ! misho     297:                if (op_array->vars[i].name == name ||
        !           298:                    (op_array->vars[i].hash_value == hash_value &&
        !           299:                     op_array->vars[i].name_len == name_len &&
        !           300:                     memcmp(op_array->vars[i].name, name, name_len) == 0)) {
        !           301:                        str_efree(name);
        !           302:                        return i;
1.1       misho     303:                }
                    304:                i++;
                    305:        }
                    306:        i = op_array->last_var;
                    307:        op_array->last_var++;
1.1.1.2 ! misho     308:        if (op_array->last_var > CG(context).vars_size) {
        !           309:                CG(context).vars_size += 16; /* FIXME */
        !           310:                op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_compiled_variable));
1.1       misho     311:        }
1.1.1.2 ! misho     312:        op_array->vars[i].name = zend_new_interned_string(name, name_len + 1, 1 TSRMLS_CC);
1.1       misho     313:        op_array->vars[i].name_len = name_len;
                    314:        op_array->vars[i].hash_value = hash_value;
                    315:        return i;
                    316: }
                    317: /* }}} */
                    318: 
1.1.1.2 ! misho     319: void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
        !           320: {
        !           321:        zval_dtor(&CONSTANT_EX(op_array, n));
        !           322:        if (n + 1 == op_array->last_literal) {
        !           323:                op_array->last_literal--;
        !           324:        } else {
        !           325:                Z_TYPE(CONSTANT_EX(op_array, n)) = IS_NULL;
        !           326:        }
        !           327: }
        !           328: /* }}} */
        !           329: 
        !           330: /* Common part of zend_add_literal and zend_append_individual_literal */
        !           331: static inline void zend_insert_literal(zend_op_array *op_array, const zval *zv, int literal_position TSRMLS_DC) /* {{{ */
        !           332: {
        !           333:        if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
        !           334:                zval *z = (zval*)zv;
        !           335:                Z_STRVAL_P(z) = (char*)zend_new_interned_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC);
        !           336:        }
        !           337:        CONSTANT_EX(op_array, literal_position) = *zv;
        !           338:        Z_SET_REFCOUNT(CONSTANT_EX(op_array, literal_position), 2);
        !           339:        Z_SET_ISREF(CONSTANT_EX(op_array, literal_position));
        !           340:        op_array->literals[literal_position].hash_value = 0;
        !           341:        op_array->literals[literal_position].cache_slot = -1;
        !           342: }
        !           343: /* }}} */
        !           344: 
        !           345: /* Is used while compiling a function, using the context to keep track
        !           346:    of an approximate size to avoid to relocate to often.
        !           347:    Literals are truncated to actual size in the second compiler pass (pass_two()). */
        !           348: int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
        !           349: {
        !           350:        int i = op_array->last_literal;
        !           351:        op_array->last_literal++;
        !           352:        if (i >= CG(context).literals_size) {
        !           353:                while (i >= CG(context).literals_size) {
        !           354:                        CG(context).literals_size += 16; /* FIXME */
        !           355:                }
        !           356:                op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
        !           357:        }
        !           358:        zend_insert_literal(op_array, zv, i TSRMLS_CC);
        !           359:        return i;
        !           360: }
        !           361: /* }}} */
        !           362: 
        !           363: /* Is used after normal compilation to append an additional literal.
        !           364:    Allocation is done precisely here. */
        !           365: int zend_append_individual_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
        !           366: {
        !           367:        int i = op_array->last_literal;
        !           368:        op_array->last_literal++;
        !           369:        op_array->literals = (zend_literal*)erealloc(op_array->literals, (i + 1) * sizeof(zend_literal));
        !           370:        zend_insert_literal(op_array, zv, i TSRMLS_CC);
        !           371:        return i;
        !           372: }
        !           373: /* }}} */
        !           374: 
        !           375: int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
        !           376: {
        !           377:        int ret;
        !           378:        char *lc_name;
        !           379:        zval c;
        !           380:        int lc_literal;
        !           381: 
        !           382:        if (op_array->last_literal > 0 && 
        !           383:            &op_array->literals[op_array->last_literal - 1].constant == zv &&
        !           384:            op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
        !           385:                /* we already have function name as last literal (do nothing) */
        !           386:                ret = op_array->last_literal - 1;
        !           387:        } else {
        !           388:                ret = zend_add_literal(op_array, zv TSRMLS_CC);
        !           389:        }
        !           390:        
        !           391:        lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
        !           392:        ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
        !           393:        lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           394:        CALCULATE_LITERAL_HASH(lc_literal);
        !           395: 
        !           396:        return ret;
        !           397: }
        !           398: /* }}} */
        !           399: 
        !           400: int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
        !           401: {
        !           402:        int ret;
        !           403:        char *lc_name;
        !           404:        const char *ns_separator;
        !           405:        int lc_len;
        !           406:        zval c;
        !           407:        int lc_literal;
        !           408: 
        !           409:        if (op_array->last_literal > 0 && 
        !           410:            &op_array->literals[op_array->last_literal - 1].constant == zv &&
        !           411:            op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
        !           412:                /* we already have function name as last literal (do nothing) */
        !           413:                ret = op_array->last_literal - 1;
        !           414:        } else {
        !           415:                ret = zend_add_literal(op_array, zv TSRMLS_CC);
        !           416:        }
        !           417: 
        !           418:        lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
        !           419:        ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
        !           420:        lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           421:        CALCULATE_LITERAL_HASH(lc_literal);
        !           422: 
        !           423:        ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv)) + 1;
        !           424:        lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
        !           425:        lc_name = zend_str_tolower_dup(ns_separator, lc_len);
        !           426:        ZVAL_STRINGL(&c, lc_name, lc_len, 0);
        !           427:        lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           428:        CALCULATE_LITERAL_HASH(lc_literal);
        !           429: 
        !           430:        return ret;
        !           431: }
        !           432: /* }}} */
        !           433: 
        !           434: int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
        !           435: {
        !           436:        int ret;
        !           437:        char *lc_name;
        !           438:        int lc_len;
        !           439:        zval c;
        !           440:        int lc_literal;
        !           441: 
        !           442:        if (op_array->last_literal > 0 && 
        !           443:            &op_array->literals[op_array->last_literal - 1].constant == zv &&
        !           444:            op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
        !           445:                /* we already have function name as last literal (do nothing) */
        !           446:                ret = op_array->last_literal - 1;
        !           447:        } else {
        !           448:                ret = zend_add_literal(op_array, zv TSRMLS_CC);
        !           449:        }
        !           450: 
        !           451:        if (Z_STRVAL_P(zv)[0] == '\\') {
        !           452:                lc_len = Z_STRLEN_P(zv) - 1;
        !           453:                lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv) + 1, lc_len);
        !           454:        } else {
        !           455:                lc_len = Z_STRLEN_P(zv);
        !           456:                lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), lc_len);
        !           457:        }
        !           458:        ZVAL_STRINGL(&c, lc_name, lc_len, 0);
        !           459:        lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           460:        CALCULATE_LITERAL_HASH(lc_literal);
        !           461: 
        !           462:        GET_CACHE_SLOT(ret);
        !           463: 
        !           464:        return ret;
        !           465: }
        !           466: /* }}} */
        !           467: 
        !           468: int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unqualified TSRMLS_DC) /* {{{ */
        !           469: {
        !           470:        int ret, tmp_literal;
        !           471:        char *name, *tmp_name;
        !           472:        const char *ns_separator;
        !           473:        int name_len, ns_len;
        !           474:        zval c;
        !           475: 
        !           476:        if (op_array->last_literal > 0 && 
        !           477:            &op_array->literals[op_array->last_literal - 1].constant == zv &&
        !           478:            op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
        !           479:                /* we already have function name as last literal (do nothing) */
        !           480:                ret = op_array->last_literal - 1;
        !           481:        } else {
        !           482:                ret = zend_add_literal(op_array, zv TSRMLS_CC);
        !           483:        }
        !           484: 
        !           485:        /* skip leading '\\' */ 
        !           486:        if (Z_STRVAL_P(zv)[0] == '\\') {
        !           487:                name_len = Z_STRLEN_P(zv) - 1;
        !           488:                name = Z_STRVAL_P(zv) + 1;
        !           489:        } else {
        !           490:                name_len = Z_STRLEN_P(zv);
        !           491:                name = Z_STRVAL_P(zv);
        !           492:        }
        !           493:        ns_separator = zend_memrchr(name, '\\', name_len);
        !           494:        if (ns_separator) {
        !           495:                ns_len = ns_separator - name;
        !           496:        } else {
        !           497:                ns_len = 0;
        !           498:        }
        !           499: 
        !           500:        if (ns_len) {
        !           501:                /* lowercased namespace name & original constant name */
        !           502:                tmp_name = estrndup(name, name_len);
        !           503:                zend_str_tolower(tmp_name, ns_len);
        !           504:                ZVAL_STRINGL(&c, tmp_name, name_len, 0);
        !           505:                tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           506:                CALCULATE_LITERAL_HASH(tmp_literal);
        !           507: 
        !           508:                /* lowercased namespace name & lowercased constant name */
        !           509:                tmp_name = zend_str_tolower_dup(name, name_len);
        !           510:                ZVAL_STRINGL(&c, tmp_name, name_len, 0);
        !           511:                tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           512:                CALCULATE_LITERAL_HASH(tmp_literal);
        !           513:        }
        !           514: 
        !           515:        if (ns_len) {
        !           516:                if (!unqualified) {
        !           517:                        return ret;
        !           518:                }
        !           519:                ns_len++;
        !           520:                name += ns_len;
        !           521:                name_len -= ns_len;
        !           522:        }
        !           523: 
        !           524:        /* original constant name */
        !           525:        tmp_name = estrndup(name, name_len);
        !           526:        ZVAL_STRINGL(&c, tmp_name, name_len, 0);
        !           527:        tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           528:        CALCULATE_LITERAL_HASH(tmp_literal);
        !           529: 
        !           530:        /* lowercased constant name */
        !           531:        tmp_name = zend_str_tolower_dup(name, name_len);
        !           532:        ZVAL_STRINGL(&c, tmp_name, name_len, 0);
        !           533:        tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
        !           534:        CALCULATE_LITERAL_HASH(tmp_literal);
        !           535: 
        !           536:        return ret;
        !           537: }
        !           538: /* }}} */
        !           539: 
        !           540: #define LITERAL_STRINGL(op, str, len, copy) do { \
        !           541:                zval _c; \
        !           542:                ZVAL_STRINGL(&_c, str, len, copy); \
        !           543:                op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
        !           544:        } while (0)
        !           545: 
        !           546: #define LITERAL_LONG(op, val) do { \
        !           547:                zval _c; \
        !           548:                ZVAL_LONG(&_c, val); \
        !           549:                op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
        !           550:        } while (0)
        !           551: 
        !           552: #define LITERAL_LONG_EX(op_array, op, val) do { \
        !           553:                zval _c; \
        !           554:                ZVAL_LONG(&_c, val); \
        !           555:                op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
        !           556:        } while (0)
        !           557: 
        !           558: #define LITERAL_NULL(op) do { \
        !           559:                zval _c; \
        !           560:                INIT_ZVAL(      _c); \
        !           561:                op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
        !           562:        } while (0)
        !           563: 
        !           564: static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
        !           565: {
        !           566:        zend_uint type = variable->EA;
        !           567: 
        !           568:        return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
        !           569: }
        !           570: /* }}} */
1.1       misho     571: 
                    572: void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
                    573: {
                    574:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    575: 
                    576:        opline->opcode = op;
1.1.1.2 ! misho     577:        opline->result_type = IS_TMP_VAR;
        !           578:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !           579:        SET_NODE(opline->op1, op1);
        !           580:        SET_NODE(opline->op2, op2);
        !           581:        GET_NODE(result, opline->result);
1.1       misho     582: }
                    583: /* }}} */
                    584: 
                    585: void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
                    586: {
                    587:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    588: 
                    589:        opline->opcode = op;
1.1.1.2 ! misho     590:        opline->result_type = IS_TMP_VAR;
        !           591:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !           592:        SET_NODE(opline->op1, op1);
        !           593:        GET_NODE(result, opline->result);
1.1       misho     594:        SET_UNUSED(opline->op2);
                    595: }
                    596: /* }}} */
                    597: 
1.1.1.2 ! misho     598: #define MAKE_NOP(opline)       { opline->opcode = ZEND_NOP;  memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED;  }
1.1       misho     599: 
                    600: static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
                    601: {
                    602:        data_op->opcode = ZEND_OP_DATA;
1.1.1.2 ! misho     603:        SET_NODE(data_op->op1, value);
1.1       misho     604:        SET_UNUSED(data_op->op2);
                    605: }
                    606: /* }}} */
                    607: 
                    608: void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
                    609: {
                    610:        int last_op_number = get_next_op_number(CG(active_op_array));
                    611:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    612: 
                    613:        if (last_op_number > 0) {
                    614:                zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
                    615: 
                    616:                switch (last_op->opcode) {
                    617:                        case ZEND_FETCH_OBJ_RW:
                    618:                                last_op->opcode = op;
                    619:                                last_op->extended_value = ZEND_ASSIGN_OBJ;
                    620: 
                    621:                                zend_do_op_data(opline, op2 TSRMLS_CC);
                    622:                                SET_UNUSED(opline->result);
1.1.1.2 ! misho     623:                                GET_NODE(result, last_op->result);
1.1       misho     624:                                return;
                    625:                        case ZEND_FETCH_DIM_RW:
                    626:                                last_op->opcode = op;
                    627:                                last_op->extended_value = ZEND_ASSIGN_DIM;
                    628: 
                    629:                                zend_do_op_data(opline, op2 TSRMLS_CC);
1.1.1.2 ! misho     630:                                opline->op2.var = get_temporary_variable(CG(active_op_array));
        !           631:                                opline->op2_type = IS_VAR;
1.1       misho     632:                                SET_UNUSED(opline->result);
1.1.1.2 ! misho     633:                                GET_NODE(result,last_op->result);
1.1       misho     634:                                return;
                    635:                        default:
                    636:                                break;
                    637:                }
                    638:        }
                    639: 
                    640:        opline->opcode = op;
1.1.1.2 ! misho     641:        SET_NODE(opline->op1, op1);
        !           642:        SET_NODE(opline->op2, op2);
        !           643:        opline->result_type = IS_VAR;
        !           644:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !           645:        GET_NODE(result, opline->result);
1.1       misho     646: }
                    647: /* }}} */
                    648: 
                    649: void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
                    650: {
                    651:        zend_op opline;
                    652:        zend_op *opline_ptr;
                    653:        zend_llist *fetch_list_ptr;
                    654: 
                    655:        if (varname->op_type == IS_CONST) {
1.1.1.2 ! misho     656:                ulong hash = 0;
        !           657: 
1.1       misho     658:                if (Z_TYPE(varname->u.constant) != IS_STRING) {
                    659:                        convert_to_string(&varname->u.constant);
1.1.1.2 ! misho     660:                } else if (IS_INTERNED(Z_STRVAL(varname->u.constant))) {
        !           661:                        hash = INTERNED_HASH(Z_STRVAL(varname->u.constant));
1.1       misho     662:                }
1.1.1.2 ! misho     663:                if (!zend_is_auto_global_quick(varname->u.constant.value.str.val, varname->u.constant.value.str.len, hash TSRMLS_CC) &&
1.1       misho     664:                    !(varname->u.constant.value.str.len == (sizeof("this")-1) &&
                    665:                      !memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
                    666:                    (CG(active_op_array)->last == 0 ||
                    667:                     CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
                    668:                        result->op_type = IS_CV;
1.1.1.2 ! misho     669:                        result->u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len, hash TSRMLS_CC);
        !           670:                        varname->u.constant.value.str.val = (char*)CG(active_op_array)->vars[result->u.op.var].name;
        !           671:                        result->EA = 0;
1.1       misho     672:                        return;
                    673:                }
                    674:        }
                    675: 
                    676:        if (bp) {
                    677:                opline_ptr = &opline;
                    678:                init_op(opline_ptr TSRMLS_CC);
                    679:        } else {
                    680:                opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
                    681:        }
                    682: 
                    683:        opline_ptr->opcode = op;
1.1.1.2 ! misho     684:        opline_ptr->result_type = IS_VAR;
        !           685:        opline_ptr->result.var = get_temporary_variable(CG(active_op_array));
        !           686:        SET_NODE(opline_ptr->op1, varname);
        !           687:        GET_NODE(result, opline_ptr->result);
1.1       misho     688:        SET_UNUSED(opline_ptr->op2);
1.1.1.2 ! misho     689:        opline_ptr->extended_value = ZEND_FETCH_LOCAL;
1.1       misho     690: 
1.1.1.2 ! misho     691:        if (varname->op_type == IS_CONST) {
        !           692:                CALCULATE_LITERAL_HASH(opline_ptr->op1.constant);
        !           693:                if (zend_is_auto_global_quick(varname->u.constant.value.str.val, varname->u.constant.value.str.len, Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC)) {
        !           694:                        opline_ptr->extended_value = ZEND_FETCH_GLOBAL;
1.1       misho     695:                }
                    696:        }
                    697: 
                    698:        if (bp) {
                    699:                zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
                    700:                zend_llist_add_element(fetch_list_ptr, opline_ptr);
                    701:        }
                    702: }
                    703: /* }}} */
                    704: 
                    705: void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
                    706: {
                    707:        /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
                    708:        fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
                    709: }
                    710: /* }}} */
                    711: 
                    712: void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
                    713: {
                    714:        znode class_node;
                    715:        zend_llist *fetch_list_ptr;
                    716:        zend_llist_element *le;
                    717:        zend_op *opline_ptr;
                    718:        zend_op opline;
                    719: 
1.1.1.2 ! misho     720:        if (class_name->op_type == IS_CONST &&
        !           721:            ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
        !           722:                zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
        !           723:                class_node = *class_name;
        !           724:        } else {
        !           725:                zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
        !           726:        }
1.1       misho     727:        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
                    728:        if (result->op_type == IS_CV) {
                    729:                init_op(&opline TSRMLS_CC);
                    730: 
                    731:                opline.opcode = ZEND_FETCH_W;
1.1.1.2 ! misho     732:                opline.result_type = IS_VAR;
        !           733:                opline.result.var = get_temporary_variable(CG(active_op_array));
        !           734:                opline.op1_type = IS_CONST;
        !           735:                LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
        !           736:                CALCULATE_LITERAL_HASH(opline.op1.constant);
        !           737:                GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
        !           738:                if (class_node.op_type == IS_CONST) {
        !           739:                        opline.op2_type = IS_CONST;
        !           740:                        opline.op2.constant =
        !           741:                                zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
        !           742:                } else {
        !           743:                        SET_NODE(opline.op2, &class_node);
        !           744:                }
        !           745:                GET_NODE(result,opline.result);
        !           746:                opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
        !           747:                opline_ptr = &opline;
1.1       misho     748: 
                    749:                zend_llist_add_element(fetch_list_ptr, &opline);
                    750:        } else {
                    751:                le = fetch_list_ptr->head;
                    752: 
                    753:                opline_ptr = (zend_op *)le->data;
1.1.1.2 ! misho     754:                if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
1.1       misho     755:                        init_op(&opline TSRMLS_CC);
                    756:                        opline.opcode = ZEND_FETCH_W;
1.1.1.2 ! misho     757:                        opline.result_type = IS_VAR;
        !           758:                        opline.result.var = get_temporary_variable(CG(active_op_array));
        !           759:                        opline.op1_type = IS_CONST;
        !           760:                        LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
        !           761:                        CALCULATE_LITERAL_HASH(opline.op1.constant);
        !           762:                        GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
        !           763:                        if (class_node.op_type == IS_CONST) {
        !           764:                                opline.op2_type = IS_CONST;
        !           765:                                opline.op2.constant =
        !           766:                                        zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
        !           767:                        } else {
        !           768:                                SET_NODE(opline.op2, &class_node);
        !           769:                        }
        !           770:                        opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
        !           771:                        COPY_NODE(opline_ptr->op1, opline.result);
1.1       misho     772: 
                    773:                        zend_llist_prepend_element(fetch_list_ptr, &opline);
                    774:                } else {
1.1.1.2 ! misho     775:                        if (opline_ptr->op1_type == IS_CONST) {
        !           776:                                GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
        !           777:                        }
        !           778:                        if (class_node.op_type == IS_CONST) {
        !           779:                                opline_ptr->op2_type = IS_CONST;
        !           780:                                opline_ptr->op2.constant =
        !           781:                                        zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
        !           782:                        } else {
        !           783:                                SET_NODE(opline_ptr->op2, &class_node);
        !           784:                        }
        !           785:                        opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
1.1       misho     786:                }
                    787:        }
                    788: }
                    789: /* }}} */
                    790: 
                    791: void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
                    792: {
                    793:        fetch_simple_variable(result, varname, 1 TSRMLS_CC);
                    794: 
                    795:        fetch_array_dim(result, result, first_dim TSRMLS_CC);
                    796: }
                    797: /* }}} */
                    798: 
                    799: void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
                    800: {
                    801:        zend_op opline;
                    802:        zend_llist *fetch_list_ptr;
                    803: 
1.1.1.2 ! misho     804:        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
        !           805: 
        !           806:        if (zend_is_function_or_method_call(parent)) {
        !           807:                init_op(&opline TSRMLS_CC);
        !           808:                opline.opcode = ZEND_SEPARATE;
        !           809:                SET_NODE(opline.op1, parent);
        !           810:                SET_UNUSED(opline.op2);
        !           811:                opline.result_type = IS_VAR;
        !           812:                opline.result.var = opline.op1.var;
        !           813:                zend_llist_add_element(fetch_list_ptr, &opline);
        !           814:        }
        !           815:        
1.1       misho     816:        init_op(&opline TSRMLS_CC);
                    817:        opline.opcode = ZEND_FETCH_DIM_W;       /* the backpatching routine assumes W */
1.1.1.2 ! misho     818:        opline.result_type = IS_VAR;
        !           819:        opline.result.var = get_temporary_variable(CG(active_op_array));
        !           820:        SET_NODE(opline.op1, parent);
        !           821:        SET_NODE(opline.op2, dim);
        !           822:        if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
        !           823:                ulong index;
        !           824:                int numeric = 0;
        !           825: 
        !           826:                ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline.op2.constant)), Z_STRLEN(CONSTANT(opline.op2.constant))+1, index, numeric = 1);
        !           827:                if (numeric) {
        !           828:                        zval_dtor(&CONSTANT(opline.op2.constant));
        !           829:                        ZVAL_LONG(&CONSTANT(opline.op2.constant), index); 
        !           830:                } else {
        !           831:                        CALCULATE_LITERAL_HASH(opline.op2.constant);
        !           832:                }
        !           833:        }
        !           834:        
        !           835:        GET_NODE(result, opline.result);
1.1       misho     836: 
                    837:        zend_llist_add_element(fetch_list_ptr, &opline);
                    838: }
                    839: /* }}} */
                    840: 
                    841: void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
                    842: {
                    843:        fetch_array_dim(result, parent, offset TSRMLS_CC);
                    844: }
                    845: /* }}} */
                    846: 
                    847: void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
                    848: {
                    849:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    850: 
1.1.1.2 ! misho     851:        opline->result_type = IS_TMP_VAR;
        !           852:        opline->result.var = get_temporary_variable(CG(active_op_array));
1.1       misho     853:        opline->opcode = ZEND_PRINT;
1.1.1.2 ! misho     854:        SET_NODE(opline->op1, arg);
1.1       misho     855:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho     856:        GET_NODE(result, opline->result);
1.1       misho     857: }
                    858: /* }}} */
                    859: 
                    860: void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
                    861: {
                    862:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    863: 
                    864:        opline->opcode = ZEND_ECHO;
1.1.1.2 ! misho     865:        SET_NODE(opline->op1, arg);
1.1       misho     866:        SET_UNUSED(opline->op2);
                    867: }
                    868: /* }}} */
                    869: 
                    870: void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
                    871: {
                    872:        char *method_type;
                    873: 
                    874:        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
                    875:                Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
                    876:                method_type = "Interface";
                    877:        } else {
                    878:                method_type = "Abstract";
                    879:        }
                    880: 
                    881:        if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
                    882:                if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) {
                    883:                        zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val);
                    884:                }
                    885:                if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
                    886:                        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    887: 
                    888:                        opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
                    889:                        SET_UNUSED(opline->op1);
                    890:                        SET_UNUSED(opline->op2);
                    891:                } else {
                    892:                        /* we had code in the function body */
                    893:                        zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val);
                    894:                }
                    895:        } else {
                    896:                if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) {
                    897:                        zend_error(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
                    898:                }
                    899:        }
                    900: }
                    901: /* }}} */
                    902: 
                    903: static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
                    904: {
1.1.1.2 ! misho     905:        if ((opline->opcode == ZEND_FETCH_W) && (opline->op1_type == IS_CONST)
        !           906:                && (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING)
        !           907:                && (Z_HASH_P(&CONSTANT(opline->op1.constant)) == THIS_HASHVAL)
        !           908:                && (Z_STRLEN(CONSTANT(opline->op1.constant)) == (sizeof("this")-1))
        !           909:                && !memcmp(Z_STRVAL(CONSTANT(opline->op1.constant)), "this", sizeof("this"))) {
1.1       misho     910:                return 1;
                    911:        } else {
                    912:                return 0;
                    913:        }
                    914: }
                    915: /* }}} */
                    916: 
1.1.1.2 ! misho     917: void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {{{ */
1.1       misho     918: {
                    919:        int last_op_number;
                    920:        zend_op *opline;
                    921: 
                    922:        if (value->op_type == IS_CV) {
                    923:                zend_llist *fetch_list_ptr;
                    924: 
                    925:                zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
                    926:                if (fetch_list_ptr && fetch_list_ptr->head) {
                    927:                        opline = (zend_op *)fetch_list_ptr->head->data;
                    928: 
                    929:                        if (opline->opcode == ZEND_FETCH_DIM_W &&
1.1.1.2 ! misho     930:                            opline->op1_type == IS_CV &&
        !           931:                            opline->op1.var == value->u.op.var) {
1.1       misho     932: 
                    933:                                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    934:                                opline->opcode = ZEND_FETCH_R;
1.1.1.2 ! misho     935:                                opline->result_type = IS_VAR;
        !           936:                                opline->result.var = get_temporary_variable(CG(active_op_array));
        !           937:                                opline->op1_type = IS_CONST;
        !           938:                                LITERAL_STRINGL(opline->op1,
        !           939:                                        CG(active_op_array)->vars[value->u.op.var].name, 
        !           940:                                        CG(active_op_array)->vars[value->u.op.var].name_len, 1);
        !           941:                                CALCULATE_LITERAL_HASH(opline->op1.constant);
1.1       misho     942:                                SET_UNUSED(opline->op2);
1.1.1.2 ! misho     943:                                opline->extended_value = ZEND_FETCH_LOCAL;
        !           944:                                GET_NODE(value, opline->result);
1.1       misho     945:                        }
                    946:                }
                    947:        }
                    948: 
                    949:        zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
                    950: 
                    951:        last_op_number = get_next_op_number(CG(active_op_array));
                    952:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    953: 
                    954:        if (variable->op_type == IS_CV) {
1.1.1.2 ! misho     955:                if (variable->u.op.var == CG(active_op_array)->this_var) {
1.1       misho     956:                        zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
                    957:                }
                    958:        } else if (variable->op_type == IS_VAR) {
                    959:                int n = 0;
                    960: 
                    961:                while (last_op_number - n > 0) {
                    962:                        zend_op *last_op;
                    963: 
                    964:                        last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
                    965: 
1.1.1.2 ! misho     966:                        if (last_op->result_type == IS_VAR &&
        !           967:                            last_op->result.var == variable->u.op.var) {
1.1       misho     968:                                if (last_op->opcode == ZEND_FETCH_OBJ_W) {
                    969:                                        if (n > 0) {
                    970:                                                int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
                    971:                                                *opline = *last_op;
                    972:                                                MAKE_NOP(last_op);
                    973:                                                /* last_op = opline; */
                    974:                                                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    975:                                                /* get_next_op can realloc, we need to move last_op */
                    976:                                                last_op = &CG(active_op_array)->opcodes[opline_no];
                    977:                                        }
                    978:                                        last_op->opcode = ZEND_ASSIGN_OBJ;
                    979:                                        zend_do_op_data(opline, value TSRMLS_CC);
                    980:                                        SET_UNUSED(opline->result);
1.1.1.2 ! misho     981:                                        GET_NODE(result, last_op->result);
1.1       misho     982:                                        return;
                    983:                                } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
                    984:                                        if (n > 0) {
                    985:                                                int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
                    986:                                                *opline = *last_op;
                    987:                                                MAKE_NOP(last_op);
                    988:                                                /* last_op = opline; */
                    989:                                                /* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
                    990:                                                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                    991:                                                /* get_next_op can realloc, we need to move last_op */
                    992:                                                last_op = &CG(active_op_array)->opcodes[opline_no];
                    993:                                        }
                    994:                                        last_op->opcode = ZEND_ASSIGN_DIM;
                    995:                                        zend_do_op_data(opline, value TSRMLS_CC);
1.1.1.2 ! misho     996:                                        opline->op2.var = get_temporary_variable(CG(active_op_array));
        !           997:                                        opline->op2_type = IS_VAR;
1.1       misho     998:                                        SET_UNUSED(opline->result);
1.1.1.2 ! misho     999:                                        GET_NODE(result, last_op->result);
1.1       misho    1000:                                        return;
                   1001:                                } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
                   1002:                                        zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
                   1003:                                } else {
                   1004:                                        break;
                   1005:                                }
                   1006:                        }
                   1007:                        n++;
                   1008:                }
                   1009:        }
                   1010: 
                   1011:        opline->opcode = ZEND_ASSIGN;
1.1.1.2 ! misho    1012:        SET_NODE(opline->op1, variable);
        !          1013:        SET_NODE(opline->op2, value);
        !          1014:        opline->result_type = IS_VAR;
        !          1015:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          1016:        GET_NODE(result, opline->result);
1.1       misho    1017: }
                   1018: /* }}} */
                   1019: 
                   1020: void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
                   1021: {
                   1022:        zend_op *opline;
                   1023: 
                   1024:        if (lvar->op_type == IS_CV) {
1.1.1.2 ! misho    1025:                if (lvar->u.op.var == CG(active_op_array)->this_var) {
1.1       misho    1026:                        zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
                   1027:                }
                   1028:        } else if (lvar->op_type == IS_VAR) {
                   1029:                int last_op_number = get_next_op_number(CG(active_op_array));
                   1030: 
                   1031:                if (last_op_number > 0) {
                   1032:                        opline = &CG(active_op_array)->opcodes[last_op_number-1];
                   1033:                        if (opline_is_fetch_this(opline TSRMLS_CC)) {
                   1034:                                zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
                   1035:                        }
                   1036:                }
                   1037:        }
                   1038: 
                   1039:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1040:        opline->opcode = ZEND_ASSIGN_REF;
                   1041:        if (zend_is_function_or_method_call(rvar)) {
                   1042:                opline->extended_value = ZEND_RETURNS_FUNCTION;
1.1.1.2 ! misho    1043:        } else if (rvar->EA & ZEND_PARSED_NEW) {
1.1       misho    1044:                opline->extended_value = ZEND_RETURNS_NEW;
                   1045:        } else {
                   1046:                opline->extended_value = 0;
                   1047:        }
                   1048:        if (result) {
1.1.1.2 ! misho    1049:                opline->result_type = IS_VAR;
        !          1050:                opline->result.var = get_temporary_variable(CG(active_op_array));
        !          1051:                GET_NODE(result, opline->result);
1.1       misho    1052:        } else {
1.1.1.2 ! misho    1053:                opline->result_type = IS_UNUSED | EXT_TYPE_UNUSED;
1.1       misho    1054:        }
1.1.1.2 ! misho    1055:        SET_NODE(opline->op1, lvar);
        !          1056:        SET_NODE(opline->op2, rvar);
1.1       misho    1057: }
                   1058: /* }}} */
                   1059: 
                   1060: static inline void do_begin_loop(TSRMLS_D) /* {{{ */
                   1061: {
                   1062:        zend_brk_cont_element *brk_cont_element;
                   1063:        int parent;
                   1064: 
1.1.1.2 ! misho    1065:        parent = CG(context).current_brk_cont;
        !          1066:        CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
1.1       misho    1067:        brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
                   1068:        brk_cont_element->start = get_next_op_number(CG(active_op_array));
                   1069:        brk_cont_element->parent = parent;
                   1070: }
                   1071: /* }}} */
                   1072: 
                   1073: static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
                   1074: {
                   1075:        if (!has_loop_var) {
                   1076:                /* The start fileld is used to free temporary variables in case of exceptions.
                   1077:                 * We won't try to free something of we don't have loop variable.
                   1078:                 */
1.1.1.2 ! misho    1079:                CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
1.1       misho    1080:        }
1.1.1.2 ! misho    1081:        CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
        !          1082:        CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
        !          1083:        CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
1.1       misho    1084: }
                   1085: /* }}} */
                   1086: 
                   1087: void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
                   1088: {
                   1089:        int while_cond_op_number = get_next_op_number(CG(active_op_array));
                   1090:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1091: 
                   1092:        opline->opcode = ZEND_JMPZ;
1.1.1.2 ! misho    1093:        SET_NODE(opline->op1, expr);
        !          1094:        close_bracket_token->u.op.opline_num = while_cond_op_number;
1.1       misho    1095:        SET_UNUSED(opline->op2);
                   1096: 
                   1097:        do_begin_loop(TSRMLS_C);
                   1098:        INC_BPC(CG(active_op_array));
                   1099: }
                   1100: /* }}} */
                   1101: 
                   1102: void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
                   1103: {
                   1104:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1105: 
                   1106:        /* add unconditional jump */
                   1107:        opline->opcode = ZEND_JMP;
1.1.1.2 ! misho    1108:        opline->op1.opline_num = while_token->u.op.opline_num;
1.1       misho    1109:        SET_UNUSED(opline->op1);
                   1110:        SET_UNUSED(opline->op2);
                   1111: 
                   1112:        /* update while's conditional jmp */
1.1.1.2 ! misho    1113:        CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    1114: 
1.1.1.2 ! misho    1115:        do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
1.1       misho    1116: 
                   1117:        DEC_BPC(CG(active_op_array));
                   1118: }
                   1119: /* }}} */
                   1120: 
                   1121: void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
                   1122: {
                   1123:        int for_cond_op_number = get_next_op_number(CG(active_op_array));
                   1124:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1125: 
                   1126:        opline->opcode = ZEND_JMPZNZ;
1.1.1.2 ! misho    1127:        SET_NODE(opline->op1, expr);  /* the conditional expression */
        !          1128:        second_semicolon_token->u.op.opline_num = for_cond_op_number;
1.1       misho    1129:        SET_UNUSED(opline->op2);
                   1130: }
                   1131: /* }}} */
                   1132: 
                   1133: void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
                   1134: {
                   1135:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1136: 
                   1137:        opline->opcode = ZEND_JMP;
1.1.1.2 ! misho    1138:        opline->op1.opline_num = cond_start->u.op.opline_num;
        !          1139:        CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1.1       misho    1140:        SET_UNUSED(opline->op1);
                   1141:        SET_UNUSED(opline->op2);
                   1142: 
                   1143:        do_begin_loop(TSRMLS_C);
                   1144: 
                   1145:        INC_BPC(CG(active_op_array));
                   1146: }
                   1147: /* }}} */
                   1148: 
                   1149: void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
                   1150: {
                   1151:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1152: 
                   1153:        opline->opcode = ZEND_JMP;
1.1.1.2 ! misho    1154:        opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
        !          1155:        CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    1156:        SET_UNUSED(opline->op1);
                   1157:        SET_UNUSED(opline->op2);
                   1158: 
1.1.1.2 ! misho    1159:        do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
1.1       misho    1160: 
                   1161:        DEC_BPC(CG(active_op_array));
                   1162: }
                   1163: /* }}} */
                   1164: 
                   1165: void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
                   1166: {
                   1167:        int last_op_number = get_next_op_number(CG(active_op_array));
                   1168:        zend_op *opline;
                   1169: 
                   1170:        if (last_op_number > 0) {
                   1171:                zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
                   1172: 
                   1173:                if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
                   1174:                        last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
1.1.1.2 ! misho    1175:                        last_op->result_type = IS_VAR;
        !          1176:                        last_op->result.var = get_temporary_variable(CG(active_op_array));
        !          1177:                        GET_NODE(result, last_op->result);
1.1       misho    1178:                        return;
                   1179:                }
                   1180:        }
                   1181: 
                   1182:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1183:        opline->opcode = op;
1.1.1.2 ! misho    1184:        SET_NODE(opline->op1, op1);
1.1       misho    1185:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    1186:        opline->result_type = IS_VAR;
        !          1187:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          1188:        GET_NODE(result, opline->result);
1.1       misho    1189: }
                   1190: /* }}} */
                   1191: 
                   1192: void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
                   1193: {
                   1194:        int last_op_number = get_next_op_number(CG(active_op_array));
                   1195:        zend_op *opline;
                   1196: 
                   1197:        if (last_op_number > 0) {
                   1198:                zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
                   1199: 
                   1200:                if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
                   1201:                        last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
1.1.1.2 ! misho    1202:                        last_op->result_type = IS_TMP_VAR;
        !          1203:                        last_op->result.var = get_temporary_variable(CG(active_op_array));
        !          1204:                        GET_NODE(result, last_op->result);
1.1       misho    1205:                        return;
                   1206:                }
                   1207:        }
                   1208: 
                   1209:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1210:        opline->opcode = op;
1.1.1.2 ! misho    1211:        SET_NODE(opline->op1, op1);
1.1       misho    1212:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    1213:        opline->result_type = IS_TMP_VAR;
        !          1214:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          1215:        GET_NODE(result, opline->result);
1.1       misho    1216: }
                   1217: /* }}} */
                   1218: 
                   1219: void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
                   1220: {
                   1221:        int if_cond_op_number = get_next_op_number(CG(active_op_array));
                   1222:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1223: 
                   1224:        opline->opcode = ZEND_JMPZ;
1.1.1.2 ! misho    1225:        SET_NODE(opline->op1, cond);
        !          1226:        closing_bracket_token->u.op.opline_num = if_cond_op_number;
1.1       misho    1227:        SET_UNUSED(opline->op2);
                   1228:        INC_BPC(CG(active_op_array));
                   1229: }
                   1230: /* }}} */
                   1231: 
                   1232: void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
                   1233: {
                   1234:        int if_end_op_number = get_next_op_number(CG(active_op_array));
                   1235:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1236:        zend_llist *jmp_list_ptr;
                   1237: 
                   1238:        opline->opcode = ZEND_JMP;
                   1239:        /* save for backpatching */
                   1240:        if (initialize) {
                   1241:                zend_llist jmp_list;
                   1242: 
                   1243:                zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
                   1244:                zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
                   1245:        }
                   1246:        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
                   1247:        zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
                   1248: 
1.1.1.2 ! misho    1249:        CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
1.1       misho    1250:        SET_UNUSED(opline->op1);
                   1251:        SET_UNUSED(opline->op2);
                   1252: }
                   1253: /* }}} */
                   1254: 
                   1255: void zend_do_if_end(TSRMLS_D) /* {{{ */
                   1256: {
                   1257:        int next_op_number = get_next_op_number(CG(active_op_array));
                   1258:        zend_llist *jmp_list_ptr;
                   1259:        zend_llist_element *le;
                   1260: 
                   1261:        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
                   1262:        for (le=jmp_list_ptr->head; le; le = le->next) {
1.1.1.2 ! misho    1263:                CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
1.1       misho    1264:        }
                   1265:        zend_llist_destroy(jmp_list_ptr);
                   1266:        zend_stack_del_top(&CG(bp_stack));
                   1267:        DEC_BPC(CG(active_op_array));
                   1268: }
                   1269: /* }}} */
                   1270: 
                   1271: void zend_check_writable_variable(const znode *variable) /* {{{ */
                   1272: {
1.1.1.2 ! misho    1273:        zend_uint type = variable->EA;
1.1       misho    1274: 
                   1275:        if (type & ZEND_PARSED_METHOD_CALL) {
                   1276:                zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
                   1277:        }
                   1278:        if (type == ZEND_PARSED_FUNCTION_CALL) {
                   1279:                zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
                   1280:        }
                   1281: }
                   1282: /* }}} */
                   1283: 
                   1284: void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
                   1285: {
                   1286:        zend_llist fetch_list;
                   1287: 
                   1288:        zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
                   1289:        zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
                   1290: }
                   1291: /* }}} */
                   1292: 
                   1293: void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
                   1294: {
                   1295:        zend_llist *fetch_list_ptr;
                   1296:        zend_llist_element *le;
                   1297:        zend_op *opline = NULL;
                   1298:        zend_op *opline_ptr;
                   1299:        zend_uint this_var = -1;
                   1300: 
                   1301:        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
                   1302: 
                   1303:        le = fetch_list_ptr->head;
                   1304: 
                   1305:        /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
                   1306: 
                   1307:        if (le) {
                   1308:                opline_ptr = (zend_op *)le->data;
                   1309:                if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
                   1310:                        /* convert to FETCH_?(this) into IS_CV */
                   1311:                        if (CG(active_op_array)->last == 0 ||
                   1312:                            CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
                   1313: 
1.1.1.2 ! misho    1314:                                this_var = opline_ptr->result.var;
1.1       misho    1315:                                if (CG(active_op_array)->this_var == -1) {
1.1.1.2 ! misho    1316:                                        CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
        !          1317:                                        Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL;
1.1       misho    1318:                                } else {
1.1.1.2 ! misho    1319:                                        zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
1.1       misho    1320:                                }
                   1321:                                le = le->next;
                   1322:                                if (variable->op_type == IS_VAR &&
1.1.1.2 ! misho    1323:                                    variable->u.op.var == this_var) {
1.1       misho    1324:                                        variable->op_type = IS_CV;
1.1.1.2 ! misho    1325:                                        variable->u.op.var = CG(active_op_array)->this_var;
1.1       misho    1326:                                }
                   1327:                        } else if (CG(active_op_array)->this_var == -1) {
1.1.1.2 ! misho    1328:                                CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
1.1       misho    1329:                        }
                   1330:                }
                   1331: 
                   1332:                while (le) {
                   1333:                        opline_ptr = (zend_op *)le->data;
1.1.1.2 ! misho    1334:                        if (opline_ptr->opcode == ZEND_SEPARATE) {
        !          1335:                                if (type != BP_VAR_R && type != BP_VAR_IS) {
        !          1336:                                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        !          1337:                                        memcpy(opline, opline_ptr, sizeof(zend_op));
        !          1338:                                }
        !          1339:                                le = le->next;
        !          1340:                                continue;
        !          1341:                        }
1.1       misho    1342:                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1343:                        memcpy(opline, opline_ptr, sizeof(zend_op));
1.1.1.2 ! misho    1344:                        if (opline->op1_type == IS_VAR &&
        !          1345:                            opline->op1.var == this_var) {
        !          1346:                                opline->op1_type = IS_CV;
        !          1347:                                opline->op1.var = CG(active_op_array)->this_var;
1.1       misho    1348:                        }
                   1349:                        switch (type) {
                   1350:                                case BP_VAR_R:
1.1.1.2 ! misho    1351:                                        if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1.1       misho    1352:                                                zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
                   1353:                                        }
                   1354:                                        opline->opcode -= 3;
                   1355:                                        break;
                   1356:                                case BP_VAR_W:
                   1357:                                        break;
                   1358:                                case BP_VAR_RW:
                   1359:                                        opline->opcode += 3;
                   1360:                                        break;
                   1361:                                case BP_VAR_IS:
1.1.1.2 ! misho    1362:                                        if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1.1       misho    1363:                                                zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
                   1364:                                        }
                   1365:                                        opline->opcode += 6; /* 3+3 */
                   1366:                                        break;
                   1367:                                case BP_VAR_FUNC_ARG:
                   1368:                                        opline->opcode += 9; /* 3+3+3 */
1.1.1.2 ! misho    1369:                                        opline->extended_value |= arg_offset;
1.1       misho    1370:                                        break;
                   1371:                                case BP_VAR_UNSET:
1.1.1.2 ! misho    1372:                                        if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1.1       misho    1373:                                                zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
                   1374:                                        }
                   1375:                                        opline->opcode += 12; /* 3+3+3+3 */
                   1376:                                        break;
                   1377:                        }
                   1378:                        le = le->next;
                   1379:                }
                   1380:                if (opline && type == BP_VAR_W && arg_offset) {
1.1.1.2 ! misho    1381:                        opline->extended_value |= ZEND_FETCH_MAKE_REF;
1.1       misho    1382:                }
                   1383:        }
                   1384:        zend_llist_destroy(fetch_list_ptr);
                   1385:        zend_stack_del_top(&CG(bp_stack));
                   1386: }
                   1387: /* }}} */
                   1388: 
                   1389: void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
                   1390: {
                   1391:        zend_op *opline;
                   1392: 
                   1393:        if (Z_STRLEN(op2->u.constant) > 1) {
                   1394:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1395:                opline->opcode = ZEND_ADD_STRING;
                   1396:        } else if (Z_STRLEN(op2->u.constant) == 1) {
                   1397:                int ch = *Z_STRVAL(op2->u.constant);
                   1398: 
                   1399:                /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
                   1400:                efree(Z_STRVAL(op2->u.constant));
                   1401:                ZVAL_LONG(&op2->u.constant, ch);
                   1402:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1403:                opline->opcode = ZEND_ADD_CHAR;
                   1404:        } else { /* String can be empty after a variable at the end of a heredoc */
                   1405:                efree(Z_STRVAL(op2->u.constant));
                   1406:                return;
                   1407:        }
                   1408: 
                   1409:        if (op1) {
1.1.1.2 ! misho    1410:                SET_NODE(opline->op1, op1);
        !          1411:                SET_NODE(opline->result, op1);
1.1       misho    1412:        } else {
                   1413:                SET_UNUSED(opline->op1);
1.1.1.2 ! misho    1414:                opline->result_type = IS_TMP_VAR;
        !          1415:                opline->result.var = get_temporary_variable(CG(active_op_array));
1.1       misho    1416:        }
1.1.1.2 ! misho    1417:        SET_NODE(opline->op2, op2);
        !          1418:        GET_NODE(result, opline->result);
1.1       misho    1419: }
                   1420: /* }}} */
                   1421: 
                   1422: void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
                   1423: {
                   1424:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1425: 
                   1426:        opline->opcode = ZEND_ADD_VAR;
                   1427: 
                   1428:        if (op1) {
1.1.1.2 ! misho    1429:                SET_NODE(opline->op1, op1);
        !          1430:                SET_NODE(opline->result, op1);
1.1       misho    1431:        } else {
                   1432:                SET_UNUSED(opline->op1);
1.1.1.2 ! misho    1433:                opline->result_type = IS_TMP_VAR;
        !          1434:                opline->result.var = get_temporary_variable(CG(active_op_array));
1.1       misho    1435:        }
1.1.1.2 ! misho    1436:        SET_NODE(opline->op2, op2);
        !          1437:        GET_NODE(result, opline->result);
1.1       misho    1438: }
                   1439: /* }}} */
                   1440: 
                   1441: void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
                   1442: {
                   1443:        if (op1->op_type==IS_TMP_VAR) {
                   1444:                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1445: 
                   1446:                opline->opcode = ZEND_FREE;
1.1.1.2 ! misho    1447:                SET_NODE(opline->op1, op1);
1.1       misho    1448:                SET_UNUSED(opline->op2);
                   1449:        } else if (op1->op_type==IS_VAR) {
                   1450:                zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
                   1451: 
                   1452:                while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
                   1453:                        opline--;
                   1454:                }
1.1.1.2 ! misho    1455:                if (opline->result_type == IS_VAR
        !          1456:                        && opline->result.var == op1->u.op.var) {
        !          1457:                        if (opline->opcode == ZEND_FETCH_R ||
        !          1458:                            opline->opcode == ZEND_FETCH_DIM_R ||
        !          1459:                            opline->opcode == ZEND_FETCH_OBJ_R ||
        !          1460:                            opline->opcode == ZEND_QM_ASSIGN_VAR) {
        !          1461:                                /* It's very rare and useless case. It's better to use
        !          1462:                                   additional FREE opcode and simplify the FETCH handlers
        !          1463:                                   their selves */
        !          1464:                                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        !          1465:                                opline->opcode = ZEND_FREE;
        !          1466:                                SET_NODE(opline->op1, op1);
        !          1467:                                SET_UNUSED(opline->op2);
        !          1468:                        } else {
        !          1469:                                opline->result_type |= EXT_TYPE_UNUSED;
        !          1470:                        }
1.1       misho    1471:                } else {
                   1472:                        while (opline>CG(active_op_array)->opcodes) {
                   1473:                                if (opline->opcode == ZEND_FETCH_DIM_R
1.1.1.2 ! misho    1474:                                    && opline->op1_type == IS_VAR
        !          1475:                                    && opline->op1.var == op1->u.op.var) {
1.1       misho    1476:                                        /* This should the end of a list() construct
                   1477:                                         * Mark its result as unused
                   1478:                                         */
                   1479:                                        opline->extended_value = ZEND_FETCH_STANDARD;
                   1480:                                        break;
1.1.1.2 ! misho    1481:                                } else if (opline->result_type==IS_VAR
        !          1482:                                        && opline->result.var == op1->u.op.var) {
1.1       misho    1483:                                        if (opline->opcode == ZEND_NEW) {
1.1.1.2 ! misho    1484:                                                opline->result_type |= EXT_TYPE_UNUSED;
1.1       misho    1485:                                        }
                   1486:                                        break;
                   1487:                                }
                   1488:                                opline--;
                   1489:                        }
                   1490:                }
                   1491:        } else if (op1->op_type == IS_CONST) {
                   1492:                zval_dtor(&op1->u.constant);
                   1493:        }
                   1494: }
                   1495: /* }}} */
                   1496: 
                   1497: int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
                   1498: {
                   1499:        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
                   1500:                && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
                   1501:                zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
                   1502:        }
                   1503:        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
                   1504:                && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
                   1505:                zend_error(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
                   1506:        }
                   1507:        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
                   1508:                && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
                   1509:                zend_error(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
                   1510:        }
                   1511:        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
                   1512:                && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
                   1513:                zend_error(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
                   1514:        }
                   1515:        if (((Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant)) & (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) == (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) {
                   1516:                zend_error(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
                   1517:        }
                   1518:        return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
                   1519: }
                   1520: /* }}} */
                   1521: 
                   1522: void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
                   1523: {
                   1524:        zend_op_array op_array;
                   1525:        char *name = function_name->u.constant.value.str.val;
                   1526:        int name_len = function_name->u.constant.value.str.len;
1.1.1.2 ! misho    1527:        int function_begin_line = function_token->u.op.opline_num;
1.1       misho    1528:        zend_uint fn_flags;
1.1.1.2 ! misho    1529:        const char *lcname;
1.1       misho    1530:        zend_bool orig_interactive;
                   1531:        ALLOCA_FLAG(use_heap)
                   1532: 
                   1533:        if (is_method) {
                   1534:                if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
                   1535:                        if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
                   1536:                                zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
                   1537:                        }
                   1538:                        Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
                   1539:                }
                   1540:                fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
                   1541:        } else {
                   1542:                fn_flags = 0;
                   1543:        }
                   1544:        if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
                   1545:                zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
                   1546:        }
                   1547: 
                   1548:        function_token->u.op_array = CG(active_op_array);
                   1549: 
                   1550:        orig_interactive = CG(interactive);
                   1551:        CG(interactive) = 0;
                   1552:        init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                   1553:        CG(interactive) = orig_interactive;
                   1554: 
                   1555:        op_array.function_name = name;
1.1.1.2 ! misho    1556:        if (return_reference) {
        !          1557:                op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
        !          1558:        }
1.1       misho    1559:        op_array.fn_flags |= fn_flags;
                   1560: 
                   1561:        op_array.scope = is_method?CG(active_class_entry):NULL;
                   1562:        op_array.prototype = NULL;
                   1563: 
                   1564:        op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
                   1565: 
                   1566:        if (is_method) {
1.1.1.2 ! misho    1567:                int result;
        !          1568:                
        !          1569:                lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
        !          1570: 
        !          1571:                if (IS_INTERNED(lcname)) {
        !          1572:                        result = zend_hash_quick_add(&CG(active_class_entry)->function_table, lcname, name_len+1, INTERNED_HASH(lcname), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
        !          1573:                } else {
        !          1574:                        result = zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
        !          1575:                }
        !          1576:                if (result == FAILURE) {
1.1       misho    1577:                        zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
                   1578:                }
                   1579: 
1.1.1.2 ! misho    1580:                zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
        !          1581:                zend_init_compiler_context(TSRMLS_C);
        !          1582: 
1.1       misho    1583:                if (fn_flags & ZEND_ACC_ABSTRACT) {
                   1584:                        CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
                   1585:                }
                   1586: 
                   1587:                if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
                   1588:                        fn_flags |= ZEND_ACC_PUBLIC;
                   1589:                }
                   1590: 
                   1591:                if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
                   1592:                        if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
                   1593:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1594:                                        zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
                   1595:                                }
                   1596:                        } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
                   1597:                                if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
                   1598:                                        zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
                   1599:                                }
                   1600:                        } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
                   1601:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1602:                                        zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
                   1603:                                }
                   1604:                        } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
                   1605:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1606:                                        zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
                   1607:                                }
                   1608:                        } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
                   1609:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1610:                                        zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
                   1611:                                }
                   1612:                        } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
                   1613:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1614:                                        zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
                   1615:                                }
                   1616:                        } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
                   1617:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1618:                                        zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
                   1619:                                }
                   1620:                        }
                   1621:                } else {
                   1622:                        char *class_lcname;
                   1623:                        
                   1624:                        class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
                   1625:                        zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
                   1626:                        /* Improve after RC: cache the lowercase class name */
                   1627: 
1.1.1.2 ! misho    1628:                        if ((CG(active_class_entry)->name_length == name_len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname, name_len))) {
1.1       misho    1629:                                if (!CG(active_class_entry)->constructor) {
                   1630:                                        CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
                   1631:                                }
                   1632:                        } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
                   1633:                                if (CG(active_class_entry)->constructor) {
                   1634:                                        zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
                   1635:                                }
                   1636:                                CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
                   1637:                        } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
                   1638:                                CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
                   1639:                        } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
                   1640:                                CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
                   1641:                        } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
                   1642:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1643:                                        zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
                   1644:                                }
                   1645:                                CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
                   1646:                        } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
                   1647:                                if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
                   1648:                                        zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
                   1649:                                }
                   1650:                                CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
                   1651:                        } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
                   1652:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1653:                                        zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
                   1654:                                }
                   1655:                                CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
                   1656:                        } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
                   1657:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1658:                                        zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
                   1659:                                }
                   1660:                                CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
                   1661:                        } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
                   1662:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1663:                                        zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
                   1664:                                }
                   1665:                                CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
                   1666:                        } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
                   1667:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1668:                                        zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
                   1669:                                }
                   1670:                                CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
                   1671:                        } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
                   1672:                                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                   1673:                                        zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
                   1674:                                }                               
                   1675:                                CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
                   1676:                        } else if (!(fn_flags & ZEND_ACC_STATIC)) {
                   1677:                                CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
                   1678:                        }
                   1679:                        free_alloca(class_lcname, use_heap);
                   1680:                }
                   1681: 
1.1.1.2 ! misho    1682:                str_efree(lcname);
1.1       misho    1683:        } else {
                   1684:                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1.1.1.2 ! misho    1685:                zval key;
1.1       misho    1686: 
                   1687:                if (CG(current_namespace)) {
                   1688:                        /* Prefix function name with current namespcae name */
                   1689:                        znode tmp;
                   1690: 
                   1691:                        tmp.u.constant = *CG(current_namespace);
                   1692:                        zval_copy_ctor(&tmp.u.constant);
                   1693:                        zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
                   1694:                        op_array.function_name = Z_STRVAL(tmp.u.constant);
                   1695:                        name_len = Z_STRLEN(tmp.u.constant);
                   1696:                        lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
1.1.1.2 ! misho    1697:                } else {
        !          1698:                        lcname = zend_str_tolower_dup(name, name_len);
1.1       misho    1699:                }
                   1700: 
                   1701:                opline->opcode = ZEND_DECLARE_FUNCTION;
1.1.1.2 ! misho    1702:                opline->op1_type = IS_CONST;
        !          1703:                build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
        !          1704:                opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
        !          1705:                Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
        !          1706:                opline->op2_type = IS_CONST;
        !          1707:                LITERAL_STRINGL(opline->op2, lcname, name_len, 0);
        !          1708:                CALCULATE_LITERAL_HASH(opline->op2.constant);
1.1       misho    1709:                opline->extended_value = ZEND_DECLARE_FUNCTION;
1.1.1.2 ! misho    1710:                zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
        !          1711:                zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
        !          1712:                zend_init_compiler_context(TSRMLS_C);
1.1       misho    1713:        }
                   1714: 
                   1715:        if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
                   1716:                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1717: 
                   1718:                opline->opcode = ZEND_EXT_NOP;
                   1719:                opline->lineno = function_begin_line;
                   1720:                SET_UNUSED(opline->op1);
                   1721:                SET_UNUSED(opline->op2);
                   1722:        }
                   1723: 
                   1724:        {
                   1725:                /* Push a seperator to the switch and foreach stacks */
                   1726:                zend_switch_entry switch_entry;
                   1727: 
                   1728:                switch_entry.cond.op_type = IS_UNUSED;
                   1729:                switch_entry.default_case = 0;
                   1730:                switch_entry.control_var = 0;
                   1731: 
                   1732:                zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
                   1733: 
                   1734:                {
                   1735:                        /* Foreach stack separator */
                   1736:                        zend_op dummy_opline;
                   1737: 
1.1.1.2 ! misho    1738:                        dummy_opline.result_type = IS_UNUSED;
        !          1739:                        dummy_opline.op1_type = IS_UNUSED;
1.1       misho    1740: 
                   1741:                        zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
                   1742:                }
                   1743:        }
                   1744: 
                   1745:        if (CG(doc_comment)) {
                   1746:                CG(active_op_array)->doc_comment = CG(doc_comment);
                   1747:                CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
                   1748:                CG(doc_comment) = NULL;
                   1749:                CG(doc_comment_len) = 0;
                   1750:        }
                   1751: }
                   1752: /* }}} */
                   1753: 
1.1.1.2 ! misho    1754: void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) /* {{{ */
1.1       misho    1755: {
                   1756:        znode          function_name;
                   1757:        zend_op_array *current_op_array = CG(active_op_array);
                   1758:        int            current_op_number = get_next_op_number(CG(active_op_array));
                   1759:        zend_op       *current_op;
                   1760: 
                   1761:        function_name.op_type = IS_CONST;
                   1762:        ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
                   1763: 
                   1764:        zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
                   1765: 
                   1766:        result->op_type = IS_TMP_VAR;
1.1.1.2 ! misho    1767:        result->u.op.var = get_temporary_variable(current_op_array);
1.1       misho    1768: 
                   1769:        current_op = &current_op_array->opcodes[current_op_number];
                   1770:        current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
1.1.1.2 ! misho    1771:        zend_del_literal(current_op_array, current_op->op2.constant);
        !          1772:        SET_UNUSED(current_op->op2);
        !          1773:        SET_NODE(current_op->result, result);
        !          1774:        if (is_static) {
        !          1775:                CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
        !          1776:        }
1.1       misho    1777:        CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
                   1778: }
                   1779: /* }}} */
                   1780: 
                   1781: void zend_do_handle_exception(TSRMLS_D) /* {{{ */
                   1782: {
                   1783:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1784: 
                   1785:        opline->opcode = ZEND_HANDLE_EXCEPTION;
                   1786:        SET_UNUSED(opline->op1);
                   1787:        SET_UNUSED(opline->op2);
                   1788: }
                   1789: /* }}} */
                   1790: 
                   1791: void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
                   1792: {
                   1793:        char lcname[16];
                   1794:        int name_len;
                   1795: 
                   1796:        zend_do_extended_info(TSRMLS_C);
                   1797:        zend_do_return(NULL, 0 TSRMLS_CC);
                   1798: 
                   1799:        pass_two(CG(active_op_array) TSRMLS_CC);
                   1800:        zend_release_labels(TSRMLS_C);
                   1801: 
                   1802:        if (CG(active_class_entry)) {
                   1803:                zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
                   1804:        } else {
                   1805:                /* we don't care if the function name is longer, in fact lowercasing only 
                   1806:                 * the beginning of the name speeds up the check process */
                   1807:                name_len = strlen(CG(active_op_array)->function_name);
                   1808:                zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
                   1809:                lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
                   1810:                if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
                   1811:                        zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
                   1812:                }               
                   1813:        }
                   1814: 
                   1815:        CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
                   1816:        CG(active_op_array) = function_token->u.op_array;
                   1817: 
                   1818: 
                   1819:        /* Pop the switch and foreach seperators */
                   1820:        zend_stack_del_top(&CG(switch_cond_stack));
                   1821:        zend_stack_del_top(&CG(foreach_copy_stack));
                   1822: }
                   1823: /* }}} */
                   1824: 
1.1.1.2 ! misho    1825: void zend_do_receive_arg(zend_uchar op, znode *varname, const znode *offset, const znode *initialization, znode *class_type, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
1.1       misho    1826: {
                   1827:        zend_op *opline;
                   1828:        zend_arg_info *cur_arg_info;
1.1.1.2 ! misho    1829:        znode var;
1.1       misho    1830: 
                   1831:        if (class_type->op_type == IS_CONST &&
                   1832:            Z_TYPE(class_type->u.constant) == IS_STRING &&
                   1833:            Z_STRLEN(class_type->u.constant) == 0) {
                   1834:                /* Usage of namespace as class name not in namespace */
                   1835:                zval_dtor(&class_type->u.constant);
                   1836:                zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
                   1837:                return;
                   1838:        }
                   1839: 
1.1.1.2 ! misho    1840:        if (zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0 TSRMLS_CC)) {
        !          1841:                zend_error(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
        !          1842:        } else {
        !          1843:                var.op_type = IS_CV;
        !          1844:                var.u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len, 0 TSRMLS_CC);
        !          1845:                Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
        !          1846:                var.EA = 0;
        !          1847:                if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
        !          1848:                        Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
        !          1849:                    !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
        !          1850:                        if (CG(active_op_array)->scope &&
        !          1851:                            (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
        !          1852:                                zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
        !          1853:                        }
        !          1854:                        CG(active_op_array)->this_var = var.u.op.var;
        !          1855:                }
1.1       misho    1856:        }
                   1857: 
                   1858:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1859:        CG(active_op_array)->num_args++;
                   1860:        opline->opcode = op;
1.1.1.2 ! misho    1861:        SET_NODE(opline->result, &var);
        !          1862:        SET_NODE(opline->op1, offset);
1.1       misho    1863:        if (op == ZEND_RECV_INIT) {
1.1.1.2 ! misho    1864:                SET_NODE(opline->op2, initialization);
1.1       misho    1865:        } else {
                   1866:                CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
                   1867:                SET_UNUSED(opline->op2);
                   1868:        }
                   1869:        CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
                   1870:        cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
1.1.1.2 ! misho    1871:        cur_arg_info->name = zend_new_interned_string(estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len), varname->u.constant.value.str.len + 1, 1 TSRMLS_CC);
1.1       misho    1872:        cur_arg_info->name_len = varname->u.constant.value.str.len;
1.1.1.2 ! misho    1873:        cur_arg_info->type_hint = 0;
1.1       misho    1874:        cur_arg_info->allow_null = 1;
                   1875:        cur_arg_info->pass_by_reference = pass_by_reference;
                   1876:        cur_arg_info->class_name = NULL;
                   1877:        cur_arg_info->class_name_len = 0;
                   1878: 
                   1879:        if (class_type->op_type != IS_UNUSED) {
                   1880:                cur_arg_info->allow_null = 0;
1.1.1.2 ! misho    1881: 
        !          1882:                if (class_type->u.constant.type != IS_NULL) {
        !          1883:                        if (class_type->u.constant.type == IS_ARRAY) {
        !          1884:                                cur_arg_info->type_hint = IS_ARRAY;
        !          1885:                                if (op == ZEND_RECV_INIT) {
        !          1886:                                        if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
        !          1887:                                                cur_arg_info->allow_null = 1;
        !          1888:                                        } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
        !          1889:                                                zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
        !          1890:                                        }
1.1       misho    1891:                                }
1.1.1.2 ! misho    1892:                        } else if (class_type->u.constant.type == IS_CALLABLE) {
        !          1893:                                cur_arg_info->type_hint = IS_CALLABLE;
        !          1894:                                if (op == ZEND_RECV_INIT) {
        !          1895:                                        if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
        !          1896:                                                cur_arg_info->allow_null = 1;
        !          1897:                                        } else {
        !          1898:                                                zend_error(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
        !          1899:                                        }
        !          1900:                                }
        !          1901:                        } else {
        !          1902:                                cur_arg_info->type_hint = IS_OBJECT;
        !          1903:                                if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
        !          1904:                                        zend_resolve_class_name(class_type, opline->extended_value, 1 TSRMLS_CC);
        !          1905:                                }
        !          1906:                                Z_STRVAL(class_type->u.constant) = (char*)zend_new_interned_string(class_type->u.constant.value.str.val, class_type->u.constant.value.str.len + 1, 1 TSRMLS_CC);
        !          1907:                                cur_arg_info->class_name = class_type->u.constant.value.str.val;
        !          1908:                                cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
        !          1909:                                if (op == ZEND_RECV_INIT) {
        !          1910:                                        if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
        !          1911:                                                cur_arg_info->allow_null = 1;
        !          1912:                                        } else {
        !          1913:                                                zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
        !          1914:                                        }
1.1       misho    1915:                                }
                   1916:                        }
                   1917:                }
                   1918:        }
                   1919: }
                   1920: /* }}} */
                   1921: 
                   1922: int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
                   1923: {
                   1924:        zend_function *function;
                   1925:        char *lcname;
                   1926:        char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
                   1927: 
                   1928:        zend_resolve_non_class_name(function_name, check_namespace TSRMLS_CC);
                   1929: 
                   1930:        if (check_namespace && CG(current_namespace) && !is_compound) {
                   1931:                        /* We assume we call function from the current namespace
                   1932:                        if it is not prefixed. */
                   1933: 
                   1934:                        /* In run-time PHP will check for function with full name and
                   1935:                        internal function with short name */
                   1936:                        zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
                   1937:                        return 1;
                   1938:        } 
                   1939: 
                   1940:        lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
                   1941:        if ((zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) ||
                   1942:                ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
                   1943:                (function->type == ZEND_INTERNAL_FUNCTION))) {
                   1944:                        zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
                   1945:                        efree(lcname);
                   1946:                        return 1; /* Dynamic */
                   1947:        } 
                   1948:        efree(function_name->u.constant.value.str.val);
                   1949:        function_name->u.constant.value.str.val = lcname;
                   1950:        
                   1951:        zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *));
                   1952:        zend_do_extended_fcall_begin(TSRMLS_C);
                   1953:        return 0;
                   1954: }
                   1955: /* }}} */
                   1956: 
                   1957: void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
                   1958: {
                   1959:        zend_op *last_op;
                   1960:        int last_op_number;
                   1961:        unsigned char *ptr = NULL;
                   1962: 
                   1963:        zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
                   1964:        zend_do_begin_variable_parse(TSRMLS_C);
                   1965: 
                   1966:        last_op_number = get_next_op_number(CG(active_op_array))-1;
                   1967:        last_op = &CG(active_op_array)->opcodes[last_op_number];
                   1968: 
1.1.1.2 ! misho    1969:        if ((last_op->op2_type == IS_CONST) && (Z_TYPE(CONSTANT(last_op->op2.constant)) == IS_STRING) && (Z_STRLEN(CONSTANT(last_op->op2.constant)) == sizeof(ZEND_CLONE_FUNC_NAME)-1)
        !          1970:                && !zend_binary_strcasecmp(Z_STRVAL(CONSTANT(last_op->op2.constant)), Z_STRLEN(CONSTANT(last_op->op2.constant)), ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
1.1       misho    1971:                zend_error(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
                   1972:        }
                   1973: 
                   1974:        if (last_op->opcode == ZEND_FETCH_OBJ_R) {
1.1.1.2 ! misho    1975:                if (last_op->op2_type == IS_CONST) {
        !          1976:                        zval name;
        !          1977:                        name = CONSTANT(last_op->op2.constant);
        !          1978:                        if (Z_TYPE(name) != IS_STRING) {
        !          1979:                                zend_error(E_COMPILE_ERROR, "Method name must be a string");
        !          1980:                        } 
        !          1981:                        if (!IS_INTERNED(Z_STRVAL(name))) {
        !          1982:                                Z_STRVAL(name) = estrndup(Z_STRVAL(name), Z_STRLEN(name));
        !          1983:                        }
        !          1984:                        FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
        !          1985:                        last_op->op2.constant =
        !          1986:                                zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
        !          1987:                        GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
        !          1988:                }
1.1       misho    1989:                last_op->opcode = ZEND_INIT_METHOD_CALL;
                   1990:                SET_UNUSED(last_op->result);
                   1991:                Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
                   1992:        } else {
                   1993:                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   1994:                opline->opcode = ZEND_INIT_FCALL_BY_NAME;
1.1.1.2 ! misho    1995:                SET_UNUSED(opline->op1);
        !          1996:                if (left_bracket->op_type == IS_CONST) {
        !          1997:                        opline->op2_type = IS_CONST;
        !          1998:                        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
        !          1999:                        GET_CACHE_SLOT(opline->op2.constant);
1.1       misho    2000:                } else {
1.1.1.2 ! misho    2001:                        SET_NODE(opline->op2, left_bracket);
1.1       misho    2002:                }
                   2003:        }
                   2004: 
                   2005:        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
                   2006:        zend_do_extended_fcall_begin(TSRMLS_C);
                   2007: }
                   2008: /* }}} */
                   2009: 
                   2010: void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
                   2011: {
                   2012:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2013: 
                   2014:        opline->opcode = ZEND_CLONE;
1.1.1.2 ! misho    2015:        SET_NODE(opline->op1, expr);
1.1       misho    2016:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    2017:        opline->result_type = IS_VAR;
        !          2018:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          2019:        GET_NODE(result, opline->result);
1.1       misho    2020: }
                   2021: /* }}} */
                   2022: 
                   2023: void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
                   2024: {
                   2025:        unsigned char *ptr = NULL;
1.1.1.2 ! misho    2026:        zend_op *opline;
1.1       misho    2027: 
                   2028:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2029:        if (ns_call) {
                   2030:                /* In run-time PHP will check for function with full name and
                   2031:                   internal function with short name */
                   2032:                opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
1.1.1.2 ! misho    2033:                SET_UNUSED(opline->op1);
        !          2034:                opline->op2_type = IS_CONST;
        !          2035:                opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
        !          2036:                GET_CACHE_SLOT(opline->op2.constant);
1.1       misho    2037:        } else {
                   2038:                opline->opcode = ZEND_INIT_FCALL_BY_NAME;
1.1.1.2 ! misho    2039:                SET_UNUSED(opline->op1);
        !          2040:                if (function_name->op_type == IS_CONST) {
        !          2041:                        opline->op2_type = IS_CONST;
        !          2042:                        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
        !          2043:                        GET_CACHE_SLOT(opline->op2.constant);
1.1       misho    2044:                } else {
1.1.1.2 ! misho    2045:                        SET_NODE(opline->op2, function_name);
1.1       misho    2046:                }
                   2047:        }
                   2048: 
                   2049:        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
                   2050:        zend_do_extended_fcall_begin(TSRMLS_C);
                   2051: }
                   2052: /* }}} */
                   2053: 
                   2054: void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
                   2055: {
                   2056:        znode tmp;
                   2057:        int len;
                   2058:        zval **ns;
                   2059:        char *lcname, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
                   2060: 
                   2061:        if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
                   2062:                /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
                   2063:                memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
                   2064:                --Z_STRLEN(element_name->u.constant);
                   2065:                return;
                   2066:        }
                   2067: 
                   2068:        if(!check_namespace) {
                   2069:                return;
                   2070:        }
                   2071: 
                   2072:        if (compound && CG(current_import)) {
                   2073:                len = compound - Z_STRVAL(element_name->u.constant);
                   2074:                lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
                   2075:                /* Check if first part of compound name is an import name */
                   2076:                if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
                   2077:                        /* Substitute import name */
                   2078:                        tmp.op_type = IS_CONST;
                   2079:                        tmp.u.constant = **ns;
                   2080:                        zval_copy_ctor(&tmp.u.constant);
                   2081:                        len += 1;
                   2082:                        Z_STRLEN(element_name->u.constant) -= len;
                   2083:                        memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
                   2084:                        zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
                   2085:                        *element_name = tmp;
                   2086:                        efree(lcname);
                   2087:                        return;
                   2088:                }
                   2089:                efree(lcname);
                   2090:        }
                   2091: 
                   2092:        if (CG(current_namespace)) {
                   2093:                tmp = *element_name;
                   2094:                Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
                   2095:                Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
                   2096:                memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
                   2097:                memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace))]), "\\", sizeof("\\")-1);
                   2098:                memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace)) + sizeof("\\")-1]), Z_STRVAL(element_name->u.constant), Z_STRLEN(element_name->u.constant)+1);
                   2099:                STR_FREE(Z_STRVAL(element_name->u.constant));
                   2100:                *element_name = tmp;
                   2101:        }
                   2102: }
                   2103: /* }}} */
                   2104: 
1.1.1.2 ! misho    2105: void zend_resolve_class_name(znode *class_name, ulong fetch_type, int check_ns_name TSRMLS_DC) /* {{{ */
1.1       misho    2106: {
                   2107:        char *compound;
                   2108:        char *lcname;
                   2109:        zval **ns;
                   2110:        znode tmp;
                   2111:        int len;
                   2112: 
                   2113:        compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
                   2114:        if (compound) {
                   2115:                /* This is a compound class name that contains namespace prefix */
                   2116:                if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
1.1.1.2 ! misho    2117:                        /* The STRING name has "\" prefix */
        !          2118:                        Z_STRLEN(class_name->u.constant) -= 1;
        !          2119:                        memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
1.1       misho    2120:                        Z_STRVAL(class_name->u.constant) = erealloc(
1.1.1.2 ! misho    2121:                        Z_STRVAL(class_name->u.constant),
        !          2122:                        Z_STRLEN(class_name->u.constant) + 1);
1.1       misho    2123: 
                   2124:                        if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
                   2125:                                zend_error(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
                   2126:                        }
                   2127:                } else { 
                   2128:                        if (CG(current_import)) {
                   2129:                                len = compound - Z_STRVAL(class_name->u.constant);
                   2130:                                lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
                   2131:                                /* Check if first part of compound name is an import name */
                   2132:                                if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
                   2133:                                        /* Substitute import name */
                   2134:                                        tmp.op_type = IS_CONST;
                   2135:                                        tmp.u.constant = **ns;
                   2136:                                        zval_copy_ctor(&tmp.u.constant);
                   2137:                                        len += 1;
                   2138:                                        Z_STRLEN(class_name->u.constant) -= len;
                   2139:                                        memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
                   2140:                                        zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
                   2141:                                        *class_name = tmp;
                   2142:                                        efree(lcname);
                   2143:                                        return;
                   2144:                                }
                   2145:                                efree(lcname);
                   2146:                        }
                   2147:                        /* Here name is not prefixed with \ and not imported */
                   2148:                        if (CG(current_namespace)) {
                   2149:                                tmp.op_type = IS_CONST;
                   2150:                                tmp.u.constant = *CG(current_namespace);
                   2151:                                zval_copy_ctor(&tmp.u.constant);
                   2152:                                zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
                   2153:                                *class_name = tmp;
                   2154:                        }
                   2155:                }
                   2156:        } else if (CG(current_import) || CG(current_namespace)) {
                   2157:                /* this is a plain name (without \) */
                   2158:                lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
                   2159: 
                   2160:                if (CG(current_import) &&
                   2161:                    zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
                   2162:                    /* The given name is an import name. Substitute it. */
                   2163:                        zval_dtor(&class_name->u.constant);
                   2164:                        class_name->u.constant = **ns;
                   2165:                        zval_copy_ctor(&class_name->u.constant);
                   2166:                } else if (CG(current_namespace)) {
                   2167:                        /* plain name, no import - prepend current namespace to it */
                   2168:                        tmp.op_type = IS_CONST;
                   2169:                        tmp.u.constant = *CG(current_namespace);
                   2170:                        zval_copy_ctor(&tmp.u.constant);
                   2171:                        zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
                   2172:                        *class_name = tmp;
                   2173:                }
                   2174:                efree(lcname);
                   2175:        }
                   2176: }
                   2177: /* }}} */
                   2178: 
                   2179: void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
                   2180: {
                   2181:        long fetch_class_op_number;
                   2182:        zend_op *opline;
                   2183: 
                   2184:        if (class_name->op_type == IS_CONST &&
                   2185:            Z_TYPE(class_name->u.constant) == IS_STRING &&
                   2186:            Z_STRLEN(class_name->u.constant) == 0) {
                   2187:                /* Usage of namespace as class name not in namespace */
                   2188:                zval_dtor(&class_name->u.constant);
                   2189:                zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
                   2190:                return;
                   2191:        }
                   2192: 
                   2193:        fetch_class_op_number = get_next_op_number(CG(active_op_array));
                   2194:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2195: 
                   2196:        opline->opcode = ZEND_FETCH_CLASS;
                   2197:        SET_UNUSED(opline->op1);
                   2198:        opline->extended_value = ZEND_FETCH_CLASS_GLOBAL;
                   2199:        CG(catch_begin) = fetch_class_op_number;
                   2200:        if (class_name->op_type == IS_CONST) {
                   2201:                int fetch_type;
                   2202: 
                   2203:                fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
                   2204:                switch (fetch_type) {
                   2205:                        case ZEND_FETCH_CLASS_SELF:
                   2206:                        case ZEND_FETCH_CLASS_PARENT:
                   2207:                        case ZEND_FETCH_CLASS_STATIC:
                   2208:                                SET_UNUSED(opline->op2);
                   2209:                                opline->extended_value = fetch_type;
                   2210:                                zval_dtor(&class_name->u.constant);
                   2211:                                break;
                   2212:                        default:
1.1.1.2 ! misho    2213:                                zend_resolve_class_name(class_name, opline->extended_value, 0 TSRMLS_CC);
        !          2214:                                opline->op2_type = IS_CONST;
        !          2215:                                opline->op2.constant =
        !          2216:                                        zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
1.1       misho    2217:                                break;
                   2218:                }
                   2219:        } else {
1.1.1.2 ! misho    2220:                SET_NODE(opline->op2, class_name);
1.1       misho    2221:        }
1.1.1.2 ! misho    2222:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          2223:        opline->result_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
        !          2224:        GET_NODE(result, opline->result);
        !          2225:        result->EA = opline->extended_value;
1.1       misho    2226: }
                   2227: /* }}} */
                   2228: 
                   2229: void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
                   2230: {
                   2231:        zend_label dest;
                   2232: 
1.1.1.2 ! misho    2233:        if (!CG(context).labels) {
        !          2234:                ALLOC_HASHTABLE(CG(context).labels);
        !          2235:                zend_hash_init(CG(context).labels, 4, NULL, NULL, 0);
1.1       misho    2236:        }
                   2237: 
1.1.1.2 ! misho    2238:        dest.brk_cont = CG(context).current_brk_cont;
        !          2239:        dest.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    2240: 
1.1.1.2 ! misho    2241:        if (zend_hash_add(CG(context).labels, Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
1.1       misho    2242:                zend_error(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
                   2243:        }
                   2244: 
                   2245:        /* Done with label now */
                   2246:        zval_dtor(&label->u.constant);
                   2247: }
                   2248: /* }}} */
                   2249: 
                   2250: void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
                   2251: {
                   2252:        zend_label *dest;
                   2253:        long current, distance;
1.1.1.2 ! misho    2254:        zval *label;
1.1       misho    2255: 
1.1.1.2 ! misho    2256:        if (pass2) {
        !          2257:                label = opline->op2.zv;
        !          2258:        } else {
        !          2259:                label = &CONSTANT_EX(op_array, opline->op2.constant);
        !          2260:        }
        !          2261:        if (CG(context).labels == NULL ||
        !          2262:            zend_hash_find(CG(context).labels, Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
1.1       misho    2263: 
                   2264:                if (pass2) {
                   2265:                        CG(in_compilation) = 1;
                   2266:                        CG(active_op_array) = op_array;
                   2267:                        CG(zend_lineno) = opline->lineno;
1.1.1.2 ! misho    2268:                        zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
1.1       misho    2269:                } else {
                   2270:                        /* Label is not defined. Delay to pass 2. */
                   2271:                        INC_BPC(op_array);
                   2272:                        return;
                   2273:                }
                   2274:        }
                   2275: 
1.1.1.2 ! misho    2276:        opline->op1.opline_num = dest->opline_num;
        !          2277:        zval_dtor(label);
        !          2278:        Z_TYPE_P(label) = IS_NULL;
1.1       misho    2279: 
                   2280:        /* Check that we are not moving into loop or switch */
                   2281:        current = opline->extended_value;
                   2282:        for (distance = 0; current != dest->brk_cont; distance++) {
                   2283:                if (current == -1) {
                   2284:                        if (pass2) {
                   2285:                                CG(in_compilation) = 1;
                   2286:                                CG(active_op_array) = op_array;
                   2287:                                CG(zend_lineno) = opline->lineno;
                   2288:                        }
                   2289:                        zend_error(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
                   2290:                }
                   2291:                current = op_array->brk_cont_array[current].parent;
                   2292:        }
                   2293: 
                   2294:        if (distance == 0) {
                   2295:                /* Nothing to break out of, optimize to ZEND_JMP */
                   2296:                opline->opcode = ZEND_JMP;
                   2297:                opline->extended_value = 0;
                   2298:                SET_UNUSED(opline->op2);
                   2299:        } else {
                   2300:                /* Set real break distance */
1.1.1.2 ! misho    2301:                ZVAL_LONG(label, distance);
1.1       misho    2302:        }
                   2303: 
                   2304:        if (pass2) {
                   2305:                DEC_BPC(op_array);
                   2306:        }
                   2307: }
                   2308: /* }}} */
                   2309: 
                   2310: void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
                   2311: {
                   2312:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2313: 
                   2314:        opline->opcode = ZEND_GOTO;
1.1.1.2 ! misho    2315:        opline->extended_value = CG(context).current_brk_cont;
1.1       misho    2316:        SET_UNUSED(opline->op1);
1.1.1.2 ! misho    2317:        SET_NODE(opline->op2, label);
1.1       misho    2318:        zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
                   2319: }
                   2320: /* }}} */
                   2321: 
                   2322: void zend_release_labels(TSRMLS_D) /* {{{ */
                   2323: {
1.1.1.2 ! misho    2324:        if (CG(context).labels) {
        !          2325:                zend_hash_destroy(CG(context).labels);
        !          2326:                FREE_HASHTABLE(CG(context).labels);
        !          2327:        }
        !          2328:        if (!zend_stack_is_empty(&CG(context_stack))) {
        !          2329:                zend_compiler_context *ctx;
        !          2330: 
        !          2331:                zend_stack_top(&CG(context_stack), (void**)&ctx);
        !          2332:                CG(context) = *ctx;
        !          2333:                zend_stack_del_top(&CG(context_stack));
1.1       misho    2334:        }
                   2335: }
                   2336: /* }}} */
                   2337: 
                   2338: void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
                   2339: {
                   2340:        zend_uint length;
                   2341: 
                   2342:        if (!result) {
                   2343:                result = prefix;
                   2344:        } else {
                   2345:                *result = *prefix;
                   2346:        }
                   2347: 
                   2348:        if (is_class_member) {
                   2349:                length = sizeof("::")-1 + result->u.constant.value.str.len + name->u.constant.value.str.len;
                   2350:                result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
                   2351:                memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
                   2352:                memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], name->u.constant.value.str.val, name->u.constant.value.str.len+1);
                   2353:                STR_FREE(name->u.constant.value.str.val);
                   2354:                result->u.constant.value.str.len = length;
                   2355:        } else {
                   2356:                length = sizeof("\\")-1 + result->u.constant.value.str.len + name->u.constant.value.str.len;
                   2357:                result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
                   2358:                memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "\\", sizeof("\\")-1);
                   2359:                memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("\\")-1], name->u.constant.value.str.val, name->u.constant.value.str.len+1);
                   2360:                STR_FREE(name->u.constant.value.str.val);
                   2361:                result->u.constant.value.str.len = length;
                   2362:        }
                   2363: }
                   2364: /* }}} */
                   2365: 
                   2366: int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
                   2367: {
                   2368:        znode class_node;
                   2369:        unsigned char *ptr = NULL;
                   2370:        zend_op *opline;
                   2371: 
                   2372:        if (method_name->op_type == IS_CONST) {
1.1.1.2 ! misho    2373:                char *lcname;
        !          2374:                if (Z_TYPE(method_name->u.constant) != IS_STRING) {
        !          2375:                        zend_error(E_COMPILE_ERROR, "Method name must be a string");
        !          2376:                }
        !          2377:                lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
1.1       misho    2378:                if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
1.1.1.2 ! misho    2379:                    memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
1.1       misho    2380:                        zval_dtor(&method_name->u.constant);
1.1.1.2 ! misho    2381:                        method_name->op_type = IS_UNUSED;
1.1       misho    2382:                }
                   2383:                efree(lcname);
                   2384:        }
                   2385: 
                   2386:        if (class_name->op_type == IS_CONST &&
1.1.1.2 ! misho    2387:            ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
        !          2388:                zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
1.1       misho    2389:                class_node = *class_name;
1.1.1.2 ! misho    2390:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1.1       misho    2391:        } else {
                   2392:                zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
1.1.1.2 ! misho    2393:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        !          2394:                opline->extended_value = class_node.EA  ;
1.1       misho    2395:        }
                   2396:        opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
1.1.1.2 ! misho    2397:        if (class_node.op_type == IS_CONST) {
        !          2398:                opline->op1_type = IS_CONST;
        !          2399:                opline->op1.constant =
        !          2400:                        zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
        !          2401:        } else {
        !          2402:                SET_NODE(opline->op1, &class_node);
        !          2403:        }
        !          2404:        if (method_name->op_type == IS_CONST) {
        !          2405:                opline->op2_type = IS_CONST;
        !          2406:                opline->op2.constant =
        !          2407:                        zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
        !          2408:                if (opline->op1_type == IS_CONST) {
        !          2409:                        GET_CACHE_SLOT(opline->op2.constant);
        !          2410:                } else {
        !          2411:                        GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
        !          2412:                }
        !          2413:        } else {
        !          2414:                SET_NODE(opline->op2, method_name);
        !          2415:        }
1.1       misho    2416: 
                   2417:        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
                   2418:        zend_do_extended_fcall_begin(TSRMLS_C);
                   2419:        return 1; /* Dynamic */
                   2420: }
                   2421: /* }}} */
                   2422: 
                   2423: void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
                   2424: {
                   2425:        zend_op *opline;
                   2426: 
                   2427:        if (is_method && function_name && function_name->op_type == IS_UNUSED) {
                   2428:                /* clone */
                   2429:                if (Z_LVAL(argument_list->u.constant) != 0) {
                   2430:                        zend_error(E_WARNING, "Clone method does not require arguments");
                   2431:                }
                   2432:                opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
                   2433:        } else {
                   2434:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2435:                if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
                   2436:                        opline->opcode = ZEND_DO_FCALL;
1.1.1.2 ! misho    2437:                        SET_NODE(opline->op1, function_name);
        !          2438:                        CALCULATE_LITERAL_HASH(opline->op1.constant);
        !          2439:                        GET_CACHE_SLOT(opline->op1.constant);
1.1       misho    2440:                } else {
                   2441:                        opline->opcode = ZEND_DO_FCALL_BY_NAME;
                   2442:                        SET_UNUSED(opline->op1);
                   2443:                }
                   2444:        }
                   2445: 
1.1.1.2 ! misho    2446:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          2447:        opline->result_type = IS_VAR;
        !          2448:        GET_NODE(result, opline->result)        ;
1.1       misho    2449:        SET_UNUSED(opline->op2);
                   2450: 
                   2451:        zend_stack_del_top(&CG(function_call_stack));
                   2452:        opline->extended_value = Z_LVAL(argument_list->u.constant);
                   2453: }
                   2454: /* }}} */
                   2455: 
                   2456: void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{{ */
                   2457: {
                   2458:        zend_op *opline;
                   2459:        int original_op=op;
                   2460:        zend_function **function_ptr_ptr, *function_ptr;
                   2461:        int send_by_reference;
                   2462:        int send_function = 0;
                   2463: 
                   2464:        zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
                   2465:        function_ptr = *function_ptr_ptr;
                   2466: 
1.1.1.2 ! misho    2467:        if (original_op == ZEND_SEND_REF) {
1.1       misho    2468:                if (function_ptr &&
1.1.1.2 ! misho    2469:                    function_ptr->common.function_name &&
        !          2470:                    function_ptr->common.type == ZEND_USER_FUNCTION &&
        !          2471:                    !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
        !          2472:                        zend_error(E_COMPILE_ERROR,
        !          2473:                                                "Call-time pass-by-reference has been removed; "
        !          2474:                                                "If you would like to pass argument by reference, modify the declaration of %s().",
        !          2475:                                                function_ptr->common.function_name);
1.1       misho    2476:                } else {
1.1.1.2 ! misho    2477:                        zend_error(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed");
1.1       misho    2478:                }
1.1.1.2 ! misho    2479:                return;
        !          2480:        } 
        !          2481:        
1.1       misho    2482:        if (function_ptr) {
                   2483:                if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
1.1.1.2 ! misho    2484:                        if (param->op_type & (IS_VAR|IS_CV) && original_op != ZEND_SEND_VAL) {
1.1       misho    2485:                                send_by_reference = 1;
                   2486:                                if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
                   2487:                                        /* Method call */
                   2488:                                        op = ZEND_SEND_VAR_NO_REF;
                   2489:                                        send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
                   2490:                                }
                   2491:                        } else {
                   2492:                                op = ZEND_SEND_VAL;
                   2493:                                send_by_reference = 0;
                   2494:                        }
                   2495:                } else {
                   2496:                        send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
                   2497:                }
                   2498:        } else {
                   2499:                send_by_reference = 0;
                   2500:        }
                   2501: 
                   2502:        if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
                   2503:                /* Method call */
                   2504:                op = ZEND_SEND_VAR_NO_REF;
                   2505:                send_function = ZEND_ARG_SEND_FUNCTION;
                   2506:        } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
                   2507:                op = ZEND_SEND_VAR_NO_REF;
                   2508:        }
                   2509: 
                   2510:        if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
                   2511:                /* change to passing by reference */
                   2512:                switch (param->op_type) {
                   2513:                        case IS_VAR:
                   2514:                        case IS_CV:
                   2515:                                op = ZEND_SEND_REF;
                   2516:                                break;
                   2517:                        default:
                   2518:                                zend_error(E_COMPILE_ERROR, "Only variables can be passed by reference");
                   2519:                                break;
                   2520:                }
                   2521:        }
                   2522: 
                   2523:        if (original_op == ZEND_SEND_VAR) {
                   2524:                switch (op) {
                   2525:                        case ZEND_SEND_VAR_NO_REF:
                   2526:                                zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
                   2527:                                break;
                   2528:                        case ZEND_SEND_VAR:
                   2529:                                if (function_ptr) {
                   2530:                                        zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
                   2531:                                } else {
                   2532:                                        zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
                   2533:                                }
                   2534:                                break;
                   2535:                        case ZEND_SEND_REF:
                   2536:                                zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
                   2537:                                break;
                   2538:                }
                   2539:        }
                   2540: 
                   2541:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2542: 
                   2543:        if (op == ZEND_SEND_VAR_NO_REF) {
                   2544:                if (function_ptr) {
                   2545:                        opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
                   2546:                } else {
                   2547:                        opline->extended_value = send_function;
                   2548:                }
                   2549:        } else {
                   2550:                if (function_ptr) {
                   2551:                        opline->extended_value = ZEND_DO_FCALL;
                   2552:                } else {
                   2553:                        opline->extended_value = ZEND_DO_FCALL_BY_NAME;
                   2554:                }
                   2555:        }
                   2556:        opline->opcode = op;
1.1.1.2 ! misho    2557:        SET_NODE(opline->op1, param);
        !          2558:        opline->op2.opline_num = offset;
1.1       misho    2559:        SET_UNUSED(opline->op2);
                   2560: }
                   2561: /* }}} */
                   2562: 
                   2563: static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
                   2564: {
                   2565:        zend_op *opline;
                   2566: 
                   2567:        if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
                   2568:                return (switch_entry->cond.op_type == IS_UNUSED);
                   2569:        }
                   2570: 
                   2571:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2572: 
                   2573:        opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
1.1.1.2 ! misho    2574:        SET_NODE(opline->op1, &switch_entry->cond);
1.1       misho    2575:        SET_UNUSED(opline->op2);
                   2576:        opline->extended_value = 0;
                   2577:        return 0;
                   2578: }
                   2579: /* }}} */
                   2580: 
                   2581: static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
                   2582: {
                   2583:        zend_op *opline;
                   2584: 
                   2585:        /* If we reach the seperator then stop applying the stack */
1.1.1.2 ! misho    2586:        if (foreach_copy->result_type == IS_UNUSED && foreach_copy->op1_type == IS_UNUSED) {
1.1       misho    2587:                return 1;
                   2588:        }
                   2589: 
                   2590:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2591: 
1.1.1.2 ! misho    2592:        opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
        !          2593:        COPY_NODE(opline->op1, foreach_copy->result);
1.1       misho    2594:        SET_UNUSED(opline->op2);
                   2595:        opline->extended_value = 1;
                   2596: 
1.1.1.2 ! misho    2597:        if (foreach_copy->op1_type != IS_UNUSED) {
1.1       misho    2598:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2599: 
1.1.1.2 ! misho    2600:                opline->opcode = (foreach_copy->op1_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
        !          2601:                COPY_NODE(opline->op1, foreach_copy->op1);
1.1       misho    2602:                SET_UNUSED(opline->op2);
                   2603:                opline->extended_value = 0;
                   2604:        }
                   2605: 
                   2606:        return 0;
                   2607: }
                   2608: /* }}} */
                   2609: 
                   2610: void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
                   2611: {
                   2612:        zend_op *opline;
                   2613:        int start_op_number, end_op_number;
                   2614: 
                   2615:        if (do_end_vparse) {
1.1.1.2 ! misho    2616:                if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(expr)) {
1.1       misho    2617:                        zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
                   2618:                } else {
                   2619:                        zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
                   2620:                }
                   2621:        }
                   2622: 
                   2623:        start_op_number = get_next_op_number(CG(active_op_array));
                   2624: 
                   2625: #ifdef ZTS
                   2626:        zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
                   2627:        zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
                   2628: #else
                   2629:        zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
                   2630:        zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
                   2631: #endif
                   2632: 
                   2633:        end_op_number = get_next_op_number(CG(active_op_array));
                   2634:        while (start_op_number < end_op_number) {
1.1.1.2 ! misho    2635:                CG(active_op_array)->opcodes[start_op_number].extended_value |= EXT_TYPE_FREE_ON_RETURN;
1.1       misho    2636:                start_op_number++;
                   2637:        }
                   2638: 
                   2639:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2640: 
1.1.1.2 ! misho    2641:        opline->opcode = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) ? ZEND_RETURN_BY_REF : ZEND_RETURN;
1.1       misho    2642: 
                   2643:        if (expr) {
1.1.1.2 ! misho    2644:                SET_NODE(opline->op1, expr);
1.1       misho    2645: 
                   2646:                if (do_end_vparse && zend_is_function_or_method_call(expr)) {
                   2647:                        opline->extended_value = ZEND_RETURNS_FUNCTION;
                   2648:                }
                   2649:        } else {
1.1.1.2 ! misho    2650:                opline->op1_type = IS_CONST;
        !          2651:                LITERAL_NULL(opline->op1);
1.1       misho    2652:        }
                   2653: 
                   2654:        SET_UNUSED(opline->op2);
                   2655: }
                   2656: /* }}} */
                   2657: 
                   2658: static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
                   2659: {
                   2660:        int try_catch_offset = CG(active_op_array)->last_try_catch++;
                   2661: 
                   2662:        CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch);
                   2663:        CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
                   2664:        return try_catch_offset;
                   2665: }
                   2666: /* }}} */
                   2667: 
                   2668: static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
                   2669: {
                   2670:        CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
                   2671: }
                   2672: /* }}} */
                   2673: 
                   2674: void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
                   2675: {
1.1.1.2 ! misho    2676:        open_parentheses->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    2677: }
                   2678: /* }}} */
                   2679: 
                   2680: void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{ */
                   2681: {
                   2682:        int jmp_op_number = get_next_op_number(CG(active_op_array));
                   2683:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2684:        zend_llist jmp_list;
                   2685:        zend_llist *jmp_list_ptr;
                   2686: 
                   2687:        opline->opcode = ZEND_JMP;
                   2688:        SET_UNUSED(opline->op1);
                   2689:        SET_UNUSED(opline->op2);
                   2690:        /* save for backpatching */
                   2691: 
                   2692:        zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
                   2693:        zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
                   2694:        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
                   2695:        zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
                   2696: 
1.1.1.2 ! misho    2697:        zend_add_catch_element(try_token->u.op.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
1.1       misho    2698: }
                   2699: /* }}} */
                   2700: 
                   2701: void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
                   2702: {
                   2703:        CG(active_op_array)->last--;
                   2704:        zend_do_if_end(TSRMLS_C);
1.1.1.2 ! misho    2705:        if (last_additional_catch->u.op.opline_num == -1) {
        !          2706:                CG(active_op_array)->opcodes[first_catch->u.op.opline_num].result.num = 1;
        !          2707:                CG(active_op_array)->opcodes[first_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1.1       misho    2708:        } else {
1.1.1.2 ! misho    2709:                CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].result.num = 1;
        !          2710:                CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1.1       misho    2711:        }
                   2712:        DEC_BPC(CG(active_op_array));
                   2713: }
                   2714: /* }}} */
                   2715: 
                   2716: void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
                   2717: {
1.1.1.2 ! misho    2718:        try_token->u.op.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
1.1       misho    2719:        INC_BPC(CG(active_op_array));
                   2720: }
                   2721: /* }}} */
                   2722: 
1.1.1.2 ! misho    2723: void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
1.1       misho    2724: {
                   2725:        long catch_op_number;
                   2726:        zend_op *opline;
                   2727:        znode catch_class;
                   2728: 
1.1.1.2 ! misho    2729:        if (class_name->op_type == IS_CONST &&
        !          2730:            ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
        !          2731:                zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
        !          2732:                catch_class = *class_name;
        !          2733:        } else {
        !          2734:                zend_error(E_COMPILE_ERROR, "Bad class name in the catch statement");
1.1       misho    2735:        }
                   2736: 
1.1.1.2 ! misho    2737:        catch_op_number = get_next_op_number(CG(active_op_array));
1.1       misho    2738:        if (first_catch) {
1.1.1.2 ! misho    2739:                first_catch->u.op.opline_num = catch_op_number;
1.1       misho    2740:        }
                   2741: 
                   2742:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2743:        opline->opcode = ZEND_CATCH;
1.1.1.2 ! misho    2744:        opline->op1_type = IS_CONST;
        !          2745:        opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &catch_class.u.constant TSRMLS_CC);
        !          2746:        opline->op2_type = IS_CV;
        !          2747:        opline->op2.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len, 0 TSRMLS_CC);
        !          2748:        Z_STRVAL(catch_var->u.constant) = (char*)CG(active_op_array)->vars[opline->op2.var].name;
        !          2749:        opline->result.num = 0; /* 1 means it's the last catch in the block */
1.1       misho    2750: 
1.1.1.2 ! misho    2751:        try_token->u.op.opline_num = catch_op_number;
1.1       misho    2752: }
                   2753: /* }}} */
                   2754: 
                   2755: void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */
                   2756: {
                   2757:        int jmp_op_number = get_next_op_number(CG(active_op_array));
                   2758:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2759:        zend_llist *jmp_list_ptr;
                   2760: 
                   2761:        opline->opcode = ZEND_JMP;
                   2762:        SET_UNUSED(opline->op1);
                   2763:        SET_UNUSED(opline->op2);
                   2764:        /* save for backpatching */
                   2765: 
                   2766:        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
                   2767:        zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
                   2768: 
1.1.1.2 ! misho    2769:        CG(active_op_array)->opcodes[try_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1.1       misho    2770: }
                   2771: /* }}} */
                   2772: 
                   2773: void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
                   2774: {
                   2775:        zend_op *opline;
                   2776: 
                   2777:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   2778:        opline->opcode = ZEND_THROW;
1.1.1.2 ! misho    2779:        SET_NODE(opline->op1, expr);
1.1       misho    2780:        SET_UNUSED(opline->op2);
                   2781: }
                   2782: /* }}} */
                   2783: 
                   2784: ZEND_API void function_add_ref(zend_function *function) /* {{{ */
                   2785: {
                   2786:        if (function->type == ZEND_USER_FUNCTION) {
                   2787:                zend_op_array *op_array = &function->op_array;
                   2788: 
                   2789:                (*op_array->refcount)++;
                   2790:                if (op_array->static_variables) {
                   2791:                        HashTable *static_variables = op_array->static_variables;
                   2792:                        zval *tmp_zval;
                   2793: 
                   2794:                        ALLOC_HASHTABLE(op_array->static_variables);
                   2795:                        zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
                   2796:                        zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
                   2797:                }
1.1.1.2 ! misho    2798:                op_array->run_time_cache = NULL;
1.1       misho    2799:        }
                   2800: }
                   2801: /* }}} */
                   2802: 
                   2803: static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
                   2804: {
1.1.1.2 ! misho    2805:        zend_function *function, *new_function;
1.1       misho    2806: 
                   2807:        if (!ce->parent) {
                   2808:                return;
                   2809:        }
                   2810: 
                   2811:        /* You cannot change create_object */
                   2812:        ce->create_object = ce->parent->create_object;
                   2813: 
                   2814:        /* Inherit special functions if needed */
                   2815:        if (!ce->get_iterator) {
                   2816:                ce->get_iterator = ce->parent->get_iterator;
                   2817:        }
                   2818:        if (!ce->iterator_funcs.funcs) {
                   2819:                ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
                   2820:        }
                   2821:        if (!ce->__get) {
                   2822:                ce->__get   = ce->parent->__get;
                   2823:        }
                   2824:        if (!ce->__set) {
                   2825:                ce->__set = ce->parent->__set;
                   2826:        }
                   2827:        if (!ce->__unset) {
                   2828:                ce->__unset = ce->parent->__unset;
                   2829:        }
                   2830:        if (!ce->__isset) {
                   2831:                ce->__isset = ce->parent->__isset;
                   2832:        }
                   2833:        if (!ce->__call) {
                   2834:                ce->__call = ce->parent->__call;
                   2835:        }
                   2836:        if (!ce->__callstatic) {
                   2837:                ce->__callstatic = ce->parent->__callstatic;
                   2838:        }
                   2839:        if (!ce->__tostring) {
                   2840:                ce->__tostring = ce->parent->__tostring;
                   2841:        }
                   2842:        if (!ce->clone) {
                   2843:                ce->clone = ce->parent->clone;
                   2844:        }
                   2845:        if(!ce->serialize) {
                   2846:                ce->serialize = ce->parent->serialize;
                   2847:        }
                   2848:        if(!ce->unserialize) {
                   2849:                ce->unserialize = ce->parent->unserialize;
                   2850:        }
                   2851:        if (!ce->destructor) {
                   2852:                ce->destructor   = ce->parent->destructor;
                   2853:        }
                   2854:        if (ce->constructor) {
                   2855:                if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
                   2856:                        zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
                   2857:                                ce->parent->name, ce->parent->constructor->common.function_name,
                   2858:                                ce->name, ce->constructor->common.function_name
                   2859:                                );
                   2860:                }
                   2861:                return;
                   2862:        }
                   2863: 
                   2864:        if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
                   2865:                /* inherit parent's constructor */
1.1.1.2 ! misho    2866:                zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), (void**)&new_function);
        !          2867:                function_add_ref(new_function);
1.1       misho    2868:        } else {
                   2869:                /* Don't inherit the old style constructor if we already have the new style constructor */
                   2870:                char *lc_class_name;
                   2871:                char *lc_parent_class_name;
                   2872: 
                   2873:                lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
                   2874:                if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
                   2875:                        lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
                   2876:                        if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) && 
                   2877:                                        zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
                   2878:                                if (function->common.fn_flags & ZEND_ACC_CTOR) {
                   2879:                                        /* inherit parent's constructor */
1.1.1.2 ! misho    2880:                                        zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), (void**)&new_function);
        !          2881:                                        function_add_ref(new_function);
1.1       misho    2882:                                }
                   2883:                        }
                   2884:                        efree(lc_parent_class_name);
                   2885:                }
                   2886:                efree(lc_class_name);
                   2887:        }
                   2888:        ce->constructor = ce->parent->constructor;
                   2889: }
                   2890: /* }}} */
                   2891: 
                   2892: char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
                   2893: {
                   2894:        if (fn_flags & ZEND_ACC_PRIVATE) {
                   2895:                return "private";
                   2896:        }
                   2897:        if (fn_flags & ZEND_ACC_PROTECTED) {
                   2898:                return "protected";
                   2899:        }
                   2900:        if (fn_flags & ZEND_ACC_PUBLIC) {
                   2901:                return "public";
                   2902:        }
                   2903:        return "";
                   2904: }
                   2905: /* }}} */
                   2906: 
                   2907: static void do_inherit_method(zend_function *function) /* {{{ */
                   2908: {
                   2909:        /* The class entry of the derived function intentionally remains the same
                   2910:         * as that of the parent class.  That allows us to know in which context
                   2911:         * we're running, and handle private method calls properly.
                   2912:         */
                   2913:        function_add_ref(function);
                   2914: }
                   2915: /* }}} */
                   2916: 
                   2917: static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
                   2918: {
                   2919:        zend_uint i;
                   2920: 
                   2921:        /* If it's a user function then arg_info == NULL means we don't have any parameters but
                   2922:         * we still need to do the arg number checks.  We are only willing to ignore this for internal
                   2923:         * functions because extensions don't always define arg_info.
                   2924:         */
                   2925:        if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
                   2926:                return 1;
                   2927:        }
                   2928: 
1.1.1.2 ! misho    2929:        /* Checks for constructors only if they are declared in an interface,
        !          2930:         * or explicitly marked as abstract
        !          2931:         */
        !          2932:        if ((fe->common.fn_flags & ZEND_ACC_CTOR)
        !          2933:                && ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
        !          2934:                        && (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) {
1.1       misho    2935:                return 1;
                   2936:        }
                   2937: 
                   2938:        /* check number of arguments */
                   2939:        if (proto->common.required_num_args < fe->common.required_num_args
                   2940:                || proto->common.num_args > fe->common.num_args) {
                   2941:                return 0;
                   2942:        }
                   2943: 
                   2944:        if (fe->common.type != ZEND_USER_FUNCTION
1.1.1.2 ! misho    2945:                && (proto->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) != 0
        !          2946:                && (fe->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) == 0) {
1.1       misho    2947:                return 0;
                   2948:        }
                   2949: 
                   2950:        /* by-ref constraints on return values are covariant */
1.1.1.2 ! misho    2951:        if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
        !          2952:                && !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
1.1       misho    2953:                return 0;
                   2954:        }
                   2955: 
                   2956:        for (i=0; i < proto->common.num_args; i++) {
                   2957:                if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)) {
                   2958:                        /* Only one has a type hint and the other one doesn't */
                   2959:                        return 0;
                   2960:                }
                   2961: 
1.1.1.2 ! misho    2962:                if (fe->common.arg_info[i].class_name) {
        !          2963:                        const char *fe_class_name, *proto_class_name;
        !          2964:                        zend_uint fe_class_name_len, proto_class_name_len;
        !          2965: 
        !          2966:                        if (!strcasecmp(fe->common.arg_info[i].class_name, "parent") && proto->common.scope) {
        !          2967:                                fe_class_name = proto->common.scope->name;
        !          2968:                                fe_class_name_len = proto->common.scope->name_length;
        !          2969:                        } else if (!strcasecmp(fe->common.arg_info[i].class_name, "self") && fe->common.scope) {
        !          2970:                                fe_class_name = fe->common.scope->name;
        !          2971:                                fe_class_name_len = fe->common.scope->name_length;
        !          2972:                        } else {
        !          2973:                                fe_class_name = fe->common.arg_info[i].class_name;
        !          2974:                                fe_class_name_len = fe->common.arg_info[i].class_name_len;
        !          2975:                        }
        !          2976: 
        !          2977:                        if (!strcasecmp(proto->common.arg_info[i].class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
        !          2978:                                proto_class_name = proto->common.scope->parent->name;
        !          2979:                                proto_class_name_len = proto->common.scope->parent->name_length;
        !          2980:                        } else if (!strcasecmp(proto->common.arg_info[i].class_name, "self") && proto->common.scope) {
        !          2981:                                proto_class_name = proto->common.scope->name;
        !          2982:                                proto_class_name_len = proto->common.scope->name_length;
        !          2983:                        } else {
        !          2984:                                proto_class_name = proto->common.arg_info[i].class_name;
        !          2985:                                proto_class_name_len = proto->common.arg_info[i].class_name_len;
        !          2986:                        }
        !          2987: 
        !          2988:                        if (strcasecmp(fe_class_name, proto_class_name)!=0) {
        !          2989:                                const char *colon;
        !          2990: 
        !          2991:                                if (fe->common.type != ZEND_USER_FUNCTION) {
1.1       misho    2992:                                        return 0;
1.1.1.2 ! misho    2993:                            } else if (strchr(proto_class_name, '\\') != NULL ||
        !          2994:                                                (colon = zend_memrchr(fe_class_name, '\\', fe_class_name_len)) == NULL ||
        !          2995:                                                strcasecmp(colon+1, proto_class_name) != 0) {
        !          2996:                                        zend_class_entry **fe_ce, **proto_ce;
        !          2997:                                        int found, found2;
        !          2998: 
        !          2999:                                        found = zend_lookup_class(fe_class_name, fe_class_name_len, &fe_ce TSRMLS_CC);
        !          3000:                                        found2 = zend_lookup_class(proto_class_name, proto_class_name_len, &proto_ce TSRMLS_CC);
        !          3001: 
        !          3002:                                        /* Check for class alias */
        !          3003:                                        if (found != SUCCESS || found2 != SUCCESS ||
        !          3004:                                                        (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
        !          3005:                                                        (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
        !          3006:                                                        *fe_ce != *proto_ce) {
        !          3007:                                                return 0;
        !          3008:                                        }
1.1       misho    3009:                                }
1.1.1.2 ! misho    3010:                        } 
        !          3011:                } 
        !          3012:                if (fe->common.arg_info[i].type_hint != proto->common.arg_info[i].type_hint) {
        !          3013:                        /* Incompatible type hint */
1.1       misho    3014:                        return 0;
                   3015:                }
                   3016: 
                   3017:                /* by-ref constraints on arguments are invariant */
                   3018:                if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
                   3019:                        return 0;
                   3020:                }
                   3021:        }
                   3022: 
1.1.1.2 ! misho    3023:        if (proto->common.fn_flags & ZEND_ACC_PASS_REST_BY_REFERENCE) {
1.1       misho    3024:                for (i=proto->common.num_args; i < fe->common.num_args; i++) {
                   3025:                        if (!fe->common.arg_info[i].pass_by_reference) {
                   3026:                                return 0;
                   3027:                        }
                   3028:                }
                   3029:        }
                   3030:        return 1;
                   3031: }
                   3032: /* }}} */
                   3033: 
1.1.1.2 ! misho    3034: #define REALLOC_BUF_IF_EXCEED(buf, offset, length, size) \
        !          3035:        if (UNEXPECTED(offset - buf + size >= length)) {        \
        !          3036:                length += size + 1;                             \
        !          3037:                buf = erealloc(buf, length);            \
        !          3038:        }
        !          3039: 
        !          3040: static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */ 
1.1       misho    3041: {
1.1.1.2 ! misho    3042:        char *offset, *buf;
        !          3043:        zend_uint length = 1024;
1.1       misho    3044: 
1.1.1.2 ! misho    3045:        offset = buf = (char *)emalloc(length * sizeof(char));
        !          3046:        if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
        !          3047:                *(offset++) = '&';
        !          3048:                *(offset++) = ' ';
        !          3049:        }
        !          3050: 
        !          3051:        if (fptr->common.scope) {
        !          3052:                memcpy(offset, fptr->common.scope->name, fptr->common.scope->name_length);
        !          3053:                offset += fptr->common.scope->name_length;
        !          3054:                *(offset++) = ':';
        !          3055:                *(offset++) = ':';
        !          3056:        }
        !          3057:        
        !          3058:        {
        !          3059:                size_t name_len = strlen(fptr->common.function_name);
        !          3060:                REALLOC_BUF_IF_EXCEED(buf, offset, length, name_len);
        !          3061:                memcpy(offset, fptr->common.function_name, name_len);
        !          3062:                offset += name_len;
        !          3063:        }
        !          3064: 
        !          3065:        *(offset++) = '(';
        !          3066:        if (fptr->common.arg_info) {
        !          3067:                zend_uint i, required;
        !          3068:                zend_arg_info *arg_info = fptr->common.arg_info;
        !          3069: 
        !          3070:                required = fptr->common.required_num_args;
        !          3071:                for (i = 0; i < fptr->common.num_args;) {
        !          3072:                        if (arg_info->class_name) {
        !          3073:                                const char *class_name;
        !          3074:                                zend_uint class_name_len;
        !          3075:                                if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope ) {
        !          3076:                                        class_name = fptr->common.scope->name;
        !          3077:                                        class_name_len = fptr->common.scope->name_length;
        !          3078:                                } else if (!strcasecmp(arg_info->class_name, "parent") && fptr->common.scope->parent) {
        !          3079:                                        class_name = fptr->common.scope->parent->name;
        !          3080:                                        class_name_len = fptr->common.scope->parent->name_length;
        !          3081:                                } else {
        !          3082:                                        class_name = arg_info->class_name;
        !          3083:                                        class_name_len = arg_info->class_name_len;
        !          3084:                                }
        !          3085:                                REALLOC_BUF_IF_EXCEED(buf, offset, length, class_name_len);
        !          3086:                                memcpy(offset, class_name, class_name_len);
        !          3087:                                offset += class_name_len;
        !          3088:                                *(offset++) = ' ';
        !          3089:                        } else if (arg_info->type_hint) {
        !          3090:                                zend_uint type_name_len;
        !          3091:                                char *type_name = zend_get_type_by_const(arg_info->type_hint);
        !          3092:                                type_name_len = strlen(type_name);
        !          3093:                                REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len);
        !          3094:                                memcpy(offset, type_name, type_name_len);
        !          3095:                                offset += type_name_len;
        !          3096:                                *(offset++) = ' ';
        !          3097:                        }
        !          3098:                                
        !          3099:                        if (arg_info->pass_by_reference) {
        !          3100:                                *(offset++) = '&';
        !          3101:                        }
        !          3102:                        *(offset++) = '$';
        !          3103: 
        !          3104:                        if (arg_info->name) {
        !          3105:                                REALLOC_BUF_IF_EXCEED(buf, offset, length, arg_info->name_len);
        !          3106:                                memcpy(offset, arg_info->name, arg_info->name_len);
        !          3107:                                offset += arg_info->name_len;
        !          3108:                        } else {
        !          3109:                                zend_uint idx = i;
        !          3110:                                memcpy(offset, "param", 5);
        !          3111:                                offset += 5;
        !          3112:                                do {
        !          3113:                                        *(offset++) = (char) (idx % 10) + '0';
        !          3114:                                        idx /= 10;
        !          3115:                                } while (idx > 0);
        !          3116:                        }
        !          3117:                        if (i >= required) {
        !          3118:                                *(offset++) = ' ';
        !          3119:                                *(offset++) = '=';
        !          3120:                                *(offset++) = ' ';
        !          3121:                                if (fptr->type == ZEND_USER_FUNCTION) {
        !          3122:                                        zend_op *precv = NULL;
        !          3123:                                        {
        !          3124:                                                zend_uint idx  = i;
        !          3125:                                                zend_op *op = ((zend_op_array *)fptr)->opcodes;
        !          3126:                                                zend_op *end = op + ((zend_op_array *)fptr)->last;
        !          3127: 
        !          3128:                                                ++idx;
        !          3129:                                                while (op < end) {
        !          3130:                                                        if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
        !          3131:                                                                        && op->op1.num == (long)idx)
        !          3132:                                                        {
        !          3133:                                                                precv = op;
        !          3134:                                                        }
        !          3135:                                                        ++op;
        !          3136:                                                }
        !          3137:                                        }
        !          3138:                                        if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
        !          3139:                                                zval *zv, zv_copy;
        !          3140:                                                int use_copy;
        !          3141:                                                ALLOC_ZVAL(zv);
        !          3142:                                                *zv = *precv->op2.zv;
        !          3143:                                                zval_copy_ctor(zv);
        !          3144:                                                INIT_PZVAL(zv);
        !          3145:                                                zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
        !          3146:                                                if (Z_TYPE_P(zv) == IS_BOOL) {
        !          3147:                                                        if (Z_LVAL_P(zv)) {
        !          3148:                                                                memcpy(offset, "true", 4);
        !          3149:                                                                offset += 4;
        !          3150:                                                        } else {
        !          3151:                                                                memcpy(offset, "false", 5);
        !          3152:                                                                offset += 5;
        !          3153:                                                        }
        !          3154:                                                } else if (Z_TYPE_P(zv) == IS_NULL) {
        !          3155:                                                        memcpy(offset, "NULL", 4);
        !          3156:                                                        offset += 4;
        !          3157:                                                } else if (Z_TYPE_P(zv) == IS_STRING) {
        !          3158:                                                        *(offset++) = '\'';
        !          3159:                                                        REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
        !          3160:                                                        memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
        !          3161:                                                        offset += MIN(Z_STRLEN_P(zv), 10);
        !          3162:                                                        if (Z_STRLEN_P(zv) > 10) {
        !          3163:                                                                *(offset++) = '.';
        !          3164:                                                                *(offset++) = '.';
        !          3165:                                                                *(offset++) = '.';
        !          3166:                                                        }
        !          3167:                                                        *(offset++) = '\'';
        !          3168:                                                } else if (Z_TYPE_P(zv) == IS_ARRAY) {
        !          3169:                                                        memcpy(offset, "Array", 5);
        !          3170:                                                        offset += 5;
        !          3171:                                                } else {
        !          3172:                                                        zend_make_printable_zval(zv, &zv_copy, &use_copy);
        !          3173:                                                        REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN(zv_copy));
        !          3174:                                                        memcpy(offset, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
        !          3175:                                                        offset += Z_STRLEN(zv_copy);
        !          3176:                                                        if (use_copy) {
        !          3177:                                                                zval_dtor(&zv_copy);
        !          3178:                                                        }
        !          3179:                                                }
        !          3180:                                                zval_ptr_dtor(&zv);
        !          3181:                                        }
        !          3182:                                } else {
        !          3183:                                        memcpy(offset, "NULL", 4);
        !          3184:                                        offset += 4;
        !          3185:                                }
        !          3186:                        }
        !          3187: 
        !          3188:                        if (++i < fptr->common.num_args) {
        !          3189:                                *(offset++) = ',';
        !          3190:                                *(offset++) = ' ';
        !          3191:                        }
        !          3192:                        arg_info++;
        !          3193:                        REALLOC_BUF_IF_EXCEED(buf, offset, length, 32);
1.1       misho    3194:                }
                   3195:        }
1.1.1.2 ! misho    3196:        *(offset++) = ')';
        !          3197:        *offset = '\0';
        !          3198: 
        !          3199:        return buf;
        !          3200: } 
        !          3201: /* }}} */
        !          3202: 
        !          3203: static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */
        !          3204: {
        !          3205:        zend_uint child_flags;
        !          3206:        zend_uint parent_flags = parent->common.fn_flags;
1.1       misho    3207: 
                   3208:        if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
                   3209:                && parent->common.fn_flags & ZEND_ACC_ABSTRACT
                   3210:                && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
                   3211:                && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
                   3212:                zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)", 
                   3213:                        parent->common.scope->name,
                   3214:                        child->common.function_name,
                   3215:                        child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
                   3216:        }
                   3217: 
                   3218:        if (parent_flags & ZEND_ACC_FINAL) {
                   3219:                zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
                   3220:        }
                   3221: 
                   3222:        child_flags     = child->common.fn_flags;
                   3223:        /* You cannot change from static to non static and vice versa.
                   3224:         */
                   3225:        if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
                   3226:                if (child->common.fn_flags & ZEND_ACC_STATIC) {
                   3227:                        zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
                   3228:                } else {
                   3229:                        zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
                   3230:                }
                   3231:        }
                   3232: 
                   3233:        /* Disallow making an inherited method abstract. */
                   3234:        if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
                   3235:                zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
                   3236:        }
                   3237: 
                   3238:        if (parent_flags & ZEND_ACC_CHANGED) {
                   3239:                child->common.fn_flags |= ZEND_ACC_CHANGED;
                   3240:        } else {
                   3241:                /* Prevent derived classes from restricting access that was available in parent classes
                   3242:                 */
                   3243:                if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
                   3244:                        zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
                   3245:                } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
                   3246:                        && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
                   3247:                        child->common.fn_flags |= ZEND_ACC_CHANGED;
                   3248:                }
                   3249:        }
                   3250: 
                   3251:        if (parent_flags & ZEND_ACC_PRIVATE) {
                   3252:                child->common.prototype = NULL;         
                   3253:        } else if (parent_flags & ZEND_ACC_ABSTRACT) {
                   3254:                child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
                   3255:                child->common.prototype = parent;
                   3256:        } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
                   3257:                /* ctors only have a prototype if it comes from an interface */
                   3258:                child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
                   3259:        }
                   3260: 
                   3261:        if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
                   3262:                if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
1.1.1.2 ! misho    3263:                        zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_get_function_declaration(child->common.prototype TSRMLS_CC)); 
1.1       misho    3264:                }
                   3265:        } else if (EG(error_reporting) & E_STRICT || EG(user_error_handler)) { /* Check E_STRICT (or custom error handler) before the check so that we save some time */
                   3266:                if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
1.1.1.2 ! misho    3267:                        char *method_prototype = zend_get_function_declaration(child->common.prototype TSRMLS_CC);
        !          3268:                        zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, method_prototype); 
        !          3269:                        efree(method_prototype);
1.1       misho    3270:                }
                   3271:        }
1.1.1.2 ! misho    3272: }
        !          3273: /* }}} */
        !          3274: 
        !          3275: static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
        !          3276: {
        !          3277:        zend_uint parent_flags = parent->common.fn_flags;
        !          3278:        zend_function *child;
        !          3279:        TSRMLS_FETCH();
1.1       misho    3280: 
1.1.1.2 ! misho    3281:        if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
        !          3282:                if (parent_flags & (ZEND_ACC_ABSTRACT)) {
        !          3283:                        child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
        !          3284:                }
        !          3285:                return 1; /* method doesn't exist in child, copy from parent */
        !          3286:        }
        !          3287:        
        !          3288:        do_inheritance_check_on_method(child, parent TSRMLS_CC);
        !          3289:        
1.1       misho    3290:        return 0;
                   3291: }
                   3292: /* }}} */
                   3293: 
                   3294: static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce) /* {{{ */
                   3295: {
                   3296:        zend_property_info *child_info;
                   3297:        zend_class_entry *parent_ce = ce->parent;
                   3298: 
                   3299:        if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
                   3300:                if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
                   3301:                        child_info->flags |= ZEND_ACC_CHANGED;
                   3302:                } else {
                   3303:                        zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
                   3304:                        if(ce->type & ZEND_INTERNAL_CLASS) {
                   3305:                                zend_duplicate_property_info_internal(child_info);
                   3306:                        } else {
                   3307:                                zend_duplicate_property_info(child_info);
                   3308:                        }
                   3309:                        child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
                   3310:                        child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
                   3311:                }
                   3312:                return 0; /* don't copy access information to child */
                   3313:        }
                   3314: 
                   3315:        if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
                   3316:                if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
                   3317:                        zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
                   3318:                                (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
                   3319:                                (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
                   3320:                                
                   3321:                }
                   3322: 
                   3323:                if(parent_info->flags & ZEND_ACC_CHANGED) {
                   3324:                        child_info->flags |= ZEND_ACC_CHANGED;
                   3325:                }
                   3326: 
                   3327:                if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
                   3328:                        zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
1.1.1.2 ! misho    3329:                } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
        !          3330:                        Z_DELREF_P(ce->default_properties_table[parent_info->offset]);
        !          3331:                        ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
        !          3332:                        ce->default_properties_table[child_info->offset] = NULL;
        !          3333:                        child_info->offset = parent_info->offset;
1.1       misho    3334:                }
                   3335:                return 0;       /* Don't copy from parent */
                   3336:        } else {
                   3337:                return 1;       /* Copy from parent */
                   3338:        }
                   3339: }
                   3340: /* }}} */
                   3341: 
                   3342: static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
                   3343: {
                   3344:        if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
                   3345:                zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
                   3346:        }
                   3347:        if (ce == iface) {
                   3348:                zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
                   3349:        }
                   3350: }
                   3351: /* }}} */
                   3352: 
                   3353: ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
                   3354: {
                   3355:        /* expects interface to be contained in ce's interface list already */
                   3356:        zend_uint i, ce_num, if_num = iface->num_interfaces;
                   3357:        zend_class_entry *entry;
                   3358: 
                   3359:        if (if_num==0) {
                   3360:                return;
                   3361:        }
                   3362:        ce_num = ce->num_interfaces;
                   3363: 
                   3364:        if (ce->type == ZEND_INTERNAL_CLASS) {
                   3365:                ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
                   3366:        } else {
                   3367:                ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
                   3368:        }
                   3369: 
                   3370:        /* Inherit the interfaces, only if they're not already inherited by the class */
                   3371:        while (if_num--) {
                   3372:                entry = iface->interfaces[if_num];
                   3373:                for (i = 0; i < ce_num; i++) {
                   3374:                        if (ce->interfaces[i] == entry) {
                   3375:                                break;
                   3376:                        }
                   3377:                }
                   3378:                if (i == ce_num) {
                   3379:                        ce->interfaces[ce->num_interfaces++] = entry;
                   3380:                }
                   3381:        }
                   3382: 
                   3383:        /* and now call the implementing handlers */
                   3384:        while (ce_num < ce->num_interfaces) {
                   3385:                do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
                   3386:        }
                   3387: }
                   3388: /* }}} */
                   3389: 
1.1.1.2 ! misho    3390: #ifdef ZTS
        !          3391: static void zval_internal_ctor(zval **p) /* {{{ */
1.1       misho    3392: {
1.1.1.2 ! misho    3393:        zval *orig_ptr = *p;
1.1       misho    3394: 
1.1.1.2 ! misho    3395:        ALLOC_ZVAL(*p);
        !          3396:        MAKE_COPY_ZVAL(&orig_ptr, *p);
1.1       misho    3397: }
                   3398: /* }}} */
                   3399: 
1.1.1.2 ! misho    3400: # define zval_property_ctor(parent_ce, ce) \
        !          3401:        ((void (*)(void *)) (((parent_ce)->type != (ce)->type) ? zval_internal_ctor : zval_add_ref))
        !          3402: #else
        !          3403: # define zval_property_ctor(parent_ce, ce) \
        !          3404:        ((void (*)(void *)) zval_add_ref)
        !          3405: #endif
1.1       misho    3406: 
                   3407: ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
                   3408: {
1.1.1.2 ! misho    3409:        zend_property_info *property_info;
        !          3410: 
1.1       misho    3411:        if ((ce->ce_flags & ZEND_ACC_INTERFACE)
                   3412:                && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
                   3413:                zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
                   3414:        }
                   3415:        if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
                   3416:                zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
                   3417:        }
                   3418: 
                   3419:        ce->parent = parent_ce;
                   3420:        /* Copy serialize/unserialize callbacks */
                   3421:        if (!ce->serialize) {
                   3422:                ce->serialize   = parent_ce->serialize;
                   3423:        }
                   3424:        if (!ce->unserialize) {
                   3425:                ce->unserialize = parent_ce->unserialize;
                   3426:        }
                   3427: 
                   3428:        /* Inherit interfaces */
                   3429:        zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
                   3430: 
                   3431:        /* Inherit properties */
1.1.1.2 ! misho    3432:        if (parent_ce->default_properties_count) {
        !          3433:                int i = ce->default_properties_count + parent_ce->default_properties_count;
        !          3434: 
        !          3435:                ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
        !          3436:                if (ce->default_properties_count) {
        !          3437:                        while (i-- > parent_ce->default_properties_count) {
        !          3438:                                ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
        !          3439:                        }
        !          3440:                }
        !          3441:                for (i = 0; i < parent_ce->default_properties_count; i++) {
        !          3442:                        ce->default_properties_table[i] = parent_ce->default_properties_table[i];
        !          3443:                        if (ce->default_properties_table[i]) {
        !          3444: #ifdef ZTS
        !          3445:                                if (parent_ce->type != ce->type) {
        !          3446:                                        zval *p;
        !          3447: 
        !          3448:                                        ALLOC_ZVAL(p);
        !          3449:                                        MAKE_COPY_ZVAL(&ce->default_properties_table[i], p);
        !          3450:                                        ce->default_properties_table[i] = p;
        !          3451:                                } else {
        !          3452:                                        Z_ADDREF_P(ce->default_properties_table[i]);
        !          3453:                                }
        !          3454: #else
        !          3455:                                Z_ADDREF_P(ce->default_properties_table[i]);
        !          3456: #endif
        !          3457:                        }
        !          3458:                }
        !          3459:                ce->default_properties_count += parent_ce->default_properties_count;
        !          3460:        }
        !          3461: 
1.1       misho    3462:        if (parent_ce->type != ce->type) {
                   3463:                /* User class extends internal class */
                   3464:                zend_update_class_constants(parent_ce  TSRMLS_CC);
1.1.1.2 ! misho    3465:                if (parent_ce->default_static_members_count) {
        !          3466:                        int i = ce->default_static_members_count + parent_ce->default_static_members_count;
        !          3467: 
        !          3468:                        ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
        !          3469:                        if (ce->default_static_members_count) {
        !          3470:                                while (i-- > parent_ce->default_static_members_count) {
        !          3471:                                        ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
        !          3472:                                }
        !          3473:                        }
        !          3474:                        for (i = 0; i < parent_ce->default_static_members_count; i++) {
        !          3475:                                SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
        !          3476:                                ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
        !          3477:                                Z_ADDREF_P(ce->default_static_members_table[i]);
        !          3478:                        }
        !          3479:                        ce->default_static_members_count += parent_ce->default_static_members_count;
        !          3480:                        ce->static_members_table = ce->default_static_members_table;
        !          3481:                }
        !          3482:        } else {
        !          3483:                if (parent_ce->default_static_members_count) {
        !          3484:                        int i = ce->default_static_members_count + parent_ce->default_static_members_count;
        !          3485: 
        !          3486:                        ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
        !          3487:                        if (ce->default_static_members_count) {
        !          3488:                                while (i-- > parent_ce->default_static_members_count) {
        !          3489:                                        ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
        !          3490:                                }
        !          3491:                        }
        !          3492:                        for (i = 0; i < parent_ce->default_static_members_count; i++) {
        !          3493:                                SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
        !          3494:                                ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
        !          3495:                                Z_ADDREF_P(ce->default_static_members_table[i]);
        !          3496:                        }
        !          3497:                        ce->default_static_members_count += parent_ce->default_static_members_count;
        !          3498:                        if (ce->type == ZEND_USER_CLASS) {
        !          3499:                                ce->static_members_table = ce->default_static_members_table;
        !          3500:                        }
        !          3501:                }
1.1       misho    3502:        }
1.1.1.2 ! misho    3503: 
        !          3504:        for (zend_hash_internal_pointer_reset(&ce->properties_info);
        !          3505:        zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
        !          3506:        zend_hash_move_forward(&ce->properties_info)) {
        !          3507:                if (property_info->ce == ce) {
        !          3508:                        if (property_info->flags & ZEND_ACC_STATIC) {
        !          3509:                                property_info->offset += parent_ce->default_static_members_count;
        !          3510:                        } else {
        !          3511:                                property_info->offset += parent_ce->default_properties_count;
        !          3512:                        }
        !          3513:                }
        !          3514:        }
        !          3515: 
1.1       misho    3516:        zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
                   3517: 
                   3518:        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
                   3519:        zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
                   3520:        do_inherit_parent_constructor(ce);
                   3521: 
                   3522:        if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
                   3523:                ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
1.1.1.2 ! misho    3524:        } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)
        !          3525:                                && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
1.1       misho    3526:                /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
                   3527:                zend_verify_abstract_class(ce TSRMLS_CC);
                   3528:        }
1.1.1.2 ! misho    3529:        ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
1.1       misho    3530: }
                   3531: /* }}} */
                   3532: 
                   3533: static zend_bool do_inherit_constant_check(HashTable *child_constants_table, const zval **parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface) /* {{{ */
                   3534: {
                   3535:        zval **old_constant;
                   3536: 
                   3537:        if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
                   3538:                if (*old_constant != *parent_constant) {
                   3539:                        zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
                   3540:                }
                   3541:                return 0;
                   3542:        }
                   3543:        return 1;
                   3544: }
                   3545: /* }}} */
                   3546: 
                   3547: static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
                   3548: {
                   3549:        zend_class_entry **iface = va_arg(args, zend_class_entry**);
                   3550: 
                   3551:        do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
                   3552: 
                   3553:        return ZEND_HASH_APPLY_KEEP;
                   3554: }
                   3555: /* }}} */
                   3556: 
                   3557: ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
                   3558: {
                   3559:        zend_uint i, ignore = 0;
                   3560:        zend_uint current_iface_num = ce->num_interfaces;
                   3561:        zend_uint parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
                   3562: 
                   3563:        for (i = 0; i < ce->num_interfaces; i++) {
                   3564:                if (ce->interfaces[i] == NULL) {
                   3565:                        memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
                   3566:                        i--;
                   3567:                } else if (ce->interfaces[i] == iface) {
                   3568:                        if (i < parent_iface_num) {
                   3569:                                ignore = 1;
                   3570:                        } else {
                   3571:                                zend_error(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
                   3572:                        }
                   3573:                }
                   3574:        }
                   3575:        if (ignore) {
                   3576:                /* Check for attempt to redeclare interface constants */
                   3577:                zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
                   3578:        } else {
                   3579:                if (ce->num_interfaces >= current_iface_num) {
                   3580:                        if (ce->type == ZEND_INTERNAL_CLASS) {
                   3581:                                ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
                   3582:                        } else {
                   3583:                                ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
                   3584:                        }
                   3585:                }
                   3586:                ce->interfaces[ce->num_interfaces++] = iface;
                   3587:        
                   3588:                zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface);
                   3589:                zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
                   3590:        
                   3591:                do_implement_interface(ce, iface TSRMLS_CC);
                   3592:                zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
                   3593:        }
                   3594: }
                   3595: /* }}} */
                   3596: 
1.1.1.2 ! misho    3597: ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
        !          3598: {
        !          3599:        zend_uint i, ignore = 0;
        !          3600:        zend_uint current_trait_num = ce->num_traits;
        !          3601:        zend_uint parent_trait_num  = ce->parent ? ce->parent->num_traits : 0;
        !          3602: 
        !          3603:        for (i = 0; i < ce->num_traits; i++) {
        !          3604:                if (ce->traits[i] == NULL) {
        !          3605:                        memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
        !          3606:                        i--;
        !          3607:                } else if (ce->traits[i] == trait) {
        !          3608:                        if (i < parent_trait_num) {
        !          3609:                                ignore = 1;
        !          3610:                        }
        !          3611:                }
        !          3612:        }
        !          3613:        if (!ignore) {
        !          3614:                if (ce->num_traits >= current_trait_num) {
        !          3615:                        if (ce->type == ZEND_INTERNAL_CLASS) {
        !          3616:                                ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
        !          3617:                        } else {
        !          3618:                                ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
        !          3619:                        }
        !          3620:                }
        !          3621:                ce->traits[ce->num_traits++] = trait;
        !          3622:        }
        !          3623: }
        !          3624: /* }}} */
        !          3625: 
        !          3626: static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC) /* {{{ */
        !          3627: {
        !          3628:        zend_uint    fn_flags = fn->common.scope->ce_flags;
        !          3629:        zend_uint other_flags = other_fn->common.scope->ce_flags;
        !          3630:        
        !          3631:        return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
        !          3632:                && zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC)
        !          3633:                && ((fn_flags & ZEND_ACC_FINAL) == (other_flags & ZEND_ACC_FINAL))   /* equal final qualifier */
        !          3634:                && ((fn_flags & ZEND_ACC_STATIC)== (other_flags & ZEND_ACC_STATIC)); /* equal static qualifier */
        !          3635: }
        !          3636: /* }}} */
        !          3637: 
        !          3638: static int zend_traits_merge_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
        !          3639: {
        !          3640:        size_t current;
        !          3641:        size_t i;
        !          3642:        size_t count;
        !          3643:        HashTable* resulting_table;
        !          3644:        HashTable** function_tables;
        !          3645:        zend_class_entry *ce;
        !          3646:        size_t collision = 0;
        !          3647:        size_t abstract_solved = 0;
        !          3648:        zend_function* other_trait_fn;
        !          3649: 
        !          3650:        current                 = va_arg(args, size_t);  /* index of current trait */
        !          3651:        count                   = va_arg(args, size_t);
        !          3652:        resulting_table = va_arg(args, HashTable*);
        !          3653:        function_tables = va_arg(args, HashTable**);
        !          3654:        ce                              = va_arg(args, zend_class_entry*);
        !          3655: 
        !          3656:        for (i = 0; i < count; i++) {
        !          3657:                if (i == current) {
        !          3658:                        continue; /* just skip this, cause its the table this function is applied on */
        !          3659:                }
        !          3660:                
        !          3661:                if (zend_hash_quick_find(function_tables[i], hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **)&other_trait_fn) == SUCCESS) {
        !          3662:                        /* if it is an abstract method, there is no collision */
        !          3663:                        if (other_trait_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
        !          3664:                                /* Make sure they are compatible */
        !          3665:                                /* In case both are abstract, just check prototype, but need to do that in both directions */
        !          3666:                                if (!zend_traits_method_compatibility_check(fn, other_trait_fn TSRMLS_CC)) {
        !          3667:                                        zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
        !          3668:                                                                                                zend_get_function_declaration(fn TSRMLS_CC),
        !          3669:                                                                                                zend_get_function_declaration(other_trait_fn TSRMLS_CC));
        !          3670:                                }
        !          3671:                                
        !          3672:                                /* we can savely free and remove it from other table */
        !          3673:                                zend_function_dtor(other_trait_fn);
        !          3674:                                zend_hash_quick_del(function_tables[i], hash_key->arKey, hash_key->nKeyLength, hash_key->h);
        !          3675:                        } else {
        !          3676:                                /* if it is not an abstract method, there is still no collision */
        !          3677:                                /* if fn is an abstract method */
        !          3678:                                if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
        !          3679:                                        /* Make sure they are compatible.
        !          3680:                                           Here, we already know other_trait_fn cannot be abstract, full check ok. */
        !          3681:                                        if (!zend_traits_method_compatibility_check(fn, other_trait_fn TSRMLS_CC)) {
        !          3682:                                                zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
        !          3683:                                                                                                        zend_get_function_declaration(fn TSRMLS_CC),
        !          3684:                                                                                                        zend_get_function_declaration(other_trait_fn TSRMLS_CC));
        !          3685:                                        }
        !          3686:                                        
        !          3687:                                        /* just mark as solved, will be added if its own trait is processed */
        !          3688:                                        abstract_solved = 1;
        !          3689:                                } else {
        !          3690:                                        /* but else, we have a collision of non-abstract methods */
        !          3691:                                        collision++;
        !          3692:                                        zend_function_dtor(other_trait_fn);
        !          3693:                                        zend_hash_quick_del(function_tables[i], hash_key->arKey, hash_key->nKeyLength, hash_key->h);
        !          3694:                                }
        !          3695:                        }
        !          3696:                }
        !          3697:        }
        !          3698: 
        !          3699:        if (collision) {
        !          3700:                zend_function* class_fn;
        !          3701: 
        !          3702:                /* make sure method is not already overridden in class */
        !          3703:                if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **)&class_fn) == FAILURE
        !          3704:                        || class_fn->common.scope != ce) {
        !          3705:                        zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s", fn->common.function_name, ce->name);
        !          3706:                }
        !          3707: 
        !          3708:                zend_function_dtor(fn);
        !          3709:        } else if (abstract_solved) {
        !          3710:                zend_function_dtor(fn);
        !          3711:        } else {
        !          3712:                /* Add it to result function table */
        !          3713:                if (zend_hash_quick_add(resulting_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, fn, sizeof(zend_function), NULL)==FAILURE) {
        !          3714:                        zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because failure occured during updating resulting trait method table", fn->common.function_name);
        !          3715:                }
        !          3716:        }
        !          3717: 
        !          3718:        return ZEND_HASH_APPLY_REMOVE;
        !          3719: }
        !          3720: /* }}} */
        !          3721: 
        !          3722: static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint mname_len, zend_function* fe TSRMLS_DC) /* {{{ */
        !          3723: {
        !          3724:        if (!strncmp(mname, ZEND_CLONE_FUNC_NAME, mname_len)) {
        !          3725:                ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
        !          3726:        } else if (!strncmp(mname, ZEND_CONSTRUCTOR_FUNC_NAME, mname_len)) {
        !          3727:                if (ce->constructor) {
        !          3728:                        zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
        !          3729:                }
        !          3730:                ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR; 
        !          3731:        } else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME,  mname_len)) {
        !          3732:                ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
        !          3733:        } else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) {
        !          3734:                ce->__get = fe;
        !          3735:        } else if (!strncmp(mname, ZEND_SET_FUNC_NAME, mname_len)) {
        !          3736:                ce->__set = fe;
        !          3737:        } else if (!strncmp(mname, ZEND_CALL_FUNC_NAME, mname_len)) {
        !          3738:                ce->__call = fe;
        !          3739:        } else if (!strncmp(mname, ZEND_UNSET_FUNC_NAME, mname_len)) {
        !          3740:                ce->__unset = fe;
        !          3741:        } else if (!strncmp(mname, ZEND_ISSET_FUNC_NAME, mname_len)) {
        !          3742:                ce->__isset = fe;
        !          3743:        } else if (!strncmp(mname, ZEND_CALLSTATIC_FUNC_NAME, mname_len)) {
        !          3744:                ce->__callstatic = fe;
        !          3745:        } else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) {
        !          3746:                ce->__tostring = fe;
        !          3747:        } else if (ce->name_length + 1 == mname_len) {
        !          3748:                char *lowercase_name = emalloc(ce->name_length + 1);
        !          3749:                zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length);
        !          3750:                lowercase_name = (char*)zend_new_interned_string(lowercase_name, ce->name_length + 1, 1 TSRMLS_CC);
        !          3751:                if (!memcmp(mname, lowercase_name, mname_len)) {
        !          3752:                        if (ce->constructor) {
        !          3753:                                zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
        !          3754:                        }
        !          3755:                        ce->constructor = fe;
        !          3756:                        fe->common.fn_flags |= ZEND_ACC_CTOR;
        !          3757:                }
        !          3758:                str_efree(lowercase_name);
        !          3759:        }
        !          3760: }
        !          3761: /* }}} */
        !          3762: 
        !          3763: static int zend_traits_merge_functions_to_class(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
        !          3764: {
        !          3765:        zend_class_entry *ce = va_arg(args, zend_class_entry*);
        !          3766:        zend_function* existing_fn = NULL;
        !          3767:        zend_function fn_copy, *fn_copy_p;
        !          3768:        zend_function* prototype = NULL;  /* is used to determine the prototype according to the inheritance chain */
        !          3769: 
        !          3770:        if (zend_hash_quick_find(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &existing_fn) == FAILURE ||
        !          3771:            existing_fn->common.scope != ce) {
        !          3772:                /* not found or inherited from other class or interface */
        !          3773:                zend_function* parent_function;
        !          3774: 
        !          3775:                if (ce->parent && zend_hash_quick_find(&ce->parent->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**) &parent_function) != FAILURE) {
        !          3776:                        prototype = parent_function; /* ->common.fn_flags |= ZEND_ACC_ABSTRACT; */
        !          3777:                        
        !          3778:                        /* we got that method in the parent class, and are going to override it,
        !          3779:                          except, if the trait is just asking to have an abstract method implemented. */
        !          3780:                        if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
        !          3781:                                /* then we clean up an skip this method */
        !          3782:                                zend_function_dtor(fn);
        !          3783:                                return ZEND_HASH_APPLY_REMOVE;
        !          3784:                        }
        !          3785:                }
        !          3786: 
        !          3787:                fn->common.scope = ce;
        !          3788:                fn->common.prototype = prototype;
        !          3789: 
        !          3790:                if (prototype
        !          3791:                        && (prototype->common.fn_flags & ZEND_ACC_IMPLEMENTED_ABSTRACT
        !          3792:                        || prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
        !          3793:                        fn->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
        !          3794:                } else if (fn->common.fn_flags & ZEND_ACC_IMPLEMENTED_ABSTRACT) {
        !          3795:                        /* remove ZEND_ACC_IMPLEMENTED_ABSTRACT flag, think it shouldn't be copied to class */
        !          3796:                        fn->common.fn_flags = fn->common.fn_flags - ZEND_ACC_IMPLEMENTED_ABSTRACT;
        !          3797:                }
        !          3798: 
        !          3799:                /* check whether the trait method fullfills the inheritance requirements */
        !          3800:                if (prototype) {
        !          3801:                        do_inheritance_check_on_method(fn, prototype TSRMLS_CC);
        !          3802:                }
        !          3803:                /* one more thing: make sure we properly implement an abstract method */
        !          3804:                if (existing_fn && existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
        !          3805:                        do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
        !          3806:                }
        !          3807: 
        !          3808:                /* delete inherited fn if the function to be added is not abstract */
        !          3809:                if (existing_fn
        !          3810:                        && existing_fn->common.scope != ce
        !          3811:                        && (fn->common.fn_flags & ZEND_ACC_ABSTRACT) == 0) {
        !          3812:                        /* it is just a reference which was added to the subclass while doing
        !          3813:                           the inheritance, so we can deleted now, and will add the overriding 
        !          3814:                           method afterwards.
        !          3815:                           Except, if we try to add an abstract function, then we should not
        !          3816:                           delete the inherited one */
        !          3817:                        zend_hash_quick_del(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h);
        !          3818:                }
        !          3819: 
        !          3820: 
        !          3821:                if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
        !          3822:                        ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
        !          3823:                }
        !          3824:                if (fn->op_array.static_variables) {
        !          3825:                        ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
        !          3826:                }
        !          3827:                fn_copy = *fn;
        !          3828:                function_add_ref(&fn_copy);
        !          3829: 
        !          3830:                if (zend_hash_quick_update(&ce->function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, &fn_copy, sizeof(zend_function), (void**)&fn_copy_p)==FAILURE) {
        !          3831:                        zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because failure occured during updating class method table", hash_key->arKey);
        !          3832:                }
        !          3833:    
        !          3834:                zend_add_magic_methods(ce, hash_key->arKey, hash_key->nKeyLength, fn_copy_p TSRMLS_CC);
        !          3835:    
        !          3836:                zend_function_dtor(fn);
        !          3837:        } else {
        !          3838:                zend_function_dtor(fn);
        !          3839:        }
        !          3840: 
        !          3841:        return ZEND_HASH_APPLY_REMOVE;
        !          3842: }
        !          3843: /* }}} */
        !          3844: 
        !          3845: static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
        !          3846: {
        !          3847:        HashTable* target;
        !          3848:        zend_trait_alias** aliases;
        !          3849:        HashTable* exclude_table;
        !          3850:        char* lcname;
        !          3851:        unsigned int fnname_len;
        !          3852:        zend_function fn_copy;
        !          3853:        void* dummy;
        !          3854:        size_t i = 0;
        !          3855: 
        !          3856:        target        = va_arg(args, HashTable*);
        !          3857:        aliases       = va_arg(args, zend_trait_alias**);
        !          3858:        exclude_table = va_arg(args, HashTable*);
        !          3859: 
        !          3860:        fnname_len = strlen(fn->common.function_name);
        !          3861: 
        !          3862:        /* apply aliases which are qualified with a class name, there should not be any ambiguity */
        !          3863:        if (aliases) {
        !          3864:                while (aliases[i]) {
        !          3865:                        /* Scope unset or equal to the function we compare to, and the alias applies to fn */
        !          3866:                        if (aliases[i]->alias != NULL
        !          3867:                                && (!aliases[i]->trait_method->ce || fn->common.scope == aliases[i]->trait_method->ce)
        !          3868:                                && aliases[i]->trait_method->mname_len == fnname_len
        !          3869:                                && (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) {
        !          3870:                                fn_copy = *fn;
        !          3871:                                function_add_ref(&fn_copy);
        !          3872:                                /* this function_name is never destroyed, because its refcount
        !          3873:                                   greater than 1, classes are always destoyed in reverse order
        !          3874:                                   and trait is declared early than this class */
        !          3875:                                fn_copy.common.function_name = aliases[i]->alias;
        !          3876:                                        
        !          3877:                                /* if it is 0, no modifieres has been changed */
        !          3878:                                if (aliases[i]->modifiers) { 
        !          3879:                                        fn_copy.common.fn_flags = aliases[i]->modifiers;
        !          3880:                                        if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
        !          3881:                                                fn_copy.common.fn_flags |= ZEND_ACC_PUBLIC;
        !          3882:                                        }
        !          3883:                                        fn_copy.common.fn_flags |= fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK);
        !          3884:                                }
        !          3885: 
        !          3886:                                lcname = zend_str_tolower_dup(aliases[i]->alias, aliases[i]->alias_len);
        !          3887: 
        !          3888:                                if (zend_hash_add(target, lcname, aliases[i]->alias_len+1, &fn_copy, sizeof(zend_function), NULL)==FAILURE) {
        !          3889:                                        zend_error(E_COMPILE_ERROR, "Failed to add aliased trait method (%s) to the trait table. There is probably already a trait method with the same name", fn_copy.common.function_name);
        !          3890:                                }
        !          3891:                                efree(lcname);
        !          3892: 
        !          3893:                                /** Record the trait from which this alias was resolved. */
        !          3894:                                if (!aliases[i]->trait_method->ce) {
        !          3895:                                        aliases[i]->trait_method->ce = fn->common.scope;
        !          3896:                                }
        !          3897:                        }
        !          3898:                        i++;
        !          3899:                }
        !          3900:        }
        !          3901: 
        !          3902:        lcname = zend_str_tolower_dup(fn->common.function_name, fnname_len);
        !          3903: 
        !          3904:        if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
        !          3905:                /* is not in hashtable, thus, function is not to be excluded */
        !          3906:                fn_copy = *fn;
        !          3907:                function_add_ref(&fn_copy);
        !          3908: 
        !          3909:                /* apply aliases which are not qualified by a class name, or which have not
        !          3910:                 * alias name, just setting visibility */
        !          3911:                if (aliases) {
        !          3912:                        i = 0;
        !          3913:                        while (aliases[i]) {
        !          3914:                                /* Scope unset or equal to the function we compare to, and the alias applies to fn */
        !          3915:                                if (aliases[i]->alias == NULL && aliases[i]->modifiers != 0
        !          3916:                                        && (!aliases[i]->trait_method->ce || fn->common.scope == aliases[i]->trait_method->ce)
        !          3917:                                        && (aliases[i]->trait_method->mname_len == fnname_len)
        !          3918:                                        && (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) {
        !          3919:                                        fn_copy.common.fn_flags = aliases[i]->modifiers;
        !          3920: 
        !          3921:                                        if (!(aliases[i]->modifiers & ZEND_ACC_PPP_MASK)) {
        !          3922:                                                fn_copy.common.fn_flags |= ZEND_ACC_PUBLIC;
        !          3923:                                        }
        !          3924:                                        fn_copy.common.fn_flags |= fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK);
        !          3925: 
        !          3926:                                        /** Record the trait from which this alias was resolved. */
        !          3927:                                        if (!aliases[i]->trait_method->ce) {
        !          3928:                                                aliases[i]->trait_method->ce = fn->common.scope;
        !          3929:                                        }
        !          3930:                                }
        !          3931:                                i++;
        !          3932:                        }
        !          3933:                }
        !          3934: 
        !          3935:                if (zend_hash_add(target, lcname, fnname_len+1, &fn_copy, sizeof(zend_function), NULL)==FAILURE) {
        !          3936:                        zend_error(E_COMPILE_ERROR, "Failed to add trait method (%s) to the trait table. There is probably already a trait method with the same name", fn_copy.common.function_name);
        !          3937:                }
        !          3938:        }
        !          3939: 
        !          3940:        efree(lcname);
        !          3941: 
        !          3942:        return ZEND_HASH_APPLY_KEEP;
        !          3943: }
        !          3944: /* }}} */
        !          3945: 
        !          3946: /* Copies function table entries to target function table with applied aliasing */
        !          3947: static void zend_traits_copy_trait_function_table(HashTable *target, HashTable *source, zend_trait_alias** aliases, HashTable* exclude_table TSRMLS_DC) /* {{{ */
        !          3948: {
        !          3949:        zend_hash_apply_with_arguments(source TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, target, aliases, exclude_table);
        !          3950: }
        !          3951: /* }}} */
        !          3952: 
        !          3953: static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* {{{ */
        !          3954: {
        !          3955:        size_t i, j = 0;
        !          3956:        zend_trait_precedence *cur_precedence;
        !          3957:        zend_trait_method_reference *cur_method_ref;
        !          3958:        char *lcname;
        !          3959:        zend_bool method_exists;
        !          3960: 
        !          3961:        /* resolve class references */
        !          3962:        if (ce->trait_precedences) {
        !          3963:                i = 0;
        !          3964:                while ((cur_precedence = ce->trait_precedences[i])) {
        !          3965:                        /** Resolve classes for all precedence operations. */
        !          3966:                        if (cur_precedence->exclude_from_classes) {
        !          3967:                                cur_method_ref = cur_precedence->trait_method;
        !          3968:                                cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name,
        !          3969:                                                                                                                                        cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
        !          3970: 
        !          3971:                                /** Ensure that the prefered method is actually available. */
        !          3972:                                lcname = zend_str_tolower_dup(cur_method_ref->method_name,
        !          3973:                                                                                          cur_method_ref->mname_len);
        !          3974:                                method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
        !          3975:                                                                                                 lcname,
        !          3976:                                                                                                 cur_method_ref->mname_len + 1);
        !          3977:                                efree(lcname);
        !          3978:                                if (!method_exists) {
        !          3979:                                        zend_error(E_COMPILE_ERROR,
        !          3980:                                                           "A precedence rule was defined for %s::%s but this method does not exist",
        !          3981:                                                           cur_method_ref->ce->name,
        !          3982:                                                           cur_method_ref->method_name);
        !          3983:                                }
        !          3984:                        
        !          3985:                                /** With the other traits, we are more permissive.
        !          3986:                                        We do not give errors for those. This allows to be more
        !          3987:                                        defensive in such definitions.
        !          3988:                                        However, we want to make sure that the insteadof declartion
        !          3989:                                        is consistent in itself.
        !          3990:                                 */
        !          3991:                                j = 0;
        !          3992:                                while (cur_precedence->exclude_from_classes[j]) {
        !          3993:                                        char* class_name = (char*)cur_precedence->exclude_from_classes[j];
        !          3994:                                        zend_uint name_length = strlen(class_name);
        !          3995: 
        !          3996:                                        cur_precedence->exclude_from_classes[j] = zend_fetch_class(class_name, name_length, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
        !          3997:                                        
        !          3998:                                        /* make sure that the trait method is not from a class mentioned in
        !          3999:                                         exclude_from_classes, for consistency */
        !          4000:                                        if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[i]) {
        !          4001:                                                zend_error(E_COMPILE_ERROR,
        !          4002:                                                                   "Inconsistent insteadof definition. " 
        !          4003:                                                                   "The method %s is to be used from %s, but %s is also on the exclude list",
        !          4004:                                                                   cur_method_ref->method_name,
        !          4005:                                                                   cur_precedence->trait_method->ce->name,
        !          4006:                                                                   cur_precedence->trait_method->ce->name);
        !          4007:                                        }
        !          4008:                                        
        !          4009:                                        efree(class_name);
        !          4010:                                        j++;
        !          4011:                                }
        !          4012:                        }
        !          4013:                        i++;
        !          4014:                }
        !          4015:        }
        !          4016: 
        !          4017:        if (ce->trait_aliases) {
        !          4018:                i = 0;
        !          4019:                while (ce->trait_aliases[i]) {
        !          4020:                        /** For all aliases with an explicit class name, resolve the class now. */
        !          4021:                        if (ce->trait_aliases[i]->trait_method->class_name) {
        !          4022:                                cur_method_ref = ce->trait_aliases[i]->trait_method;
        !          4023:                                cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT TSRMLS_CC);
        !          4024: 
        !          4025:                                /** And, ensure that the referenced method is resolvable, too. */
        !          4026:                                lcname = zend_str_tolower_dup(cur_method_ref->method_name,
        !          4027:                                       cur_method_ref->mname_len);
        !          4028:                                method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
        !          4029:                                          lcname, cur_method_ref->mname_len + 1);
        !          4030:                                efree(lcname);
        !          4031: 
        !          4032:                                if (!method_exists) {
        !          4033:                                        zend_error(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", cur_method_ref->ce->name, cur_method_ref->method_name);
        !          4034:                                }
        !          4035:                        }
        !          4036:                        i++;
        !          4037:                }
        !          4038:        }
        !          4039: }
        !          4040: /* }}} */
        !          4041: 
        !          4042: static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */
        !          4043: {
        !          4044:        size_t i = 0, j;
        !          4045:        
        !          4046:        if (!precedences) {
        !          4047:                return;
        !          4048:        }
        !          4049:        while (precedences[i]) {
        !          4050:                if (precedences[i]->exclude_from_classes) {
        !          4051:                        j = 0;
        !          4052:                        while (precedences[i]->exclude_from_classes[j]) {
        !          4053:                                if (precedences[i]->exclude_from_classes[j] == trait) {
        !          4054:                                        zend_uint lcname_len = precedences[i]->trait_method->mname_len;
        !          4055:                                        char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len);
        !          4056:                                        
        !          4057:                                        if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) {
        !          4058:                                                efree(lcname);
        !          4059:                                                zend_error(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name, trait->name);
        !          4060:                                        }
        !          4061:                                        efree(lcname);
        !          4062:                                }
        !          4063:                                ++j;
        !          4064:                        }
        !          4065:                }
        !          4066:                ++i;
        !          4067:        }
        !          4068: }
        !          4069: /* }}} */
        !          4070: 
        !          4071: static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
        !          4072: {
        !          4073:        HashTable** function_tables;
        !          4074:        HashTable* resulting_table;
        !          4075:        HashTable exclude_table;
        !          4076:        size_t i;
        !          4077: 
        !          4078:        /* prepare copies of trait function tables for combination */
        !          4079:        function_tables = malloc(sizeof(HashTable*) * ce->num_traits);
        !          4080:        resulting_table = (HashTable *) malloc(sizeof(HashTable));
        !          4081:        
        !          4082:        /* TODO: revisit this start size, may be its not optimal */
        !          4083:        zend_hash_init_ex(resulting_table, 10, NULL, NULL, 1, 0);
        !          4084:   
        !          4085:        for (i = 0; i < ce->num_traits; i++) {
        !          4086:                function_tables[i] = (HashTable *) malloc(sizeof(HashTable));
        !          4087:                zend_hash_init_ex(function_tables[i], ce->traits[i]->function_table.nNumOfElements, NULL, NULL, 1, 0);
        !          4088: 
        !          4089:                if (ce->trait_precedences) {
        !          4090:                        /* TODO: revisit this start size, may be its not optimal */
        !          4091:                        zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
        !          4092: 
        !          4093:                        zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
        !          4094: 
        !          4095:                        /* copies functions, applies defined aliasing, and excludes unused trait methods */
        !          4096:                        zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, &exclude_table TSRMLS_CC);
        !          4097:                        zend_hash_destroy(&exclude_table);
        !          4098:                } else {
        !          4099:                        zend_traits_copy_trait_function_table(function_tables[i], &ce->traits[i]->function_table, ce->trait_aliases, NULL TSRMLS_CC);
        !          4100:                }
        !          4101:        }
        !          4102:   
        !          4103:        /* now merge trait methods */
        !          4104:        for (i = 0; i < ce->num_traits; i++) {
        !          4105:                zend_hash_apply_with_arguments(function_tables[i] TSRMLS_CC, (apply_func_args_t)zend_traits_merge_functions, 5, i, ce->num_traits, resulting_table, function_tables, ce);
        !          4106:        }
        !          4107:   
        !          4108:        /* Now the resulting_table contains all trait methods we would have to
        !          4109:         * add to the class in the following step the methods are inserted into the method table
        !          4110:         * if there is already a method with the same name it is replaced iff ce != fn.scope
        !          4111:         * --> all inherited methods are overridden, methods defined in the class are left untouched
        !          4112:         */
        !          4113:        zend_hash_apply_with_arguments(resulting_table TSRMLS_CC, (apply_func_args_t)zend_traits_merge_functions_to_class, 1, ce);
        !          4114:   
        !          4115:        /* free temporary function tables */
        !          4116:        for (i = 0; i < ce->num_traits; i++) {
        !          4117:                /* zend_hash_destroy(function_tables[i]); */
        !          4118:                zend_hash_graceful_destroy(function_tables[i]);
        !          4119:                free(function_tables[i]);
        !          4120:        }
        !          4121:        free(function_tables);
        !          4122: 
        !          4123:        /* free temporary resulting table */
        !          4124:        /* zend_hash_destroy(resulting_table); */
        !          4125:        zend_hash_graceful_destroy(resulting_table);
        !          4126:        free(resulting_table);
        !          4127: }
        !          4128: /* }}} */
        !          4129: 
        !          4130: static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t current_trait, const char* prop_name, int prop_name_length, ulong prop_hash, zend_class_entry *coliding_ce) /* {{{ */
        !          4131: {
        !          4132:        size_t i;
        !          4133:        zend_property_info *coliding_prop;
        !          4134:        for (i = 0; (i < current_trait) && (i < ce->num_traits); i++) {
        !          4135:                if (zend_hash_quick_find(&ce->traits[i]->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
        !          4136:                        return ce->traits[i];
        !          4137:                }
        !          4138:        }
        !          4139: 
        !          4140:        return coliding_ce;
        !          4141: }
        !          4142: /* }}} */
        !          4143: 
        !          4144: static void zend_traits_register_private_property(zend_class_entry *ce, const char *name, int name_len, zend_property_info *old_info, zval *property TSRMLS_DC) /* {{{ */
        !          4145: {
        !          4146:        char *priv_name;
        !          4147:        int priv_name_length;
        !          4148:        const char *interned_name;
        !          4149:        zend_property_info property_info;
        !          4150:        ulong h = zend_get_hash_value(name, name_len+1);
        !          4151:        property_info = *old_info;
        !          4152: 
        !          4153:        if (old_info->flags & ZEND_ACC_STATIC) {
        !          4154:                property_info.offset = ce->default_static_members_count++;
        !          4155:                ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(zval*) * ce->default_static_members_count, ce->type == ZEND_INTERNAL_CLASS);
        !          4156:                ce->default_static_members_table[property_info.offset] = property;
        !          4157:                if (ce->type == ZEND_USER_CLASS) {
        !          4158:                        ce->static_members_table = ce->default_static_members_table;
        !          4159:                }
        !          4160:        } else {
        !          4161:                property_info.offset = ce->default_properties_count++;
        !          4162:                ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(zval*) * ce->default_properties_count, ce->type == ZEND_INTERNAL_CLASS);
        !          4163:                ce->default_properties_table[property_info.offset] = property;
        !          4164:        }
        !          4165: 
        !          4166:        zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_len, ce->type & ZEND_INTERNAL_CLASS);
        !          4167:        property_info.name = priv_name;
        !          4168:        property_info.name_length = priv_name_length;
        !          4169: 
        !          4170:        interned_name = zend_new_interned_string(property_info.name, property_info.name_length+1, 0 TSRMLS_CC);
        !          4171:        if (interned_name != property_info.name) {
        !          4172:                if (ce->type == ZEND_USER_CLASS) {
        !          4173:                        efree((char*)property_info.name);
        !          4174:                } else {
        !          4175:                        free((char*)property_info.name);
        !          4176:                }
        !          4177:                property_info.name = interned_name;
        !          4178:        }
        !          4179: 
        !          4180:        property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
        !          4181: 
        !          4182:        property_info.ce = ce;
        !          4183: 
        !          4184:        if (property_info.doc_comment) {
        !          4185:                property_info.doc_comment = estrndup(property_info.doc_comment, property_info.doc_comment_len);
        !          4186:        }
        !          4187: 
        !          4188:        zend_hash_quick_update(&ce->properties_info, name, name_len+1, h, &property_info, sizeof(zend_property_info), NULL);
        !          4189: }
        !          4190: /* }}} */
        !          4191: 
        !          4192: static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
        !          4193: {
        !          4194:        size_t i;
        !          4195:        zend_property_info *property_info;
        !          4196:        zend_property_info *coliding_prop;
        !          4197:        zval compare_result;
        !          4198:        const char* prop_name;
        !          4199:        int   prop_name_length;
        !          4200:        ulong prop_hash;
        !          4201:        const char* class_name_unused;
        !          4202:        zend_bool not_compatible;
        !          4203:        zval* prop_value;
        !          4204:        char* doc_comment;  
        !          4205:   
        !          4206:        /* In the following steps the properties are inserted into the property table
        !          4207:         * for that, a very strict approach is applied:
        !          4208:         * - check for compatibility, if not compatible with any property in class -> fatal
        !          4209:         * - if compatible, then strict notice
        !          4210:         */
        !          4211:        for (i = 0; i < ce->num_traits; i++) {
        !          4212:                for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info);
        !          4213:                         zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS;
        !          4214:                         zend_hash_move_forward(&ce->traits[i]->properties_info)) {
        !          4215:                        /* first get the unmangeld name if necessary,
        !          4216:                         * then check whether the property is already there
        !          4217:                         */
        !          4218:                        if ((property_info->flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
        !          4219:                                prop_hash = property_info->h;
        !          4220:                                prop_name = property_info->name;
        !          4221:                                prop_name_length = property_info->name_length;
        !          4222:                        } else {
        !          4223:                                /* for private and protected we need to unmangle the names */
        !          4224:                                zend_unmangle_property_name(property_info->name, property_info->name_length,
        !          4225:                                                                                        &class_name_unused, &prop_name);
        !          4226:                                prop_name_length = strlen(prop_name);
        !          4227:                                prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
        !          4228:                        }
        !          4229: 
        !          4230:                        /* next: check for conflicts with current class */
        !          4231:                        if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
        !          4232:                                if (coliding_prop->flags & ZEND_ACC_SHADOW) {
        !          4233:                                        /* this one is inherited, lets look it up in its own class */
        !          4234:                                        zend_hash_quick_find(&coliding_prop->ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop);
        !          4235:                                        if (coliding_prop->flags & ZEND_ACC_PRIVATE) {
        !          4236:                                                /* private property, make the property_info.offset indenpended */
        !          4237:                                                if (property_info->flags & ZEND_ACC_STATIC) {
        !          4238:                                                        prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
        !          4239:                                                } else {
        !          4240:                                                        prop_value = ce->traits[i]->default_properties_table[property_info->offset];
        !          4241:                                                }
        !          4242:                                                Z_ADDREF_P(prop_value);
        !          4243: 
        !          4244:                                                zend_traits_register_private_property(ce, prop_name, prop_name_length, property_info, prop_value TSRMLS_CC);
        !          4245:                                                continue;
        !          4246:                                        }
        !          4247:                                }
        !          4248:                                
        !          4249:                                if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
        !          4250:                                        == (property_info->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
        !          4251:                                        /* flags are identical, now the value needs to be checked */
        !          4252:                                        if (property_info->flags & ZEND_ACC_STATIC) {
        !          4253:                                                not_compatible = (FAILURE == compare_function(&compare_result,
        !          4254:                                                                                  ce->default_static_members_table[coliding_prop->offset],
        !          4255:                                                                                  ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
        !          4256:                                                          || (Z_LVAL(compare_result) != 0);
        !          4257:                                        } else {
        !          4258:                                                not_compatible = (FAILURE == compare_function(&compare_result,
        !          4259:                                                                                  ce->default_properties_table[coliding_prop->offset],
        !          4260:                                                                                  ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
        !          4261:                                                          || (Z_LVAL(compare_result) != 0);
        !          4262:                                        }
        !          4263:                                } else {
        !          4264:                                        /* the flags are not identical, thus, we assume properties are not compatible */
        !          4265:                                        not_compatible = 1;
        !          4266:                                }
        !          4267: 
        !          4268:                                if (not_compatible) {
        !          4269:                                        zend_error(E_COMPILE_ERROR, 
        !          4270:                                                           "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
        !          4271:                                                                find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
        !          4272:                                                                property_info->ce->name,
        !          4273:                                                                prop_name,
        !          4274:                                                                ce->name);
        !          4275:                                } else {
        !          4276:                                        zend_error(E_STRICT, 
        !          4277:                                                           "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
        !          4278:                                                                find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
        !          4279:                                                                property_info->ce->name,
        !          4280:                                                                prop_name,
        !          4281:                                                                ce->name);
        !          4282:                                }
        !          4283:                        }
        !          4284: 
        !          4285:                        /* property not found, so lets add it */
        !          4286:                        if (property_info->flags & ZEND_ACC_STATIC) {
        !          4287:                                prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
        !          4288:                        } else {
        !          4289:                                prop_value = ce->traits[i]->default_properties_table[property_info->offset];
        !          4290:                        }
        !          4291:                        Z_ADDREF_P(prop_value);
        !          4292: 
        !          4293:                        doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
        !          4294:                        zend_declare_property_ex(ce, prop_name, prop_name_length, 
        !          4295:                                                                         prop_value, property_info->flags, 
        !          4296:                                                                     doc_comment, property_info->doc_comment_len TSRMLS_CC);
        !          4297:                }
        !          4298:        }
        !          4299: }
        !          4300: /* }}} */
        !          4301: 
        !          4302: static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce TSRMLS_DC) /* {{{ */
        !          4303: {
        !          4304:        int i = 0;
        !          4305:        zend_trait_alias* cur_alias;
        !          4306:        char* lc_method_name;
        !          4307:        
        !          4308:        if (ce->trait_aliases) {
        !          4309:                while (ce->trait_aliases[i]) {
        !          4310:                        cur_alias = ce->trait_aliases[i];
        !          4311:                        /** The trait for this alias has not been resolved, this means, this
        !          4312:                                alias was not applied. Abort with an error. */
        !          4313:                        if (!cur_alias->trait_method->ce) {
        !          4314:                                if (cur_alias->alias) {
        !          4315:                                        /** Plain old inconsistency/typo/bug */
        !          4316:                                        zend_error(E_COMPILE_ERROR,
        !          4317:                                                           "An alias (%s) was defined for method %s(), but this method does not exist",
        !          4318:                                                           cur_alias->alias,
        !          4319:                                                           cur_alias->trait_method->method_name);
        !          4320:                                } else {
        !          4321:                                        /** Here are two possible cases:
        !          4322:                                                1) this is an attempt to modifiy the visibility
        !          4323:                                                   of a method introduce as part of another alias.
        !          4324:                                                   Since that seems to violate the DRY principle,
        !          4325:                                                   we check against it and abort.
        !          4326:                                                2) it is just a plain old inconsitency/typo/bug
        !          4327:                                                   as in the case where alias is set. */
        !          4328:                                        
        !          4329:                                        lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name,
        !          4330:                                                                                                                  cur_alias->trait_method->mname_len);
        !          4331:                                        if (zend_hash_exists(&ce->function_table,
        !          4332:                                                                                 lc_method_name,
        !          4333:                                                                                 cur_alias->trait_method->mname_len+1)) {
        !          4334:                                                efree(lc_method_name);
        !          4335:                                                zend_error(E_COMPILE_ERROR,
        !          4336:                                                                   "The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
        !          4337:                                                                   cur_alias->trait_method->method_name);
        !          4338:                                        } else {
        !          4339:                                                efree(lc_method_name);
        !          4340:                                                zend_error(E_COMPILE_ERROR,
        !          4341:                                                                   "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
        !          4342:                                                                   cur_alias->trait_method->method_name);
        !          4343: 
        !          4344:                                        }
        !          4345:                                }
        !          4346:                        }
        !          4347:                        i++;
        !          4348:                }
        !          4349:        }
        !          4350: }
        !          4351: /* }}} */
        !          4352: 
        !          4353: ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
        !          4354: {
        !          4355: 
        !          4356:        if (ce->num_traits <= 0) {
        !          4357:                return;
        !          4358:        }
        !          4359: 
        !          4360:        /* complete initialization of trait strutures in ce */
        !          4361:        zend_traits_init_trait_structures(ce TSRMLS_CC);
        !          4362: 
        !          4363:        /* first care about all methods to be flattened into the class */
        !          4364:        zend_do_traits_method_binding(ce TSRMLS_CC);
        !          4365:   
        !          4366:        /* Aliases which have not been applied indicate typos/bugs. */
        !          4367:        zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC);
        !          4368: 
        !          4369:        /* then flatten the properties into it, to, mostly to notfiy developer about problems */
        !          4370:        zend_do_traits_property_binding(ce TSRMLS_CC);
        !          4371: 
        !          4372:        /* verify that all abstract methods from traits have been implemented */
        !          4373:        zend_verify_abstract_class(ce TSRMLS_CC);
        !          4374:   
        !          4375:        /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
        !          4376:        if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
        !          4377:                ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
        !          4378:        }
        !          4379: }
        !          4380: /* }}} */
        !          4381: 
        !          4382: ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
1.1       misho    4383: {
                   4384:        zend_function *function;
1.1.1.2 ! misho    4385:        zval *op1, *op2;
1.1       misho    4386: 
1.1.1.2 ! misho    4387:        if (compile_time) {
        !          4388:                op1 = &CONSTANT_EX(op_array, opline->op1.constant);
        !          4389:                op2 = &CONSTANT_EX(op_array, opline->op2.constant);
        !          4390:        } else {
        !          4391:                op1 = opline->op1.zv;
        !          4392:                op2 = opline->op2.zv;
        !          4393:        }
        !          4394: 
        !          4395:        zend_hash_quick_find(function_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void *) &function);
        !          4396:        if (zend_hash_quick_add(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), function, sizeof(zend_function), NULL)==FAILURE) {
1.1       misho    4397:                int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
                   4398:                zend_function *old_function;
                   4399: 
1.1.1.2 ! misho    4400:                if (zend_hash_quick_find(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), (void *) &old_function)==SUCCESS
1.1       misho    4401:                        && old_function->type == ZEND_USER_FUNCTION
                   4402:                        && old_function->op_array.last > 0) {
                   4403:                        zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
                   4404:                                                function->common.function_name,
                   4405:                                                old_function->op_array.filename,
                   4406:                                                old_function->op_array.opcodes[0].lineno);
                   4407:                } else {
                   4408:                        zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
                   4409:                }
                   4410:                return FAILURE;
                   4411:        } else {
                   4412:                (*function->op_array.refcount)++;
                   4413:                function->op_array.static_variables = NULL; /* NULL out the unbound function */
                   4414:                return SUCCESS;
                   4415:        }
                   4416: }
                   4417: /* }}} */
                   4418: 
1.1.1.2 ! misho    4419: void zend_add_trait_precedence(znode *precedence_znode TSRMLS_DC) /* {{{ */
        !          4420: {
        !          4421:        zend_class_entry *ce = CG(active_class_entry);
        !          4422:        zend_add_to_list(&ce->trait_precedences, precedence_znode->u.op.ptr TSRMLS_CC);
        !          4423: }
        !          4424: /* }}} */
        !          4425: 
        !          4426: void zend_add_trait_alias(znode *alias_znode TSRMLS_DC) /* {{{ */
        !          4427: {
        !          4428:        zend_class_entry *ce = CG(active_class_entry);
        !          4429:        zend_add_to_list(&ce->trait_aliases, alias_znode->u.op.ptr TSRMLS_CC);
        !          4430: }
        !          4431: /* }}} */
        !          4432: 
        !          4433: void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
        !          4434: {
        !          4435:        zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
        !          4436:        method_ref->ce = NULL;
        !          4437: 
        !          4438:        /* REM: There should not be a need for copying, 
        !          4439:           zend_do_begin_class_declaration is also just using that string */
        !          4440:        if (class_name) {
        !          4441:                zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
        !          4442:                method_ref->class_name = Z_STRVAL(class_name->u.constant);
        !          4443:                method_ref->cname_len  = Z_STRLEN(class_name->u.constant);
        !          4444:        } else {
        !          4445:                method_ref->class_name = NULL;
        !          4446:                method_ref->cname_len  = 0;
        !          4447:        }
        !          4448: 
        !          4449:        method_ref->method_name = Z_STRVAL(method_name->u.constant);
        !          4450:        method_ref->mname_len   = Z_STRLEN(method_name->u.constant);
        !          4451: 
        !          4452:        result->u.op.ptr = method_ref;
        !          4453:        result->op_type = IS_TMP_VAR;
        !          4454: }
        !          4455: /* }}} */
        !          4456: 
        !          4457: void zend_prepare_trait_alias(znode *result, znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
        !          4458: {
        !          4459:        zend_trait_alias *trait_alias = emalloc(sizeof(zend_trait_alias));
        !          4460: 
        !          4461:        trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
        !          4462:        trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
        !          4463:        
        !          4464:        if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
        !          4465:                zend_error(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
        !          4466:                return;
        !          4467:        }
        !          4468: 
        !          4469:        if (alias) {
        !          4470:                trait_alias->alias = Z_STRVAL(alias->u.constant);
        !          4471:                trait_alias->alias_len = Z_STRLEN(alias->u.constant);
        !          4472:        } else {
        !          4473:                trait_alias->alias = NULL;
        !          4474:        }
        !          4475:        trait_alias->function = NULL;
        !          4476: 
        !          4477:        result->u.op.ptr = trait_alias;
        !          4478: }
        !          4479: /* }}} */
        !          4480: 
        !          4481: void zend_prepare_trait_precedence(znode *result, znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
        !          4482: {
        !          4483:        zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
        !          4484: 
        !          4485:        trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
        !          4486:        trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
        !          4487: 
        !          4488:        trait_precedence->function = NULL;
        !          4489: 
        !          4490:        result->u.op.ptr = trait_precedence;
        !          4491: }
        !          4492: /* }}} */
        !          4493: 
        !          4494: ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
1.1       misho    4495: {
                   4496:        zend_class_entry *ce, **pce;
1.1.1.2 ! misho    4497:        zval *op1, *op2;
1.1       misho    4498: 
1.1.1.2 ! misho    4499:        if (compile_time) {
        !          4500:                op1 = &CONSTANT_EX(op_array, opline->op1.constant);
        !          4501:                op2 = &CONSTANT_EX(op_array, opline->op2.constant);
        !          4502:        } else {
        !          4503:                op1 = opline->op1.zv;
        !          4504:                op2 = opline->op2.zv;
        !          4505:        }
        !          4506:        if (zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce)==FAILURE) {
        !          4507:                zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
1.1       misho    4508:                return NULL;
                   4509:        } else {
                   4510:                ce = *pce;
                   4511:        }
                   4512:        ce->refcount++;
1.1.1.2 ! misho    4513:        if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
1.1       misho    4514:                ce->refcount--;
                   4515:                if (!compile_time) {
                   4516:                        /* If we're in compile time, in practice, it's quite possible
                   4517:                         * that we'll never reach this class declaration at runtime,
                   4518:                         * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
                   4519:                         * approach to work.
                   4520:                         */
                   4521:                        zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
                   4522:                }
                   4523:                return NULL;
                   4524:        } else {
                   4525:                if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES))) {
                   4526:                        zend_verify_abstract_class(ce TSRMLS_CC);
                   4527:                }
                   4528:                return ce;
                   4529:        }
                   4530: }
                   4531: /* }}} */
                   4532: 
1.1.1.2 ! misho    4533: ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) /* {{{ */
1.1       misho    4534: {
                   4535:        zend_class_entry *ce, **pce;
                   4536:        int found_ce;
1.1.1.2 ! misho    4537:        zval *op1, *op2;
1.1       misho    4538: 
1.1.1.2 ! misho    4539:        if (compile_time) {
        !          4540:                op1 = &CONSTANT_EX(op_array, opline->op1.constant);
        !          4541:                op2 = &CONSTANT_EX(op_array, opline->op2.constant);
        !          4542:        } else {
        !          4543:                op1 = opline->op1.zv;
        !          4544:                op2 = opline->op2.zv;
        !          4545:        }
        !          4546: 
        !          4547:        found_ce = zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce);
1.1       misho    4548: 
                   4549:        if (found_ce == FAILURE) {
                   4550:                if (!compile_time) {
                   4551:                        /* If we're in compile time, in practice, it's quite possible
                   4552:                         * that we'll never reach this class declaration at runtime,
                   4553:                         * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
                   4554:                         * approach to work.
                   4555:                         */
1.1.1.2 ! misho    4556:                        zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", Z_STRVAL_P(op2));
1.1       misho    4557:                }
                   4558:                return NULL;
                   4559:        } else {
                   4560:                ce = *pce;
                   4561:        }
                   4562: 
                   4563:        if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
                   4564:                zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
1.1.1.2 ! misho    4565:        } else if ((parent_ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
        !          4566:                zend_error(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ce->name, parent_ce->name);
1.1       misho    4567:        }
                   4568: 
                   4569:        zend_do_inheritance(ce, parent_ce TSRMLS_CC);
                   4570: 
                   4571:        ce->refcount++;
                   4572: 
                   4573:        /* Register the derived class */
1.1.1.2 ! misho    4574:        if (zend_hash_quick_add(class_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
1.1       misho    4575:                zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
                   4576:        }
                   4577:        return ce;
                   4578: }
                   4579: /* }}} */
                   4580: 
                   4581: void zend_do_early_binding(TSRMLS_D) /* {{{ */
                   4582: {
                   4583:        zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
                   4584:        HashTable *table;
                   4585: 
                   4586:        while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
                   4587:                opline--;
                   4588:        }
                   4589: 
                   4590:        switch (opline->opcode) {
                   4591:                case ZEND_DECLARE_FUNCTION:
1.1.1.2 ! misho    4592:                        if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
1.1       misho    4593:                                return;
                   4594:                        }
                   4595:                        table = CG(function_table);
                   4596:                        break;
                   4597:                case ZEND_DECLARE_CLASS:
1.1.1.2 ! misho    4598:                        if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
1.1       misho    4599:                                return;
                   4600:                        }
                   4601:                        table = CG(class_table);
                   4602:                        break;
                   4603:                case ZEND_DECLARE_INHERITED_CLASS:
                   4604:                        {
                   4605:                                zend_op *fetch_class_opline = opline-1;
1.1.1.2 ! misho    4606:                                zval *parent_name;
1.1       misho    4607:                                zend_class_entry **pce;
                   4608: 
1.1.1.2 ! misho    4609:                                parent_name = &CONSTANT(fetch_class_opline->op2.constant);
1.1       misho    4610:                                if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
1.1.1.2 ! misho    4611:                                    ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
        !          4612:                                     ((*pce)->type == ZEND_INTERNAL_CLASS))) {
        !          4613:                                    if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
1.1       misho    4614:                                                zend_uint *opline_num = &CG(active_op_array)->early_binding;
                   4615: 
                   4616:                                                while (*opline_num != -1) {
1.1.1.2 ! misho    4617:                                                        opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
1.1       misho    4618:                                                }
                   4619:                                                *opline_num = opline - CG(active_op_array)->opcodes;
                   4620:                                                opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
1.1.1.2 ! misho    4621:                                                opline->result_type = IS_UNUSED;
        !          4622:                                                opline->result.opline_num = -1;
1.1       misho    4623:                                        }
                   4624:                                        return;
                   4625:                                }
1.1.1.2 ! misho    4626:                                if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
1.1       misho    4627:                                        return;
                   4628:                                }
                   4629:                                /* clear unnecessary ZEND_FETCH_CLASS opcode */
1.1.1.2 ! misho    4630:                                zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
1.1       misho    4631:                                MAKE_NOP(fetch_class_opline);
                   4632: 
                   4633:                                table = CG(class_table);
                   4634:                                break;
                   4635:                        }
                   4636:                case ZEND_VERIFY_ABSTRACT_CLASS:
                   4637:                case ZEND_ADD_INTERFACE:
1.1.1.2 ! misho    4638:                case ZEND_ADD_TRAIT:
        !          4639:                case ZEND_BIND_TRAITS:
1.1       misho    4640:                        /* We currently don't early-bind classes that implement interfaces */
1.1.1.2 ! misho    4641:                        /* Classes with traits are handled exactly the same, no early-bind here */
1.1       misho    4642:                        return;
                   4643:                default:
                   4644:                        zend_error(E_COMPILE_ERROR, "Invalid binding type");
                   4645:                        return;
                   4646:        }
                   4647: 
1.1.1.2 ! misho    4648:        zend_hash_quick_del(table, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)), Z_HASH_P(&CONSTANT(opline->op1.constant)));
        !          4649:        zend_del_literal(CG(active_op_array), opline->op1.constant);
        !          4650:        zend_del_literal(CG(active_op_array), opline->op2.constant);
1.1       misho    4651:        MAKE_NOP(opline);
                   4652: }
                   4653: /* }}} */
                   4654: 
                   4655: ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
                   4656: {
                   4657:        if (op_array->early_binding != -1) {
                   4658:                zend_bool orig_in_compilation = CG(in_compilation);
                   4659:                zend_uint opline_num = op_array->early_binding;
                   4660:                zend_class_entry **pce;
                   4661: 
                   4662:                CG(in_compilation) = 1;
                   4663:                while (opline_num != -1) {
1.1.1.2 ! misho    4664:                        if (zend_lookup_class(Z_STRVAL_P(op_array->opcodes[opline_num-1].op2.zv), Z_STRLEN_P(op_array->opcodes[opline_num-1].op2.zv), &pce TSRMLS_CC) == SUCCESS) {
        !          4665:                                do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), *pce, 0 TSRMLS_CC);
1.1       misho    4666:                        }
1.1.1.2 ! misho    4667:                        opline_num = op_array->opcodes[opline_num].result.opline_num;
1.1       misho    4668:                }
                   4669:                CG(in_compilation) = orig_in_compilation;
                   4670:        }
                   4671: }
                   4672: /* }}} */
                   4673: 
                   4674: void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
                   4675: {
                   4676:        int next_op_number = get_next_op_number(CG(active_op_array));
                   4677:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4678: 
                   4679:        opline->opcode = ZEND_JMPNZ_EX;
                   4680:        if (expr1->op_type == IS_TMP_VAR) {
1.1.1.2 ! misho    4681:                SET_NODE(opline->result, expr1);
1.1       misho    4682:        } else {
1.1.1.2 ! misho    4683:                opline->result.var = get_temporary_variable(CG(active_op_array));
        !          4684:                opline->result_type = IS_TMP_VAR;
1.1       misho    4685:        }
1.1.1.2 ! misho    4686:        SET_NODE(opline->op1, expr1);
1.1       misho    4687:        SET_UNUSED(opline->op2);
                   4688: 
1.1.1.2 ! misho    4689:        op_token->u.op.opline_num = next_op_number;
1.1       misho    4690: 
1.1.1.2 ! misho    4691:        GET_NODE(expr1, opline->result);
1.1       misho    4692: }
                   4693: /* }}} */
                   4694: 
                   4695: void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
                   4696: {
                   4697:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4698: 
                   4699:        *result = *expr1; /* we saved the original result in expr1 */
                   4700:        opline->opcode = ZEND_BOOL;
1.1.1.2 ! misho    4701:        SET_NODE(opline->result, result);
        !          4702:        SET_NODE(opline->op1, expr2);
1.1       misho    4703:        SET_UNUSED(opline->op2);
                   4704: 
1.1.1.2 ! misho    4705:        CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    4706: }
                   4707: /* }}} */
                   4708: 
                   4709: void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
                   4710: {
                   4711:        int next_op_number = get_next_op_number(CG(active_op_array));
                   4712:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4713: 
                   4714:        opline->opcode = ZEND_JMPZ_EX;
                   4715:        if (expr1->op_type == IS_TMP_VAR) {
1.1.1.2 ! misho    4716:                SET_NODE(opline->result, expr1);
1.1       misho    4717:        } else {
1.1.1.2 ! misho    4718:                opline->result.var = get_temporary_variable(CG(active_op_array));
        !          4719:                opline->result_type = IS_TMP_VAR;
1.1       misho    4720:        }
1.1.1.2 ! misho    4721:        SET_NODE(opline->op1, expr1);
1.1       misho    4722:        SET_UNUSED(opline->op2);
                   4723: 
1.1.1.2 ! misho    4724:        op_token->u.op.opline_num = next_op_number;
1.1       misho    4725: 
1.1.1.2 ! misho    4726:        GET_NODE(expr1, opline->result);
1.1       misho    4727: }
                   4728: /* }}} */
                   4729: 
                   4730: void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
                   4731: {
                   4732:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4733: 
                   4734:        *result = *expr1; /* we saved the original result in expr1 */
                   4735:        opline->opcode = ZEND_BOOL;
1.1.1.2 ! misho    4736:        SET_NODE(opline->result, result);
        !          4737:        SET_NODE(opline->op1, expr2);
1.1       misho    4738:        SET_UNUSED(opline->op2);
                   4739: 
1.1.1.2 ! misho    4740:        CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    4741: }
                   4742: /* }}} */
                   4743: 
                   4744: void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
                   4745: {
                   4746:        do_begin_loop(TSRMLS_C);
                   4747:        INC_BPC(CG(active_op_array));
                   4748: }
                   4749: /* }}} */
                   4750: 
                   4751: void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC) /* {{{ */
                   4752: {
                   4753:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4754: 
                   4755:        opline->opcode = ZEND_JMPNZ;
1.1.1.2 ! misho    4756:        SET_NODE(opline->op1, expr);
        !          4757:        opline->op2.opline_num = do_token->u.op.opline_num;
1.1       misho    4758:        SET_UNUSED(opline->op2);
                   4759: 
1.1.1.2 ! misho    4760:        do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
1.1       misho    4761: 
                   4762:        DEC_BPC(CG(active_op_array));
                   4763: }
                   4764: /* }}} */
                   4765: 
                   4766: void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
                   4767: {
                   4768:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4769: 
                   4770:        opline->opcode = op;
1.1.1.2 ! misho    4771:        opline->op1.opline_num = CG(context).current_brk_cont;
1.1       misho    4772:        SET_UNUSED(opline->op1);
                   4773:        if (expr) {
1.1.1.2 ! misho    4774:                if (expr->op_type != IS_CONST) {
        !          4775:                        zend_error(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
        !          4776:                } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
        !          4777:                        zend_error(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
        !          4778:                }
        !          4779:                SET_NODE(opline->op2, expr);
1.1       misho    4780:        } else {
1.1.1.2 ! misho    4781:                LITERAL_LONG(opline->op2, 1);
        !          4782:                opline->op2_type = IS_CONST;
1.1       misho    4783:        }
                   4784: }
                   4785: /* }}} */
                   4786: 
                   4787: void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
                   4788: {
                   4789:        zend_switch_entry switch_entry;
                   4790: 
                   4791:        switch_entry.cond = *cond;
                   4792:        switch_entry.default_case = -1;
                   4793:        switch_entry.control_var = -1;
                   4794:        zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
                   4795: 
                   4796:        do_begin_loop(TSRMLS_C);
                   4797: 
                   4798:        INC_BPC(CG(active_op_array));
                   4799: }
                   4800: /* }}} */
                   4801: 
                   4802: void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
                   4803: {
                   4804:        zend_op *opline;
                   4805:        zend_switch_entry *switch_entry_ptr;
                   4806: 
                   4807:        zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
                   4808: 
                   4809:        /* add code to jmp to default case */
                   4810:        if (switch_entry_ptr->default_case != -1) {
                   4811:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4812:                opline->opcode = ZEND_JMP;
                   4813:                SET_UNUSED(opline->op1);
                   4814:                SET_UNUSED(opline->op2);
1.1.1.2 ! misho    4815:                opline->op1.opline_num = switch_entry_ptr->default_case;
1.1       misho    4816:        }
                   4817: 
                   4818:        if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
                   4819:                int next_op_number = get_next_op_number(CG(active_op_array));
                   4820: 
1.1.1.2 ! misho    4821:                CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
1.1       misho    4822:        }
                   4823: 
                   4824:        /* remember break/continue loop information */
1.1.1.2 ! misho    4825:        CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
        !          4826:        CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
1.1       misho    4827: 
                   4828:        if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
                   4829:                /* emit free for the switch condition*/
                   4830:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4831:                opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
1.1.1.2 ! misho    4832:                SET_NODE(opline->op1, &switch_entry_ptr->cond);
1.1       misho    4833:                SET_UNUSED(opline->op2);
                   4834:        }
                   4835:        if (switch_entry_ptr->cond.op_type == IS_CONST) {
                   4836:                zval_dtor(&switch_entry_ptr->cond.u.constant);
                   4837:        }
                   4838: 
                   4839:        zend_stack_del_top(&CG(switch_cond_stack));
                   4840: 
                   4841:        DEC_BPC(CG(active_op_array));
                   4842: }
                   4843: /* }}} */
                   4844: 
                   4845: void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC) /* {{{ */
                   4846: {
                   4847:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4848:        int next_op_number;
                   4849:        zend_switch_entry *switch_entry_ptr;
                   4850:        znode result;
                   4851: 
                   4852:        zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
                   4853: 
                   4854:        if (switch_entry_ptr->control_var == -1) {
                   4855:                switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
                   4856:        }
                   4857:        opline->opcode = ZEND_CASE;
1.1.1.2 ! misho    4858:        opline->result.var = switch_entry_ptr->control_var;
        !          4859:        opline->result_type = IS_TMP_VAR;
        !          4860:        SET_NODE(opline->op1, &switch_entry_ptr->cond);
        !          4861:        SET_NODE(opline->op2, case_expr);
        !          4862:        if (opline->op1_type == IS_CONST) {
        !          4863:                zval_copy_ctor(&CONSTANT(opline->op1.constant));
1.1       misho    4864:        }
1.1.1.2 ! misho    4865:        GET_NODE(&result, opline->result);
1.1       misho    4866: 
                   4867:        next_op_number = get_next_op_number(CG(active_op_array));
                   4868:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4869:        opline->opcode = ZEND_JMPZ;
1.1.1.2 ! misho    4870:        SET_NODE(opline->op1, &result);
1.1       misho    4871:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    4872:        case_token->u.op.opline_num = next_op_number;
1.1       misho    4873: 
                   4874:        if (case_list->op_type==IS_UNUSED) {
                   4875:                return;
                   4876:        }
                   4877:        next_op_number = get_next_op_number(CG(active_op_array));
1.1.1.2 ! misho    4878:        CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
1.1       misho    4879: }
                   4880: /* }}} */
                   4881: 
                   4882: void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
                   4883: {
                   4884:        int next_op_number = get_next_op_number(CG(active_op_array));
                   4885:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4886: 
                   4887:        opline->opcode = ZEND_JMP;
                   4888:        SET_UNUSED(opline->op1);
                   4889:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    4890:        result->u.op.opline_num = next_op_number;
1.1       misho    4891: 
1.1.1.2 ! misho    4892:        switch (CG(active_op_array)->opcodes[case_token->u.op.opline_num].opcode) {
1.1       misho    4893:                case ZEND_JMP:
1.1.1.2 ! misho    4894:                        CG(active_op_array)->opcodes[case_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    4895:                        break;
                   4896:                case ZEND_JMPZ:
1.1.1.2 ! misho    4897:                        CG(active_op_array)->opcodes[case_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    4898:                        break;
                   4899:        }
                   4900: }
                   4901: /* }}} */
                   4902: 
                   4903: void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
                   4904: {
                   4905:        int next_op_number = get_next_op_number(CG(active_op_array));
                   4906:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   4907:        zend_switch_entry *switch_entry_ptr;
                   4908: 
                   4909:        zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
                   4910: 
                   4911:        opline->opcode = ZEND_JMP;
                   4912:        SET_UNUSED(opline->op1);
                   4913:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    4914:        default_token->u.op.opline_num = next_op_number;
1.1       misho    4915: 
                   4916:        next_op_number = get_next_op_number(CG(active_op_array));
                   4917:        switch_entry_ptr->default_case = next_op_number;
                   4918: 
                   4919:        if (case_list->op_type==IS_UNUSED) {
                   4920:                return;
                   4921:        }
1.1.1.2 ! misho    4922:        CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
1.1       misho    4923: }
                   4924: /* }}} */
                   4925: 
                   4926: void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
                   4927: {
                   4928:        zend_op *opline;
                   4929:        int doing_inheritance = 0;
                   4930:        zend_class_entry *new_class_entry;
                   4931:        char *lcname;
                   4932:        int error = 0;
1.1.1.2 ! misho    4933:        zval **ns_name, key;
1.1       misho    4934: 
                   4935:        if (CG(active_class_entry)) {
                   4936:                zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
                   4937:                return;
                   4938:        }
                   4939: 
                   4940:        lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
                   4941: 
                   4942:        if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
                   4943:                efree(lcname);
1.1.1.2 ! misho    4944:                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", Z_STRVAL(class_name->u.constant));
1.1       misho    4945:        }
                   4946: 
                   4947:        /* Class name must not conflict with import names */
                   4948:        if (CG(current_import) &&
1.1.1.2 ! misho    4949:            zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
1.1       misho    4950:                error = 1;
                   4951:        }
                   4952: 
                   4953:        if (CG(current_namespace)) {
                   4954:                /* Prefix class name with name of current namespace */
                   4955:                znode tmp;
                   4956: 
                   4957:                tmp.u.constant = *CG(current_namespace);
                   4958:                zval_copy_ctor(&tmp.u.constant);
                   4959:                zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
                   4960:                class_name = &tmp;
                   4961:                efree(lcname);
                   4962:                lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
                   4963:        }
                   4964: 
                   4965:        if (error) {
                   4966:                char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
                   4967: 
                   4968:                if (Z_STRLEN_PP(ns_name) != Z_STRLEN(class_name->u.constant) ||
                   4969:                        memcmp(tmp, lcname, Z_STRLEN(class_name->u.constant))) {
                   4970:                        zend_error(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
                   4971:                }
                   4972:                efree(tmp);
                   4973:        }
                   4974: 
                   4975:        new_class_entry = emalloc(sizeof(zend_class_entry));
                   4976:        new_class_entry->type = ZEND_USER_CLASS;
1.1.1.2 ! misho    4977:        new_class_entry->name = zend_new_interned_string(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant) + 1, 1 TSRMLS_CC);
        !          4978:        new_class_entry->name_length = Z_STRLEN(class_name->u.constant);
1.1       misho    4979: 
                   4980:        zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
1.1.1.2 ! misho    4981:        new_class_entry->info.user.filename = zend_get_compiled_filename(TSRMLS_C);
        !          4982:        new_class_entry->info.user.line_start = class_token->u.op.opline_num;
        !          4983:        new_class_entry->ce_flags |= class_token->EA;
1.1       misho    4984: 
                   4985:        if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
1.1.1.2 ! misho    4986:                switch (parent_class_name->EA) {
1.1       misho    4987:                        case ZEND_FETCH_CLASS_SELF:
                   4988:                                zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
                   4989:                                break;
                   4990:                        case ZEND_FETCH_CLASS_PARENT:
                   4991:                                zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
                   4992:                                break;
                   4993:                        case ZEND_FETCH_CLASS_STATIC:
                   4994:                                zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
                   4995:                                break;
                   4996:                        default:
                   4997:                                break;
                   4998:                }
                   4999:                doing_inheritance = 1;
                   5000:        }
                   5001: 
                   5002:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1.1.1.2 ! misho    5003:        opline->op1_type = IS_CONST;
        !          5004:        build_runtime_defined_function_key(&key, lcname, new_class_entry->name_length TSRMLS_CC);
        !          5005:        opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
        !          5006:        Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
1.1       misho    5007:        
1.1.1.2 ! misho    5008:        opline->op2_type = IS_CONST;
1.1       misho    5009: 
                   5010:        if (doing_inheritance) {
1.1.1.2 ! misho    5011:        /* Make sure a trait does not try to extend a class */
        !          5012:        if ((new_class_entry->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
        !          5013:            zend_error(E_COMPILE_ERROR, "A trait (%s) cannot extend a class. Traits can only be composed from other traits with the 'use' keyword. Error", new_class_entry->name);
        !          5014:        }
        !          5015:     
        !          5016:                opline->extended_value = parent_class_name->u.op.var;
1.1       misho    5017:                opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
                   5018:        } else {
                   5019:                opline->opcode = ZEND_DECLARE_CLASS;
                   5020:        }
                   5021: 
1.1.1.2 ! misho    5022:        LITERAL_STRINGL(opline->op2, lcname, new_class_entry->name_length, 0);
        !          5023:        CALCULATE_LITERAL_HASH(opline->op2.constant);
1.1       misho    5024:        
1.1.1.2 ! misho    5025:        zend_hash_quick_update(CG(class_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &new_class_entry, sizeof(zend_class_entry *), NULL);
1.1       misho    5026:        CG(active_class_entry) = new_class_entry;
                   5027: 
1.1.1.2 ! misho    5028:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5029:        opline->result_type = IS_VAR;
        !          5030:        GET_NODE(&CG(implementing_class), opline->result);
1.1       misho    5031: 
                   5032:        if (CG(doc_comment)) {
1.1.1.2 ! misho    5033:                CG(active_class_entry)->info.user.doc_comment = CG(doc_comment);
        !          5034:                CG(active_class_entry)->info.user.doc_comment_len = CG(doc_comment_len);
1.1       misho    5035:                CG(doc_comment) = NULL;
                   5036:                CG(doc_comment_len) = 0;
                   5037:        }
                   5038: }
                   5039: /* }}} */
                   5040: 
                   5041: static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
                   5042: {
                   5043:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5044: 
                   5045:        opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
1.1.1.2 ! misho    5046:        SET_NODE(opline->op1, &CG(implementing_class));
1.1       misho    5047:        SET_UNUSED(opline->op2);
                   5048: }
                   5049: /* }}} */
                   5050: 
                   5051: void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
                   5052: {
                   5053:        zend_class_entry *ce = CG(active_class_entry);
                   5054: 
                   5055:        if (ce->constructor) {
                   5056:                ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
                   5057:                if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
                   5058:                        zend_error(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
                   5059:                }
                   5060:        }
                   5061:        if (ce->destructor) {
                   5062:                ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
                   5063:                if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
                   5064:                        zend_error(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
                   5065:                }
                   5066:        }
                   5067:        if (ce->clone) {
                   5068:                ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
                   5069:                if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
                   5070:                        zend_error(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
                   5071:                }
                   5072:        }
                   5073: 
1.1.1.2 ! misho    5074:        ce->info.user.line_end = zend_get_compiled_lineno(TSRMLS_C);
        !          5075:        
        !          5076:        /* Check for traits and proceed like with interfaces.
        !          5077:         * The only difference will be a combined handling of them in the end.
        !          5078:         * Thus, we need another opcode here. */
        !          5079:        if (ce->num_traits > 0) {
        !          5080:                zend_op *opline;
        !          5081: 
        !          5082:                ce->traits = NULL;
        !          5083:                ce->num_traits = 0;
        !          5084:                ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
        !          5085: 
        !          5086:                /* opcode generation: */
        !          5087:                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        !          5088:                opline->opcode = ZEND_BIND_TRAITS;
        !          5089:                SET_NODE(opline->op1, &CG(implementing_class));
        !          5090:        }
1.1       misho    5091: 
                   5092:        if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
                   5093:                && ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) {
                   5094:                zend_verify_abstract_class(ce TSRMLS_CC);
                   5095:                if (ce->num_interfaces) {
                   5096:                        do_verify_abstract_class(TSRMLS_C);
                   5097:                }
                   5098:        }
                   5099:        /* Inherit interfaces; reset number to zero, we need it for above check and
                   5100:         * will restore it during actual implementation. 
                   5101:         * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
                   5102:         * zend_verify_abstract_class() */
                   5103:        if (ce->num_interfaces > 0) {
                   5104:                ce->interfaces = NULL;
                   5105:                ce->num_interfaces = 0;
                   5106:                ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
                   5107:        }
1.1.1.2 ! misho    5108: 
1.1       misho    5109:        CG(active_class_entry) = NULL;
                   5110: }
                   5111: /* }}} */
                   5112: 
                   5113: void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
                   5114: {
                   5115:        zend_op *opline;
                   5116: 
1.1.1.2 ! misho    5117:        /* Traits can not implement interfaces */
        !          5118:        if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
        !          5119:                zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface on '%s' since it is a Trait",
        !          5120:                                                         Z_STRVAL(interface_name->u.constant),
        !          5121:                                                         CG(active_class_entry)->name);
        !          5122:        }
        !          5123: 
1.1       misho    5124:        switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
                   5125:                case ZEND_FETCH_CLASS_SELF:
                   5126:                case ZEND_FETCH_CLASS_PARENT:
                   5127:                case ZEND_FETCH_CLASS_STATIC:
                   5128:                        zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
                   5129:                        break;
                   5130:                default:
                   5131:                        break;
                   5132:        }
                   5133: 
                   5134:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5135:        opline->opcode = ZEND_ADD_INTERFACE;
1.1.1.2 ! misho    5136:        SET_NODE(opline->op1, &CG(implementing_class));
        !          5137:        zend_resolve_class_name(interface_name, opline->extended_value, 0 TSRMLS_CC);
1.1       misho    5138:        opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
1.1.1.2 ! misho    5139:        opline->op2_type = IS_CONST;
        !          5140:        opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &interface_name->u.constant TSRMLS_CC);
1.1       misho    5141:        CG(active_class_entry)->num_interfaces++;
                   5142: }
                   5143: /* }}} */
                   5144: 
1.1.1.2 ! misho    5145: void zend_do_implements_trait(znode *trait_name TSRMLS_DC) /* {{{ */
        !          5146: {
        !          5147:        zend_op *opline;
        !          5148:        if ((CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
        !          5149:                zend_error(E_COMPILE_ERROR,
        !          5150:                                "Cannot use traits inside of interfaces. %s is used in %s",
        !          5151:                                Z_STRVAL(trait_name->u.constant), CG(active_class_entry)->name);
        !          5152:        }
        !          5153: 
        !          5154: 
        !          5155:        switch (zend_get_class_fetch_type(Z_STRVAL(trait_name->u.constant), Z_STRLEN(trait_name->u.constant))) {
        !          5156:                case ZEND_FETCH_CLASS_SELF:
        !          5157:                case ZEND_FETCH_CLASS_PARENT:
        !          5158:                case ZEND_FETCH_CLASS_STATIC:
        !          5159:                        zend_error(E_COMPILE_ERROR, "Cannot use '%s' as trait name as it is reserved", Z_STRVAL(trait_name->u.constant));
        !          5160:                        break;
        !          5161:                default:
        !          5162:                        break;
        !          5163:        }
        !          5164: 
        !          5165:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
        !          5166:        opline->opcode = ZEND_ADD_TRAIT;
        !          5167:        SET_NODE(opline->op1, &CG(implementing_class));
        !          5168:        zend_resolve_class_name(trait_name, opline->extended_value, 0 TSRMLS_CC);
        !          5169:        opline->extended_value = ZEND_FETCH_CLASS_TRAIT;
        !          5170:        opline->op2_type = IS_CONST;
        !          5171:        opline->op2.constant = zend_add_class_name_literal(CG(active_op_array), &trait_name->u.constant TSRMLS_CC);
        !          5172:        CG(active_class_entry)->num_traits++;
        !          5173: }
        !          5174: /* }}} */
        !          5175: 
1.1       misho    5176: ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
                   5177: {
                   5178:        char *prop_name;
                   5179:        int prop_name_length;
                   5180: 
                   5181:        prop_name_length = 1 + src1_length + 1 + src2_length;
                   5182:        prop_name = pemalloc(prop_name_length + 1, internal);
                   5183:        prop_name[0] = '\0';
                   5184:        memcpy(prop_name + 1, src1, src1_length+1);
                   5185:        memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
                   5186: 
                   5187:        *dest = prop_name;
                   5188:        *dest_length = prop_name_length;
                   5189: }
                   5190: /* }}} */
                   5191: 
                   5192: static int zend_strnlen(const char* s, int maxlen) /* {{{ */
                   5193: {
                   5194:        int len = 0;
                   5195:        while (*s++ && maxlen--) len++;
                   5196:        return len;
                   5197: }
                   5198: /* }}} */
                   5199: 
1.1.1.2 ! misho    5200: ZEND_API int zend_unmangle_property_name(const char *mangled_property, int len, const char **class_name, const char **prop_name) /* {{{ */
1.1       misho    5201: {
                   5202:        int class_name_len;
                   5203: 
                   5204:        *class_name = NULL;
                   5205: 
                   5206:        if (mangled_property[0]!=0) {
                   5207:                *prop_name = mangled_property;
                   5208:                return SUCCESS;
                   5209:        }
                   5210:        if (len < 3 || mangled_property[1]==0) {
                   5211:                zend_error(E_NOTICE, "Illegal member variable name");
                   5212:                *prop_name = mangled_property;
                   5213:                return FAILURE;
                   5214:        }
                   5215: 
                   5216:        class_name_len = zend_strnlen(mangled_property+1, --len - 1) + 1;
                   5217:        if (class_name_len >= len || mangled_property[class_name_len]!=0) {
                   5218:                zend_error(E_NOTICE, "Corrupt member variable name");
                   5219:                *prop_name = mangled_property;
                   5220:                return FAILURE;
                   5221:        }
                   5222:        *class_name = mangled_property+1;
                   5223:        *prop_name = (*class_name)+class_name_len;
                   5224:        return SUCCESS;
                   5225: }
                   5226: /* }}} */
                   5227: 
                   5228: void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
                   5229: {
                   5230:        zval *property;
                   5231:        zend_property_info *existing_property_info;
                   5232:        char *comment = NULL;
                   5233:        int comment_len = 0;
                   5234: 
                   5235:        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
                   5236:                zend_error(E_COMPILE_ERROR, "Interfaces may not include member variables");
                   5237:        }
                   5238: 
                   5239:        if (access_type & ZEND_ACC_ABSTRACT) {
                   5240:                zend_error(E_COMPILE_ERROR, "Properties cannot be declared abstract");
                   5241:        }
                   5242: 
                   5243:        if (access_type & ZEND_ACC_FINAL) {
                   5244:                zend_error(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
1.1.1.2 ! misho    5245:                                   CG(active_class_entry)->name, var_name->u.constant.value.str.val);
1.1       misho    5246:        }
                   5247: 
                   5248:        if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
1.1.1.2 ! misho    5249:                zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
1.1       misho    5250:        }
                   5251:        ALLOC_ZVAL(property);
                   5252: 
                   5253:        if (value) {
                   5254:                *property = value->u.constant;
                   5255:        } else {
                   5256:                INIT_PZVAL(property);
                   5257:                Z_TYPE_P(property) = IS_NULL;
                   5258:        }
                   5259: 
                   5260:        if (CG(doc_comment)) {
                   5261:                comment = CG(doc_comment);
                   5262:                comment_len = CG(doc_comment_len);
                   5263:                CG(doc_comment) = NULL;
                   5264:                CG(doc_comment_len) = 0;
                   5265:        }
                   5266: 
1.1.1.2 ! misho    5267:        zend_declare_property_ex(CG(active_class_entry), zend_new_interned_string(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len + 1, 0 TSRMLS_CC), var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
1.1       misho    5268:        efree(var_name->u.constant.value.str.val);
                   5269: }
                   5270: /* }}} */
                   5271: 
                   5272: void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC) /* {{{ */
                   5273: {
                   5274:        zval *property;
1.1.1.2 ! misho    5275:        const char *cname = NULL;
        !          5276:        int result;
1.1       misho    5277: 
                   5278:        if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
                   5279:                zend_error(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
1.1.1.2 ! misho    5280:                return;
        !          5281:        }
        !          5282:        if ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
        !          5283:                zend_error(E_COMPILE_ERROR, "Traits cannot have constants");
        !          5284:                return;
1.1       misho    5285:        }
                   5286: 
                   5287:        ALLOC_ZVAL(property);
                   5288:        *property = value->u.constant;
1.1.1.2 ! misho    5289:        
        !          5290:        cname = zend_new_interned_string(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, 0 TSRMLS_CC);
1.1       misho    5291: 
1.1.1.2 ! misho    5292:        if (IS_INTERNED(cname)) {
        !          5293:                result = zend_hash_quick_add(&CG(active_class_entry)->constants_table, cname, var_name->u.constant.value.str.len+1, INTERNED_HASH(cname), &property, sizeof(zval *), NULL);
        !          5294:        } else {
        !          5295:                result = zend_hash_add(&CG(active_class_entry)->constants_table, cname, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
        !          5296:        }
        !          5297:        if (result == FAILURE) {
1.1       misho    5298:                FREE_ZVAL(property);
                   5299:                zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
                   5300:        }
                   5301:        FREE_PNODE(var_name);
                   5302:        
                   5303:        if (CG(doc_comment)) {
                   5304:                efree(CG(doc_comment));
                   5305:                CG(doc_comment) = NULL;
                   5306:                CG(doc_comment_len) = 0;
                   5307:        }
                   5308: }
                   5309: /* }}} */
                   5310: 
                   5311: void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC) /* {{{ */
                   5312: {
                   5313:        zend_op opline;
                   5314:        zend_llist *fetch_list_ptr;
                   5315: 
                   5316:        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
                   5317: 
                   5318:        if (object->op_type == IS_CV) {
1.1.1.2 ! misho    5319:                if (object->u.op.var == CG(active_op_array)->this_var) {
        !          5320:                        object->op_type = IS_UNUSED; /* this means $this for objects */
1.1       misho    5321:                }
                   5322:        } else if (fetch_list_ptr->count == 1) {
                   5323:                zend_llist_element *le = fetch_list_ptr->head;
                   5324:                zend_op *opline_ptr = (zend_op *) le->data;
                   5325: 
                   5326:                if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
1.1.1.2 ! misho    5327:                        zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
1.1       misho    5328:                        SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
1.1.1.2 ! misho    5329:                        SET_NODE(opline_ptr->op2, property);
1.1       misho    5330:                        /* if it was usual fetch, we change it to object fetch */
                   5331:                        switch (opline_ptr->opcode) {
                   5332:                                case ZEND_FETCH_W:
                   5333:                                        opline_ptr->opcode = ZEND_FETCH_OBJ_W;
                   5334:                                        break;
                   5335:                                case ZEND_FETCH_R:
                   5336:                                        opline_ptr->opcode = ZEND_FETCH_OBJ_R;
                   5337:                                        break;
                   5338:                                case ZEND_FETCH_RW:
                   5339:                                        opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
                   5340:                                        break;
                   5341:                                case ZEND_FETCH_IS:
                   5342:                                        opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
                   5343:                                        break;
                   5344:                                case ZEND_FETCH_UNSET:
                   5345:                                        opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
                   5346:                                        break;
                   5347:                                case ZEND_FETCH_FUNC_ARG:
                   5348:                                        opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
                   5349:                                        break;
                   5350:                        }
1.1.1.2 ! misho    5351:                        if (opline_ptr->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline_ptr->op2.constant)) == IS_STRING) {
        !          5352:                                CALCULATE_LITERAL_HASH(opline_ptr->op2.constant);
        !          5353:                                GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op2.constant);
        !          5354:                        }
        !          5355:                        GET_NODE(result, opline_ptr->result);
1.1       misho    5356:                        return;
                   5357:                }
                   5358:        }
                   5359: 
1.1.1.2 ! misho    5360:        if (zend_is_function_or_method_call(object)) {
        !          5361:                init_op(&opline TSRMLS_CC);
        !          5362:                opline.opcode = ZEND_SEPARATE;
        !          5363:                SET_NODE(opline.op1, object);
        !          5364:                SET_UNUSED(opline.op2);
        !          5365:                opline.result_type = IS_VAR;
        !          5366:                opline.result.var = opline.op1.var;
        !          5367:                zend_llist_add_element(fetch_list_ptr, &opline);
        !          5368:        }
        !          5369: 
1.1       misho    5370:        init_op(&opline TSRMLS_CC);
                   5371:        opline.opcode = ZEND_FETCH_OBJ_W;       /* the backpatching routine assumes W */
1.1.1.2 ! misho    5372:        opline.result_type = IS_VAR;
        !          5373:        opline.result.var = get_temporary_variable(CG(active_op_array));
        !          5374:        SET_NODE(opline.op1, object);
        !          5375:        SET_NODE(opline.op2, property);
        !          5376:        if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
        !          5377:                CALCULATE_LITERAL_HASH(opline.op2.constant);
        !          5378:                GET_POLYMORPHIC_CACHE_SLOT(opline.op2.constant);
        !          5379:        }
        !          5380:        GET_NODE(result, opline.result);
1.1       misho    5381: 
                   5382:        zend_llist_add_element(fetch_list_ptr, &opline);
                   5383: }
                   5384: /* }}} */
                   5385: 
                   5386: void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
                   5387: {
                   5388:        char *name, *cfilename;
                   5389:        char haltoff[] = "__COMPILER_HALT_OFFSET__";
                   5390:        int len, clen;
                   5391:        
                   5392:        if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
                   5393:                zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope");
                   5394:        }
                   5395:        
                   5396:        cfilename = zend_get_compiled_filename(TSRMLS_C);
                   5397:        clen = strlen(cfilename);
                   5398:        zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
                   5399:        zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
                   5400:        pefree(name, 0);
                   5401:        
                   5402:        if (CG(in_namespace)) {
                   5403:                zend_do_end_namespace(TSRMLS_C);
                   5404:        }
                   5405: }
                   5406: /* }}} */
                   5407: 
                   5408: void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
                   5409: {
                   5410:        zend_stack_push(&CG(object_stack), object, sizeof(znode));
                   5411: }
                   5412: /* }}} */
                   5413: 
                   5414: void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */
                   5415: {
                   5416:        if (object) {
                   5417:                znode *tmp;
                   5418: 
                   5419:                zend_stack_top(&CG(object_stack), (void **) &tmp);
                   5420:                *object = *tmp;
                   5421:        }
                   5422:        zend_stack_del_top(&CG(object_stack));
                   5423: }
                   5424: /* }}} */
                   5425: 
                   5426: void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
                   5427: {
                   5428:        zend_op *opline;
                   5429:        unsigned char *ptr = NULL;
                   5430: 
1.1.1.2 ! misho    5431:        new_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    5432:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5433:        opline->opcode = ZEND_NEW;
1.1.1.2 ! misho    5434:        opline->result_type = IS_VAR;
        !          5435:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5436:        SET_NODE(opline->op1, class_type);
1.1       misho    5437:        SET_UNUSED(opline->op2);
                   5438: 
                   5439:        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
                   5440: }
                   5441: /* }}} */
                   5442: 
                   5443: void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC) /* {{{ */
                   5444: {
                   5445:        znode ctor_result;
                   5446: 
                   5447:        zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
                   5448:        zend_do_free(&ctor_result TSRMLS_CC);
                   5449: 
1.1.1.2 ! misho    5450:        CG(active_op_array)->opcodes[new_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
        !          5451:        GET_NODE(result, CG(active_op_array)->opcodes[new_token->u.op.opline_num].result);
1.1       misho    5452: }
                   5453: /* }}} */
                   5454: 
                   5455: static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
                   5456: {
                   5457:        zend_constant *c = NULL;
                   5458: 
                   5459:        if (Z_STRVAL_P(const_name)[0] == '\\') {
                   5460:                if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name), (void **) &c) == FAILURE) {
                   5461:                        char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1);
                   5462: 
                   5463:                        if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name), (void **) &c)==SUCCESS) {
                   5464:                                if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
                   5465:                                        efree(lookup_name);
                   5466:                                        return c;
                   5467:                                }
                   5468:                        }
                   5469:                        efree(lookup_name);
                   5470:                        return NULL;
                   5471:                }
                   5472:        } else if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)+1, (void **) &c) == FAILURE) {
                   5473:                char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name));
                   5474:                 
                   5475:                if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
                   5476:                        if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
                   5477:                                efree(lookup_name);
                   5478:                                return c;
                   5479:                        }
                   5480:                }
                   5481:                efree(lookup_name);
                   5482:                return NULL;
                   5483:        }
                   5484:        if (c->flags & CONST_CT_SUBST) {
                   5485:                return c;
                   5486:        }
                   5487:        if (all_internal_constants_substitution &&
1.1.1.2 ! misho    5488:            (c->flags & CONST_PERSISTENT) &&
        !          5489:            !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
        !          5490:            Z_TYPE(c->value) != IS_CONSTANT &&
        !          5491:            Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
1.1       misho    5492:                return c;
                   5493:        }
                   5494:        return NULL;
                   5495: }
                   5496: /* }}} */
                   5497: 
                   5498: static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
                   5499: {
                   5500:        zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
                   5501: 
                   5502:        if (c) {
                   5503:                zval_dtor(const_name);
                   5504:                result->op_type = IS_CONST;
                   5505:                result->u.constant = c->value;
                   5506:                zval_copy_ctor(&result->u.constant);
                   5507:                INIT_PZVAL(&result->u.constant);
                   5508:                return 1;
                   5509:        }
                   5510:        return 0;
                   5511: }
                   5512: /* }}} */
                   5513: 
                   5514: void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
                   5515: {
                   5516:        znode tmp;
                   5517:        zend_op *opline;
                   5518:        int type;
                   5519:        char *compound;
                   5520:        ulong fetch_type = 0;
                   5521: 
                   5522:        if (constant_container) {
                   5523:                switch (mode) {
                   5524:                        case ZEND_CT:
                   5525:                                /* this is a class constant */
                   5526:                                type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant));
                   5527:        
                   5528:                                if (ZEND_FETCH_CLASS_STATIC == type) {
                   5529:                                        zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
                   5530:                                } else if (ZEND_FETCH_CLASS_DEFAULT == type) {
1.1.1.2 ! misho    5531:                                        zend_resolve_class_name(constant_container, fetch_type, 1 TSRMLS_CC);
1.1       misho    5532:                                }
                   5533:                                zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
                   5534:                                *result = *constant_container;
                   5535:                                result->u.constant.type = IS_CONSTANT | fetch_type;
                   5536:                                break;
                   5537:                        case ZEND_RT:
                   5538:                                if (constant_container->op_type == IS_CONST &&
                   5539:                                ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
1.1.1.2 ! misho    5540:                                        zend_resolve_class_name(constant_container, fetch_type, 1 TSRMLS_CC);
1.1       misho    5541:                                } else {
                   5542:                                        zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
                   5543:                                        constant_container = &tmp;
                   5544:                                }
                   5545:                                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5546:                                opline->opcode = ZEND_FETCH_CONSTANT;
1.1.1.2 ! misho    5547:                                opline->result_type = IS_TMP_VAR;
        !          5548:                                opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5549:                                if (constant_container->op_type == IS_CONST) {
        !          5550:                                        opline->op1_type = IS_CONST;
        !          5551:                                        opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &constant_container->u.constant TSRMLS_CC);
        !          5552:                                } else {
        !          5553:                                        SET_NODE(opline->op1, constant_container);
        !          5554:                                }
        !          5555:                                SET_NODE(opline->op2, constant_name);
        !          5556:                                CALCULATE_LITERAL_HASH(opline->op2.constant);
        !          5557:                                if (opline->op1_type == IS_CONST) {
        !          5558:                                        GET_CACHE_SLOT(opline->op2.constant);
        !          5559:                                } else {
        !          5560:                                        GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
        !          5561:                                }
        !          5562:                                GET_NODE(result, opline->result);
1.1       misho    5563:                                break;
                   5564:                }
                   5565:                return;
                   5566:        }
                   5567:        /* namespace constant */
                   5568:        /* only one that did not contain \ from the start can be converted to string if unknown */
                   5569:        switch (mode) {
                   5570:                case ZEND_CT:
                   5571:                        compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
                   5572:                        /* this is a namespace constant, or an unprefixed constant */
                   5573: 
                   5574:                        if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
                   5575:                                break;
                   5576:                        }
                   5577: 
                   5578:                        zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
                   5579: 
                   5580:                        if(!compound) {
                   5581:                                fetch_type |= IS_CONSTANT_UNQUALIFIED;
                   5582:                        }
                   5583: 
                   5584:                        *result = *constant_name;
                   5585:                        result->u.constant.type = IS_CONSTANT | fetch_type;
                   5586:                        break;
                   5587:                case ZEND_RT:
                   5588:                        compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
                   5589: 
                   5590:                        zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
                   5591:                        
                   5592:                        if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
                   5593:                                break;
                   5594:                        }
                   5595: 
                   5596:                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5597:                        opline->opcode = ZEND_FETCH_CONSTANT;
1.1.1.2 ! misho    5598:                        opline->result_type = IS_TMP_VAR;
        !          5599:                        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5600:                        GET_NODE(result, opline->result);
1.1       misho    5601:                        SET_UNUSED(opline->op1);
1.1.1.2 ! misho    5602:                        opline->op2_type = IS_CONST;
        !          5603:                        if (compound) {
1.1       misho    5604:                                /* the name is unambiguous */
                   5605:                                opline->extended_value = 0;
1.1.1.2 ! misho    5606:                                opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
        !          5607:                        } else {                                
1.1       misho    5608:                                opline->extended_value = IS_CONSTANT_UNQUALIFIED;
1.1.1.2 ! misho    5609:                                if (CG(current_namespace)) {
        !          5610:                                        opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
        !          5611:                                        opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 1 TSRMLS_CC);
        !          5612:                                } else {
        !          5613:                                        opline->op2.constant = zend_add_const_name_literal(CG(active_op_array), &constant_name->u.constant, 0 TSRMLS_CC);
        !          5614:                                }
1.1       misho    5615:                        }
1.1.1.2 ! misho    5616:                        GET_CACHE_SLOT(opline->op2.constant);
1.1       misho    5617:                        break;
                   5618:        }
                   5619: }
                   5620: /* }}} */
                   5621: 
                   5622: void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
                   5623: {
                   5624:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5625: 
                   5626:        switch (cmd->op_type) {
                   5627:                case IS_CONST:
                   5628:                case IS_TMP_VAR:
                   5629:                        opline->opcode = ZEND_SEND_VAL;
                   5630:                        break;
                   5631:                default:
                   5632:                        opline->opcode = ZEND_SEND_VAR;
                   5633:                        break;
                   5634:        }
1.1.1.2 ! misho    5635:        SET_NODE(opline->op1, cmd);
        !          5636:        opline->op2.opline_num = 0;
1.1       misho    5637:        opline->extended_value = ZEND_DO_FCALL;
                   5638:        SET_UNUSED(opline->op2);
                   5639: 
                   5640:        /* FIXME: exception support not added to this op2 */
                   5641:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5642:        opline->opcode = ZEND_DO_FCALL;
1.1.1.2 ! misho    5643:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5644:        opline->result_type = IS_VAR;
        !          5645:        LITERAL_STRINGL(opline->op1, estrndup("shell_exec", sizeof("shell_exec")-1), sizeof("shell_exec")-1, 0);
        !          5646:        CALCULATE_LITERAL_HASH(opline->op1.constant);
        !          5647:        opline->op1_type = IS_CONST;
        !          5648:        GET_CACHE_SLOT(opline->op1.constant);
1.1       misho    5649:        opline->extended_value = 1;
                   5650:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    5651:        GET_NODE(result, opline->result);
1.1       misho    5652: }
                   5653: /* }}} */
                   5654: 
                   5655: void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
                   5656: {
                   5657:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5658: 
                   5659:        opline->opcode = ZEND_INIT_ARRAY;
1.1.1.2 ! misho    5660:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5661:        opline->result_type = IS_TMP_VAR;
        !          5662:        GET_NODE(result, opline->result);
1.1       misho    5663:        if (expr) {
1.1.1.2 ! misho    5664:                SET_NODE(opline->op1, expr);
1.1       misho    5665:                if (offset) {
1.1.1.2 ! misho    5666:                        SET_NODE(opline->op2, offset);
        !          5667:                        if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
        !          5668:                                ulong index;
        !          5669:                                int numeric = 0;
        !          5670: 
        !          5671:                                ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
        !          5672:                                if (numeric) {
        !          5673:                                        zval_dtor(&CONSTANT(opline->op2.constant));
        !          5674:                                        ZVAL_LONG(&CONSTANT(opline->op2.constant), index); 
        !          5675:                                } else {
        !          5676:                                        CALCULATE_LITERAL_HASH(opline->op2.constant);
        !          5677:                                }
        !          5678:                        }
1.1       misho    5679:                } else {
                   5680:                        SET_UNUSED(opline->op2);
                   5681:                }
                   5682:        } else {
                   5683:                SET_UNUSED(opline->op1);
                   5684:                SET_UNUSED(opline->op2);
                   5685:        }
                   5686:        opline->extended_value = is_ref;
                   5687: }
                   5688: /* }}} */
                   5689: 
                   5690: void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
                   5691: {
                   5692:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5693: 
                   5694:        opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
1.1.1.2 ! misho    5695:        SET_NODE(opline->result, result);
        !          5696:        SET_NODE(opline->op1, expr);
1.1       misho    5697:        if (offset) {
1.1.1.2 ! misho    5698:                SET_NODE(opline->op2, offset);
        !          5699:                if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) {
        !          5700:                        ulong index;
        !          5701:                        int numeric = 0;
        !          5702: 
        !          5703:                        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline->op2.constant)), Z_STRLEN(CONSTANT(opline->op2.constant))+1, index, numeric = 1);
        !          5704:                        if (numeric) {
        !          5705:                                zval_dtor(&CONSTANT(opline->op2.constant));
        !          5706:                                ZVAL_LONG(&CONSTANT(opline->op2.constant), index); 
        !          5707:                        } else {
        !          5708:                                CALCULATE_LITERAL_HASH(opline->op2.constant);
        !          5709:                        }
        !          5710:                }
1.1       misho    5711:        } else {
                   5712:                SET_UNUSED(opline->op2);
                   5713:        }
                   5714:        opline->extended_value = is_ref;
                   5715: }
                   5716: /* }}} */
                   5717: 
                   5718: void zend_do_add_static_array_element(znode *result, znode *offset, const znode *expr) /* {{{ */
                   5719: {
                   5720:        zval *element;
                   5721: 
                   5722:        ALLOC_ZVAL(element);
                   5723:        *element = expr->u.constant;
                   5724:        if (offset) {
                   5725:                switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
                   5726:                        case IS_CONSTANT:
                   5727:                                /* Ugly hack to denote that this value has a constant index */
                   5728:                                Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
                   5729:                                Z_STRVAL(offset->u.constant) = erealloc(Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3);
                   5730:                                Z_STRVAL(offset->u.constant)[Z_STRLEN(offset->u.constant)+1] = Z_TYPE(offset->u.constant);
                   5731:                                Z_STRVAL(offset->u.constant)[Z_STRLEN(offset->u.constant)+2] = 0;
                   5732:                                zend_symtable_update(result->u.constant.value.ht, Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
                   5733:                                zval_dtor(&offset->u.constant);
                   5734:                                break;
                   5735:                        case IS_STRING:
                   5736:                                zend_symtable_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL);
                   5737:                                zval_dtor(&offset->u.constant);
                   5738:                                break;
                   5739:                        case IS_NULL:
                   5740:                                zend_symtable_update(Z_ARRVAL(result->u.constant), "", 1, &element, sizeof(zval *), NULL);
                   5741:                                break;
                   5742:                        case IS_LONG:
                   5743:                        case IS_BOOL:
                   5744:                                zend_hash_index_update(Z_ARRVAL(result->u.constant), Z_LVAL(offset->u.constant), &element, sizeof(zval *), NULL);
                   5745:                                break;
                   5746:                        case IS_DOUBLE:
                   5747:                                zend_hash_index_update(Z_ARRVAL(result->u.constant), zend_dval_to_lval(Z_DVAL(offset->u.constant)), &element, sizeof(zval *), NULL);
                   5748:                                break;
                   5749:                        case IS_CONSTANT_ARRAY:
                   5750:                                zend_error(E_ERROR, "Illegal offset type");
                   5751:                                break;
                   5752:                }
                   5753:        } else {
                   5754:                zend_hash_next_index_insert(Z_ARRVAL(result->u.constant), &element, sizeof(zval *), NULL);
                   5755:        }
                   5756: }
                   5757: /* }}} */
                   5758: 
                   5759: void zend_do_add_list_element(const znode *element TSRMLS_DC) /* {{{ */
                   5760: {
                   5761:        list_llist_element lle;
                   5762: 
                   5763:        if (element) {
                   5764:                zend_check_writable_variable(element);
                   5765: 
                   5766:                lle.var = *element;
                   5767:                zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
                   5768:                zend_llist_prepend_element(&CG(list_llist), &lle);
                   5769:        }
                   5770:        (*((int *)CG(dimension_llist).tail->data))++;
                   5771: }
                   5772: /* }}} */
                   5773: 
                   5774: void zend_do_new_list_begin(TSRMLS_D) /* {{{ */
                   5775: {
                   5776:        int current_dimension = 0;
                   5777:        zend_llist_add_element(&CG(dimension_llist), &current_dimension);
                   5778: }
                   5779: /* }}} */
                   5780: 
                   5781: void zend_do_new_list_end(TSRMLS_D) /* {{{ */
                   5782: {
                   5783:        zend_llist_remove_tail(&CG(dimension_llist));
                   5784:        (*((int *)CG(dimension_llist).tail->data))++;
                   5785: }
                   5786: /* }}} */
                   5787: 
                   5788: void zend_do_list_init(TSRMLS_D) /* {{{ */
                   5789: {
                   5790:        zend_stack_push(&CG(list_stack), &CG(list_llist), sizeof(zend_llist));
                   5791:        zend_stack_push(&CG(list_stack), &CG(dimension_llist), sizeof(zend_llist));
                   5792:        zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
                   5793:        zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
                   5794:        zend_do_new_list_begin(TSRMLS_C);
                   5795: }
                   5796: /* }}} */
                   5797: 
                   5798: void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
                   5799: {
                   5800:        zend_llist_element *le;
                   5801:        zend_llist_element *dimension;
                   5802:        zend_op *opline;
                   5803:        znode last_container;
                   5804: 
                   5805:        le = CG(list_llist).head;
                   5806:        while (le) {
                   5807:                zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
                   5808:                dimension = tmp_dimension_llist->head;
                   5809:                while (dimension) {
                   5810:                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5811:                        if (dimension == tmp_dimension_llist->head) { /* first */
                   5812:                                last_container = *expr;
                   5813:                                switch (expr->op_type) {
                   5814:                                        case IS_VAR:
                   5815:                                        case IS_CV:
                   5816:                                                opline->opcode = ZEND_FETCH_DIM_R;
                   5817:                                                break;
                   5818:                                        case IS_TMP_VAR:
                   5819:                                                opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
                   5820:                                                break;
                   5821:                                        case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */
                   5822:                                                zval_copy_ctor(&expr->u.constant);
                   5823:                                                opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
                   5824:                                                break;
                   5825:                                }
1.1.1.2 ! misho    5826:                                opline->extended_value |= ZEND_FETCH_ADD_LOCK;
1.1       misho    5827:                        } else {
                   5828:                                opline->opcode = ZEND_FETCH_DIM_R;
                   5829:                        }
1.1.1.2 ! misho    5830:                        opline->result_type = IS_VAR;
        !          5831:                        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5832:                        SET_NODE(opline->op1, &last_container);
        !          5833:                        opline->op2_type = IS_CONST;
        !          5834:                        LITERAL_LONG(opline->op2, *((int *) dimension->data));
        !          5835:                        GET_NODE(&last_container, opline->result);
1.1       misho    5836:                        dimension = dimension->next;
                   5837:                }
                   5838:                ((list_llist_element *) le->data)->value = last_container;
                   5839:                zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
                   5840:                zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
                   5841:                zend_do_free(result TSRMLS_CC);
                   5842:                le = le->next;
                   5843:        }
                   5844:        zend_llist_destroy(&CG(dimension_llist));
                   5845:        zend_llist_destroy(&CG(list_llist));
                   5846:        *result = *expr;
                   5847:        {
                   5848:                zend_llist *p;
                   5849: 
                   5850:                /* restore previous lists */
                   5851:                zend_stack_top(&CG(list_stack), (void **) &p);
                   5852:                CG(dimension_llist) = *p;
                   5853:                zend_stack_del_top(&CG(list_stack));
                   5854:                zend_stack_top(&CG(list_stack), (void **) &p);
                   5855:                CG(list_llist) = *p;
                   5856:                zend_stack_del_top(&CG(list_stack));
                   5857:        }
                   5858: }
                   5859: /* }}} */
                   5860: 
1.1.1.2 ! misho    5861: void zend_init_list(void *result, void *item TSRMLS_DC) /* {{{ */
        !          5862: {
        !          5863:        void** list = emalloc(sizeof(void*) * 2);
        !          5864: 
        !          5865:        list[0] = item;
        !          5866:        list[1] = NULL;
        !          5867: 
        !          5868:        *(void**)result = list;
        !          5869: }
        !          5870: /* }}} */
        !          5871: 
        !          5872: void zend_add_to_list(void *result, void *item TSRMLS_DC) /* {{{ */
        !          5873: {
        !          5874:        void** list = *(void**)result;
        !          5875:        size_t n = 0;
        !          5876: 
        !          5877:        while (list && list[n]) { n++; }
        !          5878: 
        !          5879:        list = erealloc(list, sizeof(void*) * (n+2));
        !          5880: 
        !          5881:        list[n]   = item;
        !          5882:        list[n+1] = NULL;
        !          5883: 
        !          5884:        *(void**)result = list;
        !          5885: }
        !          5886: /* }}} */
        !          5887: 
1.1       misho    5888: void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
                   5889: {
                   5890:        zval *tmp;
                   5891:        zend_op *opline;
                   5892:        znode lval;
                   5893:        znode result;
                   5894: 
                   5895:        ALLOC_ZVAL(tmp);
                   5896: 
                   5897:        if (static_assignment) {
                   5898:                *tmp = static_assignment->u.constant;
                   5899:        } else {
                   5900:                INIT_ZVAL(*tmp);
                   5901:        }
                   5902:        if (!CG(active_op_array)->static_variables) {
1.1.1.2 ! misho    5903:                if (CG(active_op_array)->scope) {
        !          5904:                        CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
        !          5905:                }
1.1       misho    5906:                ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
                   5907:                zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
                   5908:        }
                   5909:        zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
                   5910: 
                   5911:        if (varname->op_type == IS_CONST) {
                   5912:                if (Z_TYPE(varname->u.constant) != IS_STRING) {
                   5913:                        convert_to_string(&varname->u.constant);
                   5914:                }
                   5915:        }
                   5916: 
                   5917:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5918:        opline->opcode = (fetch_type == ZEND_FETCH_LEXICAL) ? ZEND_FETCH_R : ZEND_FETCH_W;              /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
1.1.1.2 ! misho    5919:        opline->result_type = IS_VAR;
        !          5920:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5921:        SET_NODE(opline->op1, varname);
        !          5922:        if (opline->op1_type == IS_CONST) {
        !          5923:                CALCULATE_LITERAL_HASH(opline->op1.constant);
        !          5924:        }
1.1       misho    5925:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    5926:        opline->extended_value = ZEND_FETCH_STATIC;
        !          5927:        GET_NODE(&result, opline->result);
1.1       misho    5928: 
                   5929:        if (varname->op_type == IS_CONST) {
                   5930:                zval_copy_ctor(&varname->u.constant);
                   5931:        }
                   5932:        fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
                   5933: 
                   5934:        if (fetch_type == ZEND_FETCH_LEXICAL) {
                   5935:                znode dummy;
                   5936: 
                   5937:                zend_do_begin_variable_parse(TSRMLS_C);
                   5938:                zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
                   5939:                zend_do_free(&dummy TSRMLS_CC);
                   5940:        } else {
                   5941:                zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
                   5942:        }
1.1.1.2 ! misho    5943:        CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
1.1       misho    5944: }
                   5945: /* }}} */
                   5946: 
                   5947: void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
                   5948: {
                   5949:        znode value;
                   5950: 
                   5951:        if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
1.1.1.2 ! misho    5952:            memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
1.1       misho    5953:                zend_error(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
                   5954:                return;
                   5955:        }
                   5956: 
                   5957:        value.op_type = IS_CONST;
                   5958:        ZVAL_NULL(&value.u.constant);
                   5959:        Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
                   5960:        Z_SET_REFCOUNT_P(&value.u.constant, 1);
                   5961:        Z_UNSET_ISREF_P(&value.u.constant);
                   5962:        
                   5963:        zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
                   5964: }
                   5965: /* }}} */
                   5966: 
                   5967: void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
                   5968: {
                   5969:        zend_op *opline;
                   5970:        znode lval;
                   5971:        znode result;
                   5972: 
                   5973:        if (varname->op_type == IS_CONST) {
                   5974:                if (Z_TYPE(varname->u.constant) != IS_STRING) {
                   5975:                        convert_to_string(&varname->u.constant);
                   5976:                }
                   5977:        }
                   5978: 
                   5979:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   5980:        opline->opcode = ZEND_FETCH_W;          /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
1.1.1.2 ! misho    5981:        opline->result_type = IS_VAR;
        !          5982:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          5983:        SET_NODE(opline->op1, varname);
        !          5984:        if (opline->op1_type == IS_CONST) {
        !          5985:                CALCULATE_LITERAL_HASH(opline->op1.constant);
        !          5986:        }
1.1       misho    5987:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    5988:        opline->extended_value = fetch_type;
        !          5989:        GET_NODE(&result, opline->result);
1.1       misho    5990: 
                   5991:        if (varname->op_type == IS_CONST) {
                   5992:                zval_copy_ctor(&varname->u.constant);
                   5993:        }
                   5994:        fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
                   5995: 
                   5996:        zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
1.1.1.2 ! misho    5997:        CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result_type |= EXT_TYPE_UNUSED;
1.1       misho    5998: }
                   5999: /* }}} */
                   6000: 
                   6001: void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC) /* {{{ */
                   6002: {
                   6003:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6004: 
                   6005:        opline->opcode = ZEND_CAST;
1.1.1.2 ! misho    6006:        opline->result_type = IS_TMP_VAR;
        !          6007:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6008:        SET_NODE(opline->op1, expr);
1.1       misho    6009:        SET_UNUSED(opline->op2);
                   6010:        opline->extended_value = type;
1.1.1.2 ! misho    6011:        GET_NODE(result, opline->result);
1.1       misho    6012: }
                   6013: /* }}} */
                   6014: 
                   6015: void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
                   6016: {
                   6017:        zend_do_extended_fcall_begin(TSRMLS_C);
                   6018:        {
                   6019:                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6020: 
                   6021:                opline->opcode = ZEND_INCLUDE_OR_EVAL;
1.1.1.2 ! misho    6022:                opline->result_type = IS_VAR;
        !          6023:                opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6024:                SET_NODE(opline->op1, op1);
1.1       misho    6025:                SET_UNUSED(opline->op2);
1.1.1.2 ! misho    6026:                opline->extended_value = type;
        !          6027:                GET_NODE(result, opline->result);
1.1       misho    6028:        }
                   6029:        zend_do_extended_fcall_end(TSRMLS_C);
                   6030: }
                   6031: /* }}} */
                   6032: 
                   6033: void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC) /* {{{ */
                   6034: {
                   6035:        int i;
                   6036: 
                   6037:        zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
                   6038:        for (i=1; i<num_references->u.constant.value.lval; i++) {
                   6039:                fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
                   6040:                *variable = *result;
                   6041:        }
                   6042:        zend_do_begin_variable_parse(TSRMLS_C);
                   6043:        fetch_simple_variable(result, variable, 1 TSRMLS_CC);
                   6044:        /* there is a chance someone is accessing $this */
                   6045:        if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
1.1.1.2 ! misho    6046:                CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
1.1       misho    6047:        }
                   6048: }
                   6049: /* }}} */
                   6050: 
                   6051: void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
                   6052: {
                   6053:        zend_op *last_op;
                   6054: 
                   6055:        zend_check_writable_variable(variable);
                   6056: 
                   6057:        if (variable->op_type == IS_CV) {
                   6058:                zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6059:                opline->opcode = ZEND_UNSET_VAR;
1.1.1.2 ! misho    6060:                SET_NODE(opline->op1, variable);
1.1       misho    6061:                SET_UNUSED(opline->op2);
                   6062:                SET_UNUSED(opline->result);
1.1.1.2 ! misho    6063:                opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
1.1       misho    6064:        } else {
                   6065:                last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
                   6066: 
                   6067:                switch (last_op->opcode) {
                   6068:                        case ZEND_FETCH_UNSET:
                   6069:                                last_op->opcode = ZEND_UNSET_VAR;
1.1.1.2 ! misho    6070:                                SET_UNUSED(last_op->result);
1.1       misho    6071:                                break;
                   6072:                        case ZEND_FETCH_DIM_UNSET:
                   6073:                                last_op->opcode = ZEND_UNSET_DIM;
1.1.1.2 ! misho    6074:                                SET_UNUSED(last_op->result);
1.1       misho    6075:                                break;
                   6076:                        case ZEND_FETCH_OBJ_UNSET:
                   6077:                                last_op->opcode = ZEND_UNSET_OBJ;
1.1.1.2 ! misho    6078:                                SET_UNUSED(last_op->result);
1.1       misho    6079:                                break;
                   6080: 
                   6081:                }
                   6082:        }
                   6083: }
                   6084: /* }}} */
                   6085: 
                   6086: void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC) /* {{{ */
                   6087: {
                   6088:        zend_op *last_op;
                   6089: 
                   6090:        zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
                   6091: 
                   6092:        zend_check_writable_variable(variable);
                   6093: 
                   6094:        if (variable->op_type == IS_CV) {
                   6095:                last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6096:                last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
1.1.1.2 ! misho    6097:                SET_NODE(last_op->op1, variable);
1.1       misho    6098:                SET_UNUSED(last_op->op2);
1.1.1.2 ! misho    6099:                last_op->result.var = get_temporary_variable(CG(active_op_array));
        !          6100:                last_op->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
1.1       misho    6101:        } else {
                   6102:                last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
                   6103: 
                   6104:                switch (last_op->opcode) {
                   6105:                        case ZEND_FETCH_IS:
                   6106:                                last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
                   6107:                                break;
                   6108:                        case ZEND_FETCH_DIM_IS:
                   6109:                                last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
                   6110:                                break;
                   6111:                        case ZEND_FETCH_OBJ_IS:
                   6112:                                last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
                   6113:                                break;
                   6114:                }
                   6115:        }
1.1.1.2 ! misho    6116:        last_op->result_type = IS_TMP_VAR;
1.1       misho    6117:        last_op->extended_value |= type;
                   6118: 
1.1.1.2 ! misho    6119:        GET_NODE(result, last_op->result);
1.1       misho    6120: }
                   6121: /* }}} */
                   6122: 
                   6123: void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC) /* {{{ */
                   6124: {
                   6125:        int last_op_number = get_next_op_number(CG(active_op_array));
                   6126:        zend_op *opline;
                   6127: 
                   6128:        if (last_op_number > 0) {
                   6129:                opline = &CG(active_op_array)->opcodes[last_op_number-1];
                   6130:                if (opline->opcode == ZEND_FETCH_CLASS) {
                   6131:                        opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
                   6132:                }
                   6133:        }
                   6134: 
                   6135:        if (expr->op_type == IS_CONST) {
                   6136:                zend_error(E_COMPILE_ERROR, "instanceof expects an object instance, constant given");
                   6137:        }
                   6138: 
                   6139:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6140:        opline->opcode = ZEND_INSTANCEOF;
1.1.1.2 ! misho    6141:        opline->result_type = IS_TMP_VAR;
        !          6142:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6143:        SET_NODE(opline->op1, expr);
1.1       misho    6144: 
1.1.1.2 ! misho    6145:        SET_NODE(opline->op2, class_znode);
1.1       misho    6146: 
1.1.1.2 ! misho    6147:        GET_NODE(result, opline->result);
1.1       misho    6148: }
                   6149: /* }}} */
                   6150: 
                   6151: void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC) /* {{{ */
                   6152: {
                   6153:        zend_op *opline;
                   6154:        zend_bool is_variable;
                   6155:        zend_bool push_container = 0;
                   6156:        zend_op dummy_opline;
                   6157: 
                   6158:        if (variable) {
                   6159:                if (zend_is_function_or_method_call(array)) {
                   6160:                        is_variable = 0;
                   6161:                } else {
                   6162:                        is_variable = 1;
                   6163:                }
                   6164:                /* save the location of FETCH_W instruction(s) */
1.1.1.2 ! misho    6165:                open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6166:                zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
                   6167:                if (CG(active_op_array)->last > 0 &&
1.1.1.2 ! misho    6168:                    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
1.1       misho    6169:                        /* Only lock the container if we are fetching from a real container and not $this */
1.1.1.2 ! misho    6170:                        if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1_type == IS_VAR) {
1.1       misho    6171:                                CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
                   6172:                                push_container = 1;
                   6173:                        }
                   6174:                }
                   6175:        } else {
                   6176:                is_variable = 0;
1.1.1.2 ! misho    6177:                open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6178:        }
                   6179: 
                   6180:        /* save the location of FE_RESET */
1.1.1.2 ! misho    6181:        foreach_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6182: 
                   6183:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6184: 
                   6185:        /* Preform array reset */
                   6186:        opline->opcode = ZEND_FE_RESET;
1.1.1.2 ! misho    6187:        opline->result_type = IS_VAR;
        !          6188:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6189:        SET_NODE(opline->op1, array);
1.1       misho    6190:        SET_UNUSED(opline->op2);
                   6191:        opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
                   6192: 
1.1.1.2 ! misho    6193:        COPY_NODE(dummy_opline.result, opline->result);
1.1       misho    6194:        if (push_container) {
1.1.1.2 ! misho    6195:                COPY_NODE(dummy_opline.op1, CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1);
1.1       misho    6196:        } else {
1.1.1.2 ! misho    6197:                dummy_opline.op1_type = IS_UNUSED;
1.1       misho    6198:        }
                   6199:        zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
                   6200: 
                   6201:        /* save the location of FE_FETCH */
1.1.1.2 ! misho    6202:        as_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6203: 
                   6204:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6205:        opline->opcode = ZEND_FE_FETCH;
1.1.1.2 ! misho    6206:        opline->result_type = IS_VAR;
        !          6207:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6208:        COPY_NODE(opline->op1, dummy_opline.result);
1.1       misho    6209:        opline->extended_value = 0;
                   6210:        SET_UNUSED(opline->op2);
                   6211: 
                   6212:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6213:        opline->opcode = ZEND_OP_DATA;
                   6214:        SET_UNUSED(opline->op1);
                   6215:        SET_UNUSED(opline->op2);
                   6216:        SET_UNUSED(opline->result);
                   6217: }
                   6218: /* }}} */
                   6219: 
                   6220: void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC) /* {{{ */
                   6221: {
                   6222:        zend_op *opline;
                   6223:        znode dummy, value_node;
                   6224:        zend_bool assign_by_ref=0;
                   6225: 
1.1.1.2 ! misho    6226:        opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num];
1.1       misho    6227:        if (key->op_type != IS_UNUSED) {
                   6228:                znode *tmp;
                   6229: 
                   6230:                /* switch between the key and value... */
                   6231:                tmp = key;
                   6232:                key = value;
                   6233:                value = tmp;
                   6234: 
                   6235:                /* Mark extended_value in case both key and value are being used */
                   6236:                opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
                   6237:        }
                   6238: 
1.1.1.2 ! misho    6239:        if ((key->op_type != IS_UNUSED) && (key->EA & ZEND_PARSED_REFERENCE_VARIABLE)) {
1.1       misho    6240:                zend_error(E_COMPILE_ERROR, "Key element cannot be a reference");
                   6241:        }
                   6242: 
1.1.1.2 ! misho    6243:        if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) {
1.1       misho    6244:                assign_by_ref = 1;
                   6245:                if (!(opline-1)->extended_value) {
                   6246:                        zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
                   6247:                }
                   6248:                /* Mark extended_value for assign-by-reference */
                   6249:                opline->extended_value |= ZEND_FE_FETCH_BYREF;
1.1.1.2 ! misho    6250:                CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
1.1       misho    6251:        } else {
                   6252:                zend_op *foreach_copy;
1.1.1.2 ! misho    6253:                zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num];
        !          6254:                zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num];
1.1       misho    6255: 
                   6256:                /* Change "write context" into "read context" */
                   6257:                fetch->extended_value = 0;  /* reset ZEND_FE_RESET_VARIABLE */
                   6258:                while (fetch != end) {
                   6259:                        --fetch;
1.1.1.2 ! misho    6260:                        if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) {
1.1       misho    6261:                                zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
                   6262:                        }
1.1.1.2 ! misho    6263:                        if (fetch->opcode == ZEND_SEPARATE) {
        !          6264:                                MAKE_NOP(fetch);
        !          6265:                        } else {
        !          6266:                                fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
        !          6267:                        }
1.1       misho    6268:                }
                   6269:                /* prevent double SWITCH_FREE */
                   6270:                zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
1.1.1.2 ! misho    6271:                foreach_copy->op1_type = IS_UNUSED;
1.1       misho    6272:        }
                   6273: 
1.1.1.2 ! misho    6274:        GET_NODE(&value_node, opline->result);
1.1       misho    6275: 
                   6276:        if (assign_by_ref) {
                   6277:                zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
                   6278:                /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
                   6279:                zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
                   6280:        } else {
                   6281:                zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
                   6282:                zend_do_free(&dummy TSRMLS_CC);
                   6283:        }
                   6284: 
                   6285:        if (key->op_type != IS_UNUSED) {
                   6286:                znode key_node;
                   6287: 
1.1.1.2 ! misho    6288:                opline = &CG(active_op_array)->opcodes[as_token->u.op.opline_num+1];
        !          6289:                opline->result_type = IS_TMP_VAR;
        !          6290:                opline->result.opline_num = get_temporary_variable(CG(active_op_array));
        !          6291:                GET_NODE(&key_node, opline->result);
1.1       misho    6292: 
                   6293:                zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
                   6294:                zend_do_free(&dummy TSRMLS_CC);
                   6295:        }
                   6296: 
                   6297:        do_begin_loop(TSRMLS_C);
                   6298:        INC_BPC(CG(active_op_array));
                   6299: }
                   6300: /* }}} */
                   6301: 
                   6302: void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC) /* {{{ */
                   6303: {
                   6304:        zend_op *container_ptr;
                   6305:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6306: 
                   6307:        opline->opcode = ZEND_JMP;
1.1.1.2 ! misho    6308:        opline->op1.opline_num = as_token->u.op.opline_num;
1.1       misho    6309:        SET_UNUSED(opline->op1);
                   6310:        SET_UNUSED(opline->op2);
                   6311: 
1.1.1.2 ! misho    6312:        CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
        !          6313:        CG(active_op_array)->opcodes[as_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
1.1       misho    6314: 
1.1.1.2 ! misho    6315:        do_end_loop(as_token->u.op.opline_num, 1 TSRMLS_CC);
1.1       misho    6316: 
                   6317:        zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
                   6318:        generate_free_foreach_copy(container_ptr TSRMLS_CC);
                   6319:        zend_stack_del_top(&CG(foreach_copy_stack));
                   6320: 
                   6321:        DEC_BPC(CG(active_op_array));
                   6322: }
                   6323: /* }}} */
                   6324: 
                   6325: void zend_do_declare_begin(TSRMLS_D) /* {{{ */
                   6326: {
                   6327:        zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables));
                   6328: }
                   6329: /* }}} */
                   6330: 
                   6331: void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
                   6332: {
                   6333:        if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
                   6334:                convert_to_long(&val->u.constant);
                   6335:                CG(declarables).ticks = val->u.constant;
                   6336:        } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
                   6337:                if ((Z_TYPE(val->u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
                   6338:                        zend_error(E_COMPILE_ERROR, "Cannot use constants as encoding");
                   6339:                }
                   6340: 
                   6341:                /*
                   6342:                 * Check that the pragma comes before any opcodes. If the compilation
                   6343:                 * got as far as this, the previous portion of the script must have been
                   6344:                 * parseable according to the .ini script_encoding setting. We still
                   6345:                 * want to tell them to put declare() at the top.
                   6346:                 */
                   6347:                {
                   6348:                        int num = CG(active_op_array)->last;
                   6349:                        /* ignore ZEND_EXT_STMT and ZEND_TICKS */
                   6350:                        while (num > 0 &&
1.1.1.2 ! misho    6351:                               (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
        !          6352:                                CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
1.1       misho    6353:                                --num;
                   6354:                        }
                   6355: 
                   6356:                        if (num > 0) {
                   6357:                                zend_error(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
                   6358:                        }
                   6359:                }
                   6360: 
1.1.1.2 ! misho    6361:                if (CG(multibyte)) {
        !          6362:                        const zend_encoding *new_encoding, *old_encoding;
        !          6363:                        zend_encoding_filter old_input_filter;
        !          6364: 
        !          6365:                        CG(encoding_declared) = 1;
        !          6366: 
        !          6367:                        convert_to_string(&val->u.constant);
        !          6368:                        new_encoding = zend_multibyte_fetch_encoding(val->u.constant.value.str.val TSRMLS_CC);
        !          6369:                        if (!new_encoding) {
        !          6370:                                zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", val->u.constant.value.str.val);
        !          6371:                        } else {
        !          6372:                                old_input_filter = LANG_SCNG(input_filter);
        !          6373:                                old_encoding = LANG_SCNG(script_encoding);
        !          6374:                                zend_multibyte_set_filter(new_encoding TSRMLS_CC);
        !          6375: 
        !          6376:                                /* need to re-scan if input filter changed */
        !          6377:                                if (old_input_filter != LANG_SCNG(input_filter) ||
        !          6378:                                         (old_input_filter && new_encoding != old_encoding)) {
        !          6379:                                        zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
        !          6380:                                }
1.1       misho    6381:                        }
1.1.1.2 ! misho    6382:                } else {
        !          6383:                        zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because Zend multibyte feature is turned off by settings");
1.1       misho    6384:                }
                   6385:                zval_dtor(&val->u.constant);
                   6386:        } else {
                   6387:                zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", var->u.constant.value.str.val);
                   6388:                zval_dtor(&val->u.constant);
                   6389:        }
                   6390:        zval_dtor(&var->u.constant);
                   6391: }
                   6392: /* }}} */
                   6393: 
                   6394: void zend_do_declare_end(const znode *declare_token TSRMLS_DC) /* {{{ */
                   6395: {
                   6396:        zend_declarables *declarables;
                   6397: 
                   6398:        zend_stack_top(&CG(declare_stack), (void **) &declarables);
                   6399:        /* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
1.1.1.2 ! misho    6400:        if ((get_next_op_number(CG(active_op_array)) - declare_token->u.op.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
1.1       misho    6401:                CG(declarables) = *declarables;
                   6402:        }
                   6403: }
                   6404: /* }}} */
                   6405: 
                   6406: void zend_do_exit(znode *result, const znode *message TSRMLS_DC) /* {{{ */
                   6407: {
                   6408:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6409: 
                   6410:        opline->opcode = ZEND_EXIT;
1.1.1.2 ! misho    6411:        SET_NODE(opline->op1, message);
1.1       misho    6412:        SET_UNUSED(opline->op2);
                   6413: 
                   6414:        result->op_type = IS_CONST;
                   6415:        Z_TYPE(result->u.constant) = IS_BOOL;
                   6416:        Z_LVAL(result->u.constant) = 1;
                   6417: }
                   6418: /* }}} */
                   6419: 
                   6420: void zend_do_begin_silence(znode *strudel_token TSRMLS_DC) /* {{{ */
                   6421: {
                   6422:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6423: 
                   6424:        opline->opcode = ZEND_BEGIN_SILENCE;
1.1.1.2 ! misho    6425:        opline->result_type = IS_TMP_VAR;
        !          6426:        opline->result.var = get_temporary_variable(CG(active_op_array));
1.1       misho    6427:        SET_UNUSED(opline->op1);
                   6428:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    6429:        GET_NODE(strudel_token, opline->result);
1.1       misho    6430: }
                   6431: /* }}} */
                   6432: 
                   6433: void zend_do_end_silence(const znode *strudel_token TSRMLS_DC) /* {{{ */
                   6434: {
                   6435:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6436: 
                   6437:        opline->opcode = ZEND_END_SILENCE;
1.1.1.2 ! misho    6438:        SET_NODE(opline->op1, strudel_token);
1.1       misho    6439:        SET_UNUSED(opline->op2);
                   6440: }
                   6441: /* }}} */
                   6442: 
                   6443: void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC) /* {{{ */
                   6444: {
                   6445:        int op_number = get_next_op_number(CG(active_op_array));
                   6446:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6447: 
1.1.1.2 ! misho    6448:        if (value->op_type == IS_VAR || value->op_type == IS_CV) {
        !          6449:                opline->opcode = ZEND_JMP_SET_VAR;
        !          6450:                opline->result_type = IS_VAR;
        !          6451:        } else {
        !          6452:                opline->opcode = ZEND_JMP_SET;
        !          6453:                opline->result_type = IS_TMP_VAR;
        !          6454:        }
        !          6455:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6456:        SET_NODE(opline->op1, value);
1.1       misho    6457:        SET_UNUSED(opline->op2);
                   6458:        
1.1.1.2 ! misho    6459:        GET_NODE(colon_token, opline->result);
1.1       misho    6460: 
1.1.1.2 ! misho    6461:        jmp_token->u.op.opline_num = op_number;
1.1       misho    6462: 
                   6463:        INC_BPC(CG(active_op_array));
                   6464: }
                   6465: /* }}} */
                   6466: 
                   6467: void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *jmp_token, const znode *colon_token TSRMLS_DC) /* {{{ */
                   6468: {
                   6469:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6470: 
1.1.1.2 ! misho    6471:        SET_NODE(opline->result, colon_token);
        !          6472:        if (colon_token->op_type == IS_TMP_VAR) {
        !          6473:                if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
        !          6474:                        CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
        !          6475:                        CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
        !          6476:                        opline->opcode = ZEND_QM_ASSIGN_VAR;
        !          6477:                        opline->result_type = IS_VAR;
        !          6478:                } else {
        !          6479:                        opline->opcode = ZEND_QM_ASSIGN;
        !          6480:                }
        !          6481:        } else {
        !          6482:                opline->opcode = ZEND_QM_ASSIGN_VAR;
        !          6483:        }
1.1       misho    6484:        opline->extended_value = 0;
1.1.1.2 ! misho    6485:        SET_NODE(opline->op1, false_value);
1.1       misho    6486:        SET_UNUSED(opline->op2);
                   6487:        
1.1.1.2 ! misho    6488:        GET_NODE(result, opline->result);
1.1       misho    6489: 
1.1.1.2 ! misho    6490:        CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6491:        
                   6492:        DEC_BPC(CG(active_op_array));
                   6493: }
                   6494: /* }}} */
                   6495: 
                   6496: void zend_do_begin_qm_op(const znode *cond, znode *qm_token TSRMLS_DC) /* {{{ */
                   6497: {
                   6498:        int jmpz_op_number = get_next_op_number(CG(active_op_array));
                   6499:        zend_op *opline;
                   6500: 
                   6501:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6502: 
                   6503:        opline->opcode = ZEND_JMPZ;
1.1.1.2 ! misho    6504:        SET_NODE(opline->op1, cond);
1.1       misho    6505:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    6506:        opline->op2.opline_num = jmpz_op_number;
        !          6507:        GET_NODE(qm_token, opline->op2);
1.1       misho    6508: 
                   6509:        INC_BPC(CG(active_op_array));
                   6510: }
                   6511: /* }}} */
                   6512: 
                   6513: void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC) /* {{{ */
                   6514: {
                   6515:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6516: 
1.1.1.2 ! misho    6517:        CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
1.1       misho    6518: 
1.1.1.2 ! misho    6519:        if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
        !          6520:                opline->opcode = ZEND_QM_ASSIGN_VAR;
        !          6521:                opline->result_type = IS_VAR;
        !          6522:        } else {
        !          6523:                opline->opcode = ZEND_QM_ASSIGN;
        !          6524:                opline->result_type = IS_TMP_VAR;
        !          6525:        }
        !          6526:        opline->result.var = get_temporary_variable(CG(active_op_array));
        !          6527:        SET_NODE(opline->op1, true_value);
1.1       misho    6528:        SET_UNUSED(opline->op2);
                   6529: 
1.1.1.2 ! misho    6530:        GET_NODE(qm_token, opline->result);
        !          6531:        colon_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6532: 
                   6533:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6534:        opline->opcode = ZEND_JMP;
                   6535:        SET_UNUSED(opline->op1);
                   6536:        SET_UNUSED(opline->op2);
                   6537: }
                   6538: /* }}} */
                   6539: 
                   6540: void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_token, const znode *colon_token TSRMLS_DC) /* {{{ */
                   6541: {
                   6542:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6543: 
1.1.1.2 ! misho    6544:        SET_NODE(opline->result, qm_token);
        !          6545:        if (qm_token->op_type == IS_TMP_VAR) {
        !          6546:                if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
        !          6547:                        CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
        !          6548:                        CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
        !          6549:                        opline->opcode = ZEND_QM_ASSIGN_VAR;
        !          6550:                        opline->result_type = IS_VAR;
        !          6551:                } else {
        !          6552:                        opline->opcode = ZEND_QM_ASSIGN;
        !          6553:                }
        !          6554:        } else {
        !          6555:                opline->opcode = ZEND_QM_ASSIGN_VAR;
        !          6556:        }
        !          6557:        SET_NODE(opline->op1, false_value);
1.1       misho    6558:        SET_UNUSED(opline->op2);
                   6559: 
1.1.1.2 ! misho    6560:        CG(active_op_array)->opcodes[colon_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
1.1       misho    6561: 
1.1.1.2 ! misho    6562:        GET_NODE(result, opline->result);
1.1       misho    6563: 
                   6564:        DEC_BPC(CG(active_op_array));
                   6565: }
                   6566: /* }}} */
                   6567: 
                   6568: void zend_do_extended_info(TSRMLS_D) /* {{{ */
                   6569: {
                   6570:        zend_op *opline;
                   6571: 
                   6572:        if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
                   6573:                return;
                   6574:        }
                   6575: 
                   6576:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6577: 
                   6578:        opline->opcode = ZEND_EXT_STMT;
                   6579:        SET_UNUSED(opline->op1);
                   6580:        SET_UNUSED(opline->op2);
                   6581: }
                   6582: /* }}} */
                   6583: 
                   6584: void zend_do_extended_fcall_begin(TSRMLS_D) /* {{{ */
                   6585: {
                   6586:        zend_op *opline;
                   6587: 
                   6588:        if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
                   6589:                return;
                   6590:        }
                   6591: 
                   6592:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6593: 
                   6594:        opline->opcode = ZEND_EXT_FCALL_BEGIN;
                   6595:        SET_UNUSED(opline->op1);
                   6596:        SET_UNUSED(opline->op2);
                   6597: }
                   6598: /* }}} */
                   6599: 
                   6600: void zend_do_extended_fcall_end(TSRMLS_D) /* {{{ */
                   6601: {
                   6602:        zend_op *opline;
                   6603: 
                   6604:        if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
                   6605:                return;
                   6606:        }
                   6607: 
                   6608:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6609: 
                   6610:        opline->opcode = ZEND_EXT_FCALL_END;
                   6611:        SET_UNUSED(opline->op1);
                   6612:        SET_UNUSED(opline->op2);
                   6613: }
                   6614: /* }}} */
                   6615: 
                   6616: void zend_do_ticks(TSRMLS_D) /* {{{ */
                   6617: {
                   6618:        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   6619: 
                   6620:        opline->opcode = ZEND_TICKS;
1.1.1.2 ! misho    6621:        SET_UNUSED(opline->op1);
1.1       misho    6622:        SET_UNUSED(opline->op2);
1.1.1.2 ! misho    6623:        opline->extended_value = Z_LVAL(CG(declarables).ticks);
1.1       misho    6624: }
                   6625: /* }}} */
                   6626: 
1.1.1.2 ! misho    6627: zend_bool zend_is_auto_global_quick(const char *name, uint name_len, ulong hashval TSRMLS_DC) /* {{{ */
1.1       misho    6628: {
                   6629:        zend_auto_global *auto_global;
1.1.1.2 ! misho    6630:        ulong hash = hashval ? hashval : zend_hash_func(name, name_len+1);
1.1       misho    6631: 
1.1.1.2 ! misho    6632:        if (zend_hash_quick_find(CG(auto_globals), name, name_len+1, hash, (void **) &auto_global)==SUCCESS) {
1.1       misho    6633:                if (auto_global->armed) {
                   6634:                        auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
                   6635:                }
                   6636:                return 1;
                   6637:        }
                   6638:        return 0;
                   6639: }
                   6640: /* }}} */
                   6641: 
1.1.1.2 ! misho    6642: zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */
        !          6643: {
        !          6644:        return zend_is_auto_global_quick(name, name_len, 0 TSRMLS_CC);
        !          6645: }
        !          6646: /* }}} */
        !          6647: 
        !          6648: int zend_register_auto_global(const char *name, uint name_len, zend_bool jit, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
1.1       misho    6649: {
                   6650:        zend_auto_global auto_global;
                   6651: 
1.1.1.2 ! misho    6652:        auto_global.name = zend_new_interned_string((char*)name, name_len + 1, 0 TSRMLS_CC);
1.1       misho    6653:        auto_global.name_len = name_len;
                   6654:        auto_global.auto_global_callback = auto_global_callback;
1.1.1.2 ! misho    6655:        auto_global.jit = jit;
1.1       misho    6656: 
                   6657:        return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL);
                   6658: }
                   6659: /* }}} */
                   6660: 
1.1.1.2 ! misho    6661: static int zend_auto_global_init(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
        !          6662: {
        !          6663:        if (auto_global->jit) {
        !          6664:                auto_global->armed = 1;
        !          6665:        } else if (auto_global->auto_global_callback) {
        !          6666:                auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
        !          6667:        } else {
        !          6668:                auto_global->armed = 0;
        !          6669:        }
        !          6670:        return 0;
        !          6671: }
        !          6672: /* }}} */
        !          6673: 
        !          6674: ZEND_API void zend_activate_auto_globals(TSRMLS_D) /* {{{ */
        !          6675: {
        !          6676:        zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_init TSRMLS_CC);
        !          6677: }
        !          6678: /* }}} */
        !          6679: 
1.1       misho    6680: int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */
                   6681: {
                   6682:        int retval;
                   6683: 
                   6684:        if (CG(increment_lineno)) {
                   6685:                CG(zend_lineno)++;
                   6686:                CG(increment_lineno) = 0;
                   6687:        }
                   6688: 
                   6689: again:
                   6690:        Z_TYPE(zendlval->u.constant) = IS_LONG;
                   6691:        retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
                   6692:        switch (retval) {
                   6693:                case T_COMMENT:
                   6694:                case T_DOC_COMMENT:
                   6695:                case T_OPEN_TAG:
                   6696:                case T_WHITESPACE:
                   6697:                        goto again;
                   6698: 
                   6699:                case T_CLOSE_TAG:
                   6700:                        if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
                   6701:                                CG(increment_lineno) = 1;
                   6702:                        }
                   6703:                        if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
                   6704:                                goto again;                             
                   6705:                        }
                   6706:                        retval = ';'; /* implicit ; */
                   6707:                        break;
                   6708:                case T_OPEN_TAG_WITH_ECHO:
                   6709:                        retval = T_ECHO;
                   6710:                        break;
                   6711:                case T_END_HEREDOC:
                   6712:                        efree(Z_STRVAL(zendlval->u.constant));
                   6713:                        break;
                   6714:        }
                   6715: 
                   6716:        INIT_PZVAL(&zendlval->u.constant);
                   6717:        zendlval->op_type = IS_CONST;
                   6718:        return retval;
                   6719: }
                   6720: /* }}} */
                   6721: 
                   6722: ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC) /* {{{ */
                   6723: {
                   6724:        zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
                   6725:        dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
                   6726: 
                   6727:        ce->refcount = 1;
                   6728:        ce->ce_flags = 0;
                   6729: 
1.1.1.2 ! misho    6730:        ce->default_properties_table = NULL;
        !          6731:        ce->default_static_members_table = NULL;
1.1       misho    6732:        zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
                   6733:        zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
                   6734:        zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
                   6735: 
                   6736:        if (ce->type == ZEND_INTERNAL_CLASS) {
                   6737: #ifdef ZTS
                   6738:                int n = zend_hash_num_elements(CG(class_table));
                   6739: 
1.1.1.2 ! misho    6740:                if (CG(static_members_table) && n >= CG(last_static_member)) {
1.1       misho    6741:                        /* Support for run-time declaration: dl() */
                   6742:                        CG(last_static_member) = n+1;
1.1.1.2 ! misho    6743:                        CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval**));
        !          6744:                        CG(static_members_table)[n] = NULL;
1.1       misho    6745:                }
1.1.1.2 ! misho    6746:                ce->static_members_table = (zval**)(zend_intptr_t)n;
1.1       misho    6747: #else
1.1.1.2 ! misho    6748:                ce->static_members_table = NULL;
1.1       misho    6749: #endif
                   6750:        } else {
1.1.1.2 ! misho    6751:                ce->static_members_table = ce->default_static_members_table;
        !          6752:                ce->info.user.doc_comment = NULL;
        !          6753:                ce->info.user.doc_comment_len = 0;
1.1       misho    6754:        }
                   6755: 
1.1.1.2 ! misho    6756:        ce->default_properties_count = 0;
        !          6757:        ce->default_static_members_count = 0;
        !          6758: 
1.1       misho    6759:        if (nullify_handlers) {
                   6760:                ce->constructor = NULL;
                   6761:                ce->destructor = NULL;
                   6762:                ce->clone = NULL;
                   6763:                ce->__get = NULL;
                   6764:                ce->__set = NULL;
                   6765:                ce->__unset = NULL;
                   6766:                ce->__isset = NULL;
                   6767:                ce->__call = NULL;
                   6768:                ce->__callstatic = NULL;
                   6769:                ce->__tostring = NULL;
                   6770:                ce->create_object = NULL;
                   6771:                ce->get_iterator = NULL;
                   6772:                ce->iterator_funcs.funcs = NULL;
                   6773:                ce->interface_gets_implemented = NULL;
                   6774:                ce->get_static_method = NULL;
                   6775:                ce->parent = NULL;
                   6776:                ce->num_interfaces = 0;
                   6777:                ce->interfaces = NULL;
1.1.1.2 ! misho    6778:                ce->num_traits = 0;
        !          6779:                ce->traits = NULL;
        !          6780:                ce->trait_aliases = NULL;
        !          6781:                ce->trait_precedences = NULL;
1.1       misho    6782:                ce->serialize = NULL;
                   6783:                ce->unserialize = NULL;
                   6784:                ce->serialize_func = NULL;
                   6785:                ce->unserialize_func = NULL;
1.1.1.2 ! misho    6786:                if (ce->type == ZEND_INTERNAL_CLASS) {
        !          6787:                        ce->info.internal.module = NULL;
        !          6788:                        ce->info.internal.builtin_functions = NULL;
        !          6789:                }
1.1       misho    6790:        }
                   6791: }
                   6792: /* }}} */
                   6793: 
                   6794: int zend_get_class_fetch_type(const char *class_name, uint class_name_len) /* {{{ */
                   6795: {
                   6796:        if ((class_name_len == sizeof("self")-1) &&
                   6797:                !memcmp(class_name, "self", sizeof("self")-1)) {
                   6798:                return ZEND_FETCH_CLASS_SELF;           
                   6799:        } else if ((class_name_len == sizeof("parent")-1) &&
                   6800:                !memcmp(class_name, "parent", sizeof("parent")-1)) {
                   6801:                return ZEND_FETCH_CLASS_PARENT;
                   6802:        } else if ((class_name_len == sizeof("static")-1) &&
                   6803:                !memcmp(class_name, "static", sizeof("static")-1)) {
                   6804:                return ZEND_FETCH_CLASS_STATIC;
                   6805:        } else {
                   6806:                return ZEND_FETCH_CLASS_DEFAULT;
                   6807:        }
                   6808: }
                   6809: /* }}} */
                   6810: 
1.1.1.2 ! misho    6811: ZEND_API const char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len) /* {{{ */
1.1       misho    6812: {
                   6813:        if (name_len) {
                   6814:                *name_len = op_array->vars[var].name_len;
                   6815:        }
                   6816:        return op_array->vars[var].name;
                   6817: }
                   6818: /* }}} */
                   6819: 
                   6820: void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */
                   6821: {
                   6822:        if (prefix) {
                   6823:                *result = *prefix;
                   6824:                if (Z_TYPE(result->u.constant) == IS_STRING &&
1.1.1.2 ! misho    6825:                    Z_STRLEN(result->u.constant) == 0) {
1.1       misho    6826:                        /* namespace\ */
                   6827:                        if (CG(current_namespace)) {
                   6828:                                znode tmp;
                   6829: 
                   6830:                                zval_dtor(&result->u.constant);
                   6831:                                tmp.op_type = IS_CONST;
                   6832:                                tmp.u.constant = *CG(current_namespace);
                   6833:                                zval_copy_ctor(&tmp.u.constant);
                   6834:                                zend_do_build_namespace_name(result, NULL, &tmp TSRMLS_CC);
                   6835:                        }
                   6836:                }
                   6837:        } else {
                   6838:                result->op_type = IS_CONST;
                   6839:                Z_TYPE(result->u.constant) = IS_STRING;
                   6840:                Z_STRVAL(result->u.constant) = NULL;
                   6841:                Z_STRLEN(result->u.constant) = 0;
                   6842:        }
                   6843:        /* prefix = result */
                   6844:        zend_do_build_full_name(NULL, result, name, 0 TSRMLS_CC);
                   6845: }
                   6846: /* }}} */
                   6847: 
                   6848: void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC) /* {{{ */
                   6849: {
                   6850:        char *lcname;
                   6851: 
                   6852:        /* handle mixed syntax declaration or nested namespaces */
                   6853:        if (!CG(has_bracketed_namespaces)) {
                   6854:                if (CG(current_namespace)) {
                   6855:                        /* previous namespace declarations were unbracketed */
                   6856:                        if (with_bracket) {
                   6857:                                zend_error(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
                   6858:                        }
                   6859:                }
                   6860:        } else {
                   6861:                /* previous namespace declarations were bracketed */
                   6862:                if (!with_bracket) {
                   6863:                        zend_error(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
                   6864:                } else if (CG(current_namespace) || CG(in_namespace)) {
                   6865:                        zend_error(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
                   6866:                }
                   6867:        }
                   6868: 
                   6869:        if (((!with_bracket && !CG(current_namespace)) || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0) {
                   6870:                /* ignore ZEND_EXT_STMT and ZEND_TICKS */
                   6871:                int num = CG(active_op_array)->last;
                   6872:                while (num > 0 &&
1.1.1.2 ! misho    6873:                       (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
        !          6874:                        CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
1.1       misho    6875:                        --num;
                   6876:                }
                   6877:                if (num > 0) {
                   6878:                        zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
                   6879:                }
                   6880:        }
                   6881: 
                   6882:        CG(in_namespace) = 1;
                   6883:        if (with_bracket) {
                   6884:                CG(has_bracketed_namespaces) = 1;
                   6885:        }
                   6886: 
                   6887:        if (name) {
                   6888:                lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
                   6889:                if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
1.1.1.2 ! misho    6890:                      !memcmp(lcname, "self", sizeof("self")-1)) ||
        !          6891:                    ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
        !          6892:                  !memcmp(lcname, "parent", sizeof("parent")-1))) {
1.1       misho    6893:                        zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
                   6894:                }
                   6895:                efree(lcname);
                   6896: 
                   6897:                if (CG(current_namespace)) {
                   6898:                        zval_dtor(CG(current_namespace));
                   6899:                } else {
                   6900:                        ALLOC_ZVAL(CG(current_namespace));
                   6901:                }
                   6902:                *CG(current_namespace) = name->u.constant;
                   6903:        } else {
                   6904:                if (CG(current_namespace)) {
                   6905:                        zval_dtor(CG(current_namespace));
                   6906:                        FREE_ZVAL(CG(current_namespace));
                   6907:                        CG(current_namespace) = NULL;
                   6908:                }
                   6909:        }
                   6910: 
                   6911:        if (CG(current_import)) {
                   6912:                zend_hash_destroy(CG(current_import));
                   6913:                efree(CG(current_import));
                   6914:                CG(current_import) = NULL;
                   6915:        }
1.1.1.2 ! misho    6916:        
1.1       misho    6917:        if (CG(doc_comment)) {
                   6918:                efree(CG(doc_comment));
                   6919:                CG(doc_comment) = NULL;
                   6920:                CG(doc_comment_len) = 0;
                   6921:        }
                   6922: }
                   6923: /* }}} */
                   6924: 
                   6925: void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
                   6926: {
                   6927:        char *lcname;
                   6928:        zval *name, *ns, tmp;
                   6929:        zend_bool warn = 0;
                   6930:        zend_class_entry **pce;
                   6931: 
                   6932:        if (!CG(current_import)) {
                   6933:                CG(current_import) = emalloc(sizeof(HashTable));
                   6934:                zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
                   6935:        }
                   6936: 
                   6937:        ALLOC_ZVAL(ns);
                   6938:        *ns = ns_name->u.constant;
                   6939:        if (new_name) {
                   6940:                name = &new_name->u.constant;
                   6941:        } else {
1.1.1.2 ! misho    6942:                const char *p;
1.1       misho    6943: 
                   6944:                /* The form "use A\B" is eqivalent to "use A\B as B".
                   6945:                   So we extract the last part of compound name to use as a new_name */
                   6946:                name = &tmp;
                   6947:                p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
                   6948:                if (p) {
                   6949:                        ZVAL_STRING(name, p+1, 1);
                   6950:                } else {
                   6951:                        *name = *ns;
                   6952:                        zval_copy_ctor(name);
                   6953:                        warn = !is_global && !CG(current_namespace);
                   6954:                }
                   6955:        }
                   6956: 
                   6957:        lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
                   6958: 
                   6959:        if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
1.1.1.2 ! misho    6960:           !memcmp(lcname, "self", sizeof("self")-1)) ||
        !          6961:            ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
        !          6962:           !memcmp(lcname, "parent", sizeof("parent")-1))) {
1.1       misho    6963:                zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
                   6964:        }
                   6965: 
                   6966:        if (CG(current_namespace)) {
                   6967:                /* Prefix import name with current namespace name to avoid conflicts with classes */
                   6968:                char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
                   6969: 
                   6970:                zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
                   6971:                c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
                   6972:                memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
                   6973:                if (zend_hash_exists(CG(class_table), c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
                   6974:                        char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
                   6975: 
                   6976:                        if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
                   6977:                                memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
                   6978:                                zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
                   6979:                        }
                   6980:                        efree(tmp2);
                   6981:                }
                   6982:                efree(c_ns_name);
                   6983:        } else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
                   6984:                   (*pce)->type == ZEND_USER_CLASS &&
1.1.1.2 ! misho    6985:                   (*pce)->info.user.filename == CG(compiled_filename)) {
1.1       misho    6986:                char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
                   6987: 
                   6988:                if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
                   6989:                        memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
                   6990:                        zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
                   6991:                }
                   6992:                efree(c_tmp);
                   6993:        }
                   6994: 
                   6995:        if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
                   6996:                zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
                   6997:        }
                   6998:        if (warn) {
1.1.1.2 ! misho    6999:                if (!strcmp(Z_STRVAL_P(name), "strict")) {
        !          7000:                        zend_error(E_COMPILE_ERROR, "You seem to be trying to use a different language...");
        !          7001:                }
1.1       misho    7002:                zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
                   7003:        }
                   7004:        efree(lcname);
                   7005:        zval_dtor(name);
                   7006: }
                   7007: /* }}} */
                   7008: 
                   7009: void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
                   7010: {
                   7011:        zend_op *opline;
                   7012: 
                   7013:        if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
                   7014:                zend_error(E_COMPILE_ERROR, "Arrays are not allowed as constants");
                   7015:        }
                   7016: 
                   7017:        if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
                   7018:                zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
                   7019:        }
                   7020: 
                   7021:        if (CG(current_namespace)) {
                   7022:                /* Prefix constant name with name of current namespace, lowercased */
                   7023:                znode tmp;
                   7024: 
                   7025:                tmp.op_type = IS_CONST;
                   7026:                tmp.u.constant = *CG(current_namespace);
                   7027:                Z_STRVAL(tmp.u.constant) = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
                   7028:                zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
                   7029:                *name = tmp;
                   7030:        }
                   7031: 
                   7032:        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
                   7033:        opline->opcode = ZEND_DECLARE_CONST;
                   7034:        SET_UNUSED(opline->result);
1.1.1.2 ! misho    7035:        SET_NODE(opline->op1, name);
        !          7036:        SET_NODE(opline->op2, value);
1.1       misho    7037: }
                   7038: /* }}} */
                   7039: 
                   7040: void zend_verify_namespace(TSRMLS_D) /* {{{ */
                   7041: {
                   7042:        if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
                   7043:                zend_error(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
                   7044:        }
                   7045: }
                   7046: /* }}} */
                   7047: 
                   7048: void zend_do_end_namespace(TSRMLS_D) /* {{{ */
                   7049: {
                   7050:        CG(in_namespace) = 0;
                   7051:        if (CG(current_namespace)) {
                   7052:                zval_dtor(CG(current_namespace));
                   7053:                FREE_ZVAL(CG(current_namespace));
                   7054:                CG(current_namespace) = NULL;
                   7055:        }
                   7056:        if (CG(current_import)) {
                   7057:                zend_hash_destroy(CG(current_import));
                   7058:                efree(CG(current_import));
                   7059:                CG(current_import) = NULL;
                   7060:        }
                   7061: }
                   7062: /* }}} */
                   7063: 
                   7064: void zend_do_end_compilation(TSRMLS_D) /* {{{ */
                   7065: {
                   7066:        CG(has_bracketed_namespaces) = 0;
                   7067:        zend_do_end_namespace(TSRMLS_C);
                   7068: }
                   7069: /* }}} */
                   7070: 
                   7071: /* {{{ zend_dirname
                   7072:    Returns directory name component of path */
                   7073: ZEND_API size_t zend_dirname(char *path, size_t len)
                   7074: {
                   7075:        register char *end = path + len - 1;
                   7076:        unsigned int len_adjust = 0;
                   7077: 
                   7078: #ifdef PHP_WIN32
                   7079:        /* Note that on Win32 CWD is per drive (heritage from CP/M).
                   7080:         * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
                   7081:         */
                   7082:        if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
                   7083:                /* Skip over the drive spec (if any) so as not to change */
                   7084:                path += 2;
                   7085:                len_adjust += 2;
                   7086:                if (2 == len) {
                   7087:                        /* Return "c:" on Win32 for dirname("c:").
                   7088:                         * It would be more consistent to return "c:." 
                   7089:                         * but that would require making the string *longer*.
                   7090:                         */
                   7091:                        return len;
                   7092:                }
                   7093:        }
                   7094: #elif defined(NETWARE)
                   7095:        /*
                   7096:         * Find the first occurence of : from the left 
                   7097:         * move the path pointer to the position just after :
                   7098:         * increment the len_adjust to the length of path till colon character(inclusive)
                   7099:         * If there is no character beyond : simple return len
                   7100:         */
                   7101:        char *colonpos = NULL;
                   7102:        colonpos = strchr(path, ':');
                   7103:        if (colonpos != NULL) {
                   7104:                len_adjust = ((colonpos - path) + 1);
                   7105:                path += len_adjust;
                   7106:                if (len_adjust == len) {
                   7107:                        return len;
                   7108:                }
                   7109:        }
                   7110: #endif
                   7111: 
                   7112:        if (len == 0) {
                   7113:                /* Illegal use of this function */
                   7114:                return 0;
                   7115:        }
                   7116: 
                   7117:        /* Strip trailing slashes */
                   7118:        while (end >= path && IS_SLASH_P(end)) {
                   7119:                end--;
                   7120:        }
                   7121:        if (end < path) {
                   7122:                /* The path only contained slashes */
                   7123:                path[0] = DEFAULT_SLASH;
                   7124:                path[1] = '\0';
                   7125:                return 1 + len_adjust;
                   7126:        }
                   7127: 
                   7128:        /* Strip filename */
                   7129:        while (end >= path && !IS_SLASH_P(end)) {
                   7130:                end--;
                   7131:        }
                   7132:        if (end < path) {
                   7133:                /* No slash found, therefore return '.' */
                   7134: #ifdef NETWARE
                   7135:                if (len_adjust == 0) {
                   7136:                        path[0] = '.';
                   7137:                        path[1] = '\0';
                   7138:                        return 1; /* only one character */
                   7139:                } else {
                   7140:                        path[0] = '\0';
                   7141:                        return len_adjust;
                   7142:                }
                   7143: #else
                   7144:                path[0] = '.';
                   7145:                path[1] = '\0';
                   7146:                return 1 + len_adjust;
                   7147: #endif
                   7148:        }
                   7149: 
                   7150:        /* Strip slashes which came before the file name */
                   7151:        while (end >= path && IS_SLASH_P(end)) {
                   7152:                end--;
                   7153:        }
                   7154:        if (end < path) {
                   7155:                path[0] = DEFAULT_SLASH;
                   7156:                path[1] = '\0';
                   7157:                return 1 + len_adjust;
                   7158:        }
                   7159:        *(end+1) = '\0';
                   7160: 
                   7161:        return (size_t)(end + 1 - path) + len_adjust;
                   7162: }
                   7163: /* }}} */
                   7164: 
                   7165: /*
                   7166:  * Local variables:
                   7167:  * tab-width: 4
                   7168:  * c-basic-offset: 4
                   7169:  * indent-tabs-mode: t
                   7170:  * End:
                   7171:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>