1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
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
31#ifdef ZEND_MULTIBYTE
32#include "zend_multibyte.h"
33#endif /* ZEND_MULTIBYTE */
34
35ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
36ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
37
38#ifndef ZTS
39ZEND_API zend_compiler_globals compiler_globals;
40ZEND_API zend_executor_globals executor_globals;
41#endif
42
43static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
44{
45    property_info->name = estrndup(property_info->name, property_info->name_length);
46    if (property_info->doc_comment) {
47        property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
48    }
49}
50/* }}} */
51
52
53static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
54{
55    property_info->name = zend_strndup(property_info->name, property_info->name_length);
56}
57/* }}} */
58
59
60static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
61{
62    efree(property_info->name);
63    if (property_info->doc_comment) {
64        efree(property_info->doc_comment);
65    }
66}
67/* }}} */
68
69
70static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
71{
72    free(property_info->name);
73}
74/* }}} */
75
76static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
77{
78    char char_pos_buf[32];
79    uint char_pos_len;
80    char *filename;
81
82    char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
83    if (CG(active_op_array)->filename) {
84        filename = CG(active_op_array)->filename;
85    } else {
86        filename = "-";
87    }
88
89    /* NULL, name length, filename length, last accepting char position length */
90    result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
91#ifdef ZEND_MULTIBYTE
92    /* must be binary safe */
93    result->value.str.val = (char *) safe_emalloc(result->value.str.len, 1, 1);
94    result->value.str.val[0] = '\0';
95    sprintf(result->value.str.val+1, "%s%s%s", name, filename, char_pos_buf);
96#else
97    zend_spprintf(&result->value.str.val, 0, "%c%s%s%s", '\0', name, filename, char_pos_buf);
98#endif /* ZEND_MULTIBYTE */
99    result->type = IS_STRING;
100    Z_SET_REFCOUNT_P(result, 1);
101}
102/* }}} */
103
104
105int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
106{
107    auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
108    return 0;
109}
110/* }}} */
111
112
113ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */
114{
115    zend_auto_global *auto_global;
116
117    if (zend_hash_find(CG(auto_globals), varname, varname_length+1, (void **) &auto_global)==FAILURE) {
118        return FAILURE;
119    }
120    auto_global->armed = 0;
121    return SUCCESS;
122}
123/* }}} */
124
125
126static void init_compiler_declarables(TSRMLS_D) /* {{{ */
127{
128    Z_TYPE(CG(declarables).ticks) = IS_LONG;
129    Z_LVAL(CG(declarables).ticks) = 0;
130}
131/* }}} */
132
133
134void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
135{
136    zend_stack_init(&CG(bp_stack));
137    zend_stack_init(&CG(function_call_stack));
138    zend_stack_init(&CG(switch_cond_stack));
139    zend_stack_init(&CG(foreach_copy_stack));
140    zend_stack_init(&CG(object_stack));
141    zend_stack_init(&CG(declare_stack));
142    CG(active_class_entry) = NULL;
143    zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
144    zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
145    zend_stack_init(&CG(list_stack));
146    CG(in_compilation) = 0;
147    CG(start_lineno) = 0;
148    CG(current_namespace) = NULL;
149    CG(in_namespace) = 0;
150    CG(has_bracketed_namespaces) = 0;
151    CG(current_import) = NULL;
152    init_compiler_declarables(TSRMLS_C);
153    zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
154    zend_stack_init(&CG(labels_stack));
155    CG(labels) = NULL;
156
157#ifdef ZEND_MULTIBYTE
158    CG(script_encoding_list) = NULL;
159    CG(script_encoding_list_size) = 0;
160    CG(internal_encoding) = NULL;
161    CG(encoding_detector) = NULL;
162    CG(encoding_converter) = NULL;
163    CG(encoding_oddlen) = NULL;
164    CG(encoding_declared) = 0;
165#endif /* ZEND_MULTIBYTE */
166}
167/* }}} */
168
169
170ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
171{
172    TSRMLS_FETCH();
173
174    zend_file_handle_dtor(fh TSRMLS_CC);
175}
176/* }}} */
177
178
179void init_compiler(TSRMLS_D) /* {{{ */
180{
181    CG(active_op_array) = NULL;
182    zend_init_compiler_data_structures(TSRMLS_C);
183    zend_init_rsrc_list(TSRMLS_C);
184    zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
185    zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
186    CG(unclean_shutdown) = 0;
187}
188/* }}} */
189
190
191void shutdown_compiler(TSRMLS_D) /* {{{ */
192{
193    zend_stack_destroy(&CG(bp_stack));
194    zend_stack_destroy(&CG(function_call_stack));
195    zend_stack_destroy(&CG(switch_cond_stack));
196    zend_stack_destroy(&CG(foreach_copy_stack));
197    zend_stack_destroy(&CG(object_stack));
198    zend_stack_destroy(&CG(declare_stack));
199    zend_stack_destroy(&CG(list_stack));
200    zend_hash_destroy(&CG(filenames_table));
201    zend_llist_destroy(&CG(open_files));
202    zend_stack_destroy(&CG(labels_stack));
203
204#ifdef ZEND_MULTIBYTE
205    if (CG(script_encoding_list)) {
206        efree(CG(script_encoding_list));
207    }
208#endif /* ZEND_MULTIBYTE */
209}
210/* }}} */
211
212
213ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
214{
215    char **pp, *p;
216    int length = strlen(new_compiled_filename);
217
218    if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
219        CG(compiled_filename) = *pp;
220        return *pp;
221    }
222    p = estrndup(new_compiled_filename, length);
223    zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
224    CG(compiled_filename) = p;
225    return p;
226}
227/* }}} */
228
229
230ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
231{
232    CG(compiled_filename) = original_compiled_filename;
233}
234/* }}} */
235
236
237ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
238{
239    return CG(compiled_filename);
240}
241/* }}} */
242
243
244ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
245{
246    return CG(zend_lineno);
247}
248/* }}} */
249
250
251ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
252{
253    return CG(in_compilation);
254}
255/* }}} */
256
257
258static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
259{
260    return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
261}
262/* }}} */
263
264static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ */
265{
266    int i = 0;
267    ulong hash_value = zend_inline_hash_func(name, name_len+1);
268
269    while (i < op_array->last_var) {
270        if (op_array->vars[i].hash_value == hash_value &&
271            op_array->vars[i].name_len == name_len &&
272            strcmp(op_array->vars[i].name, name) == 0) {
273          efree(name);
274          return i;
275        }
276        i++;
277    }
278    i = op_array->last_var;
279    op_array->last_var++;
280    if (op_array->last_var > op_array->size_var) {
281        op_array->size_var += 16; /* FIXME */
282        op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
283    }
284    op_array->vars[i].name = name; /* estrndup(name, name_len); */
285    op_array->vars[i].name_len = name_len;
286    op_array->vars[i].hash_value = hash_value;
287    return i;
288}
289/* }}} */
290
291
292void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
293{
294    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
295
296    opline->opcode = op;
297    opline->result.op_type = IS_TMP_VAR;
298    opline->result.u.var = get_temporary_variable(CG(active_op_array));
299    opline->op1 = *op1;
300    opline->op2 = *op2;
301    *result = opline->result;
302}
303/* }}} */
304
305void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
306{
307    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
308
309    opline->opcode = op;
310    opline->result.op_type = IS_TMP_VAR;
311    opline->result.u.var = get_temporary_variable(CG(active_op_array));
312    opline->op1 = *op1;
313    *result = opline->result;
314    SET_UNUSED(opline->op2);
315}
316/* }}} */
317
318#define MAKE_NOP(opline)    { opline->opcode = ZEND_NOP;  memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED;  }
319
320
321static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
322{
323    data_op->opcode = ZEND_OP_DATA;
324    data_op->op1 = *value;
325    SET_UNUSED(data_op->op2);
326}
327/* }}} */
328
329void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
330{
331    int last_op_number = get_next_op_number(CG(active_op_array));
332    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
333
334    if (last_op_number > 0) {
335        zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
336
337        switch (last_op->opcode) {
338            case ZEND_FETCH_OBJ_RW:
339                last_op->opcode = op;
340                last_op->extended_value = ZEND_ASSIGN_OBJ;
341
342                zend_do_op_data(opline, op2 TSRMLS_CC);
343                SET_UNUSED(opline->result);
344                *result = last_op->result;
345                return;
346            case ZEND_FETCH_DIM_RW:
347                last_op->opcode = op;
348                last_op->extended_value = ZEND_ASSIGN_DIM;
349
350                zend_do_op_data(opline, op2 TSRMLS_CC);
351                opline->op2.u.var = get_temporary_variable(CG(active_op_array));
352                opline->op2.u.EA.type = 0;
353                opline->op2.op_type = IS_VAR;
354                SET_UNUSED(opline->result);
355                *result = last_op->result;
356                return;
357            default:
358                break;
359        }
360    }
361
362    opline->opcode = op;
363    opline->op1 = *op1;
364    opline->op2 = *op2;
365    opline->result.op_type = IS_VAR;
366    opline->result.u.EA.type = 0;
367    opline->result.u.var = get_temporary_variable(CG(active_op_array));
368    *result = opline->result;
369}
370/* }}} */
371
372void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
373{
374    zend_op opline;
375    zend_op *opline_ptr;
376    zend_llist *fetch_list_ptr;
377
378    if (varname->op_type == IS_CONST) {
379        if (Z_TYPE(varname->u.constant) != IS_STRING) {
380            convert_to_string(&varname->u.constant);
381        }
382        if (!zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC) &&
383            !(varname->u.constant.value.str.len == (sizeof("this")-1) &&
384              !memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
385            (CG(active_op_array)->last == 0 ||
386             CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
387            result->op_type = IS_CV;
388            result->u.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
389            result->u.EA.type = 0;
390            varname->u.constant.value.str.val = CG(active_op_array)->vars[result->u.var].name;
391            return;
392        }
393    }
394
395    if (bp) {
396        opline_ptr = &opline;
397        init_op(opline_ptr TSRMLS_CC);
398    } else {
399        opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
400    }
401
402    opline_ptr->opcode = op;
403    opline_ptr->result.op_type = IS_VAR;
404    opline_ptr->result.u.EA.type = 0;
405    opline_ptr->result.u.var = get_temporary_variable(CG(active_op_array));
406    opline_ptr->op1 = *varname;
407    *result = opline_ptr->result;
408    SET_UNUSED(opline_ptr->op2);
409
410    opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
411    if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
412        if (zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC)) {
413            opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
414        }
415    }
416
417    if (bp) {
418        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
419        zend_llist_add_element(fetch_list_ptr, opline_ptr);
420    }
421}
422/* }}} */
423
424void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
425{
426    /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
427    fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
428}
429/* }}} */
430
431void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
432{
433    znode class_node;
434    zend_llist *fetch_list_ptr;
435    zend_llist_element *le;
436    zend_op *opline_ptr;
437    zend_op opline;
438
439    zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
440    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
441    if (result->op_type == IS_CV) {
442        init_op(&opline TSRMLS_CC);
443
444        opline.opcode = ZEND_FETCH_W;
445        opline.result.op_type = IS_VAR;
446        opline.result.u.EA.type = 0;
447        opline.result.u.var = get_temporary_variable(CG(active_op_array));
448        opline.op1.op_type = IS_CONST;
449        opline.op1.u.constant.type = IS_STRING;
450        opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
451        opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
452        SET_UNUSED(opline.op2);
453        opline.op2 = class_node;
454        opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
455        *result = opline.result;
456
457        zend_llist_add_element(fetch_list_ptr, &opline);
458    } else {
459        le = fetch_list_ptr->head;
460
461        opline_ptr = (zend_op *)le->data;
462        if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1.op_type == IS_CV) {
463            init_op(&opline TSRMLS_CC);
464            opline.opcode = ZEND_FETCH_W;
465            opline.result.op_type = IS_VAR;
466            opline.result.u.EA.type = 0;
467            opline.result.u.var = get_temporary_variable(CG(active_op_array));
468            opline.op1.op_type = IS_CONST;
469            opline.op1.u.constant.type = IS_STRING;
470            opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
471            opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
472            SET_UNUSED(opline.op2);
473            opline.op2 = class_node;
474            opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
475            opline_ptr->op1 = opline.result;
476
477            zend_llist_prepend_element(fetch_list_ptr, &opline);
478        } else {
479            opline_ptr->op2 = class_node;
480            opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
481        }
482    }
483}
484/* }}} */
485
486void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
487{
488    fetch_simple_variable(result, varname, 1 TSRMLS_CC);
489
490    fetch_array_dim(result, result, first_dim TSRMLS_CC);
491}
492/* }}} */
493
494void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
495{
496    zend_op opline;
497    zend_llist *fetch_list_ptr;
498
499    init_op(&opline TSRMLS_CC);
500    opline.opcode = ZEND_FETCH_DIM_W;   /* the backpatching routine assumes W */
501    opline.result.op_type = IS_VAR;
502    opline.result.u.EA.type = 0;
503    opline.result.u.var = get_temporary_variable(CG(active_op_array));
504    opline.op1 = *parent;
505    opline.op2 = *dim;
506    opline.extended_value = ZEND_FETCH_STANDARD;
507    *result = opline.result;
508
509    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
510    zend_llist_add_element(fetch_list_ptr, &opline);
511}
512/* }}} */
513
514void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
515{
516    fetch_array_dim(result, parent, offset TSRMLS_CC);
517}
518/* }}} */
519
520void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
521{
522    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
523
524    opline->result.op_type = IS_TMP_VAR;
525    opline->result.u.var = get_temporary_variable(CG(active_op_array));
526    opline->opcode = ZEND_PRINT;
527    opline->op1 = *arg;
528    SET_UNUSED(opline->op2);
529    *result = opline->result;
530}
531/* }}} */
532
533void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
534{
535    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
536
537    opline->opcode = ZEND_ECHO;
538    opline->op1 = *arg;
539    SET_UNUSED(opline->op2);
540}
541/* }}} */
542
543void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
544{
545    char *method_type;
546
547    if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
548        Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
549        method_type = "Interface";
550    } else {
551        method_type = "Abstract";
552    }
553
554    if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
555        if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) {
556            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);
557        }
558        if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
559            zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
560
561            opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
562            SET_UNUSED(opline->op1);
563            SET_UNUSED(opline->op2);
564        } else {
565            /* we had code in the function body */
566            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);
567        }
568    } else {
569        if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) {
570            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);
571        }
572    }
573}
574/* }}} */
575
576static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
577{
578    if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
579        && (opline->op1.u.constant.type == IS_STRING)
580        && (opline->op1.u.constant.value.str.len == (sizeof("this")-1))
581        && !memcmp(opline->op1.u.constant.value.str.val, "this", sizeof("this"))) {
582        return 1;
583    } else {
584        return 0;
585    }
586}
587/* }}} */
588
589void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC) /* {{{ */
590{
591    int last_op_number;
592    zend_op *opline;
593
594    if (value->op_type == IS_CV) {
595        zend_llist *fetch_list_ptr;
596
597        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
598        if (fetch_list_ptr && fetch_list_ptr->head) {
599            opline = (zend_op *)fetch_list_ptr->head->data;
600
601            if (opline->opcode == ZEND_FETCH_DIM_W &&
602                opline->op1.op_type == IS_CV &&
603                opline->op1.u.var == value->u.var) {
604
605                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
606                opline->opcode = ZEND_FETCH_R;
607                opline->result.op_type = IS_VAR;
608                opline->result.u.EA.type = 0;
609                opline->result.u.var = get_temporary_variable(CG(active_op_array));
610                opline->op1.op_type = IS_CONST;
611                ZVAL_STRINGL(&opline->op1.u.constant,
612                    CG(active_op_array)->vars[value->u.var].name,
613                    CG(active_op_array)->vars[value->u.var].name_len, 1);
614                SET_UNUSED(opline->op2);
615                opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
616                value = &opline->result;
617            }
618        }
619    }
620
621    zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
622
623    last_op_number = get_next_op_number(CG(active_op_array));
624    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
625
626    if (variable->op_type == IS_CV) {
627        if (variable->u.var == CG(active_op_array)->this_var) {
628            zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
629        }
630    } else if (variable->op_type == IS_VAR) {
631        int n = 0;
632
633        while (last_op_number - n > 0) {
634            zend_op *last_op;
635
636            last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
637
638            if (last_op->result.op_type == IS_VAR &&
639                last_op->result.u.var == variable->u.var) {
640                if (last_op->opcode == ZEND_FETCH_OBJ_W) {
641                    if (n > 0) {
642                        int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
643                        *opline = *last_op;
644                        MAKE_NOP(last_op);
645                        /* last_op = opline; */
646                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
647                        /* get_next_op can realloc, we need to move last_op */
648                        last_op = &CG(active_op_array)->opcodes[opline_no];
649                    }
650                    last_op->opcode = ZEND_ASSIGN_OBJ;
651                    zend_do_op_data(opline, value TSRMLS_CC);
652                    SET_UNUSED(opline->result);
653                    *result = last_op->result;
654                    return;
655                } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
656                    if (n > 0) {
657                        int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
658                        *opline = *last_op;
659                        MAKE_NOP(last_op);
660                        /* last_op = opline; */
661                        /* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
662                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
663                        /* get_next_op can realloc, we need to move last_op */
664                        last_op = &CG(active_op_array)->opcodes[opline_no];
665                    }
666                    last_op->opcode = ZEND_ASSIGN_DIM;
667                    zend_do_op_data(opline, value TSRMLS_CC);
668                    opline->op2.u.var = get_temporary_variable(CG(active_op_array));
669                    opline->op2.u.EA.type = 0;
670                    opline->op2.op_type = IS_VAR;
671                    SET_UNUSED(opline->result);
672                    *result = last_op->result;
673                    return;
674                } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
675                    zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
676                } else {
677                    break;
678                }
679            }
680            n++;
681        }
682    }
683
684    opline->opcode = ZEND_ASSIGN;
685    opline->op1 = *variable;
686    opline->op2 = *value;
687    opline->result.op_type = IS_VAR;
688    opline->result.u.EA.type = 0;
689    opline->result.u.var = get_temporary_variable(CG(active_op_array));
690    *result = opline->result;
691}
692/* }}} */
693
694static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
695{
696    zend_uint type = variable->u.EA.type;
697
698    return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
699}
700/* }}} */
701
702void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
703{
704    zend_op *opline;
705
706    if (lvar->op_type == IS_CV) {
707        if (lvar->u.var == CG(active_op_array)->this_var) {
708            zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
709        }
710    } else if (lvar->op_type == IS_VAR) {
711        int last_op_number = get_next_op_number(CG(active_op_array));
712
713        if (last_op_number > 0) {
714            opline = &CG(active_op_array)->opcodes[last_op_number-1];
715            if (opline_is_fetch_this(opline TSRMLS_CC)) {
716                zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
717            }
718        }
719    }
720
721    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
722    opline->opcode = ZEND_ASSIGN_REF;
723    if (zend_is_function_or_method_call(rvar)) {
724        opline->extended_value = ZEND_RETURNS_FUNCTION;
725    } else if (rvar->u.EA.type & ZEND_PARSED_NEW) {
726        opline->extended_value = ZEND_RETURNS_NEW;
727    } else {
728        opline->extended_value = 0;
729    }
730    if (result) {
731        opline->result.op_type = IS_VAR;
732        opline->result.u.EA.type = 0;
733        opline->result.u.var = get_temporary_variable(CG(active_op_array));
734        *result = opline->result;
735    } else {
736        /* SET_UNUSED(opline->result); */
737        opline->result.u.EA.type |= EXT_TYPE_UNUSED;
738    }
739    opline->op1 = *lvar;
740    opline->op2 = *rvar;
741}
742/* }}} */
743
744static inline void do_begin_loop(TSRMLS_D) /* {{{ */
745{
746    zend_brk_cont_element *brk_cont_element;
747    int parent;
748
749    parent = CG(active_op_array)->current_brk_cont;
750    CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
751    brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
752    brk_cont_element->start = get_next_op_number(CG(active_op_array));
753    brk_cont_element->parent = parent;
754}
755/* }}} */
756
757static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
758{
759    if (!has_loop_var) {
760        /* The start fileld is used to free temporary variables in case of exceptions.
761         * We won't try to free something of we don't have loop variable.
762         */
763        CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
764    }
765    CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
766    CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
767    CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
768}
769/* }}} */
770
771void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
772{
773    int while_cond_op_number = get_next_op_number(CG(active_op_array));
774    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
775
776    opline->opcode = ZEND_JMPZ;
777    opline->op1 = *expr;
778    close_bracket_token->u.opline_num = while_cond_op_number;
779    SET_UNUSED(opline->op2);
780
781    do_begin_loop(TSRMLS_C);
782    INC_BPC(CG(active_op_array));
783}
784/* }}} */
785
786void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
787{
788    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
789
790    /* add unconditional jump */
791    opline->opcode = ZEND_JMP;
792    opline->op1.u.opline_num = while_token->u.opline_num;
793    SET_UNUSED(opline->op1);
794    SET_UNUSED(opline->op2);
795
796    /* update while's conditional jmp */
797    CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
798
799    do_end_loop(while_token->u.opline_num, 0 TSRMLS_CC);
800
801    DEC_BPC(CG(active_op_array));
802}
803/* }}} */
804
805void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
806{
807    int for_cond_op_number = get_next_op_number(CG(active_op_array));
808    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
809
810    opline->opcode = ZEND_JMPZNZ;
811    opline->op1 = *expr;  /* the conditional expression */
812    second_semicolon_token->u.opline_num = for_cond_op_number;
813    SET_UNUSED(opline->op2);
814}
815/* }}} */
816
817void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
818{
819    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
820
821    opline->opcode = ZEND_JMP;
822    opline->op1.u.opline_num = cond_start->u.opline_num;
823    CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
824    SET_UNUSED(opline->op1);
825    SET_UNUSED(opline->op2);
826
827    do_begin_loop(TSRMLS_C);
828
829    INC_BPC(CG(active_op_array));
830}
831/* }}} */
832
833void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
834{
835    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
836
837    opline->opcode = ZEND_JMP;
838    opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1;
839    CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
840    SET_UNUSED(opline->op1);
841    SET_UNUSED(opline->op2);
842
843    do_end_loop(second_semicolon_token->u.opline_num+1, 0 TSRMLS_CC);
844
845    DEC_BPC(CG(active_op_array));
846}
847/* }}} */
848
849void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
850{
851    int last_op_number = get_next_op_number(CG(active_op_array));
852    zend_op *opline;
853
854    if (last_op_number > 0) {
855        zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
856
857        if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
858            last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
859            last_op->result.op_type = IS_VAR;
860            last_op->result.u.EA.type = 0;
861            last_op->result.u.var = get_temporary_variable(CG(active_op_array));
862            *result = last_op->result;
863            return;
864        }
865    }
866
867    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
868    opline->opcode = op;
869    opline->op1 = *op1;
870    SET_UNUSED(opline->op2);
871    opline->result.op_type = IS_VAR;
872    opline->result.u.EA.type = 0;
873    opline->result.u.var = get_temporary_variable(CG(active_op_array));
874    *result = opline->result;
875}
876/* }}} */
877
878void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
879{
880    int last_op_number = get_next_op_number(CG(active_op_array));
881    zend_op *opline;
882
883    if (last_op_number > 0) {
884        zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
885
886        if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
887            last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
888            last_op->result.op_type = IS_TMP_VAR;
889            last_op->result.u.var = get_temporary_variable(CG(active_op_array));
890            *result = last_op->result;
891            return;
892        }
893    }
894
895    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
896    opline->opcode = op;
897    opline->op1 = *op1;
898    SET_UNUSED(opline->op2);
899    opline->result.op_type = IS_TMP_VAR;
900    opline->result.u.var = get_temporary_variable(CG(active_op_array));
901    *result = opline->result;
902}
903/* }}} */
904
905void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
906{
907    int if_cond_op_number = get_next_op_number(CG(active_op_array));
908    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
909
910    opline->opcode = ZEND_JMPZ;
911    opline->op1 = *cond;
912    closing_bracket_token->u.opline_num = if_cond_op_number;
913    SET_UNUSED(opline->op2);
914    INC_BPC(CG(active_op_array));
915}
916/* }}} */
917
918void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
919{
920    int if_end_op_number = get_next_op_number(CG(active_op_array));
921    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
922    zend_llist *jmp_list_ptr;
923
924    opline->opcode = ZEND_JMP;
925    /* save for backpatching */
926    if (initialize) {
927        zend_llist jmp_list;
928
929        zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
930        zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
931    }
932    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
933    zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
934
935    CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1;
936    SET_UNUSED(opline->op1);
937    SET_UNUSED(opline->op2);
938}
939/* }}} */
940
941void zend_do_if_end(TSRMLS_D) /* {{{ */
942{
943    int next_op_number = get_next_op_number(CG(active_op_array));
944    zend_llist *jmp_list_ptr;
945    zend_llist_element *le;
946
947    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
948    for (le=jmp_list_ptr->head; le; le = le->next) {
949        CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number;
950    }
951    zend_llist_destroy(jmp_list_ptr);
952    zend_stack_del_top(&CG(bp_stack));
953    DEC_BPC(CG(active_op_array));
954}
955/* }}} */
956
957void zend_check_writable_variable(const znode *variable) /* {{{ */
958{
959    zend_uint type = variable->u.EA.type;
960
961    if (type & ZEND_PARSED_METHOD_CALL) {
962        zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
963    }
964    if (type == ZEND_PARSED_FUNCTION_CALL) {
965        zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
966    }
967}
968/* }}} */
969
970void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
971{
972    zend_llist fetch_list;
973
974    zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
975    zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
976}
977/* }}} */
978
979void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
980{
981    zend_llist *fetch_list_ptr;
982    zend_llist_element *le;
983    zend_op *opline = NULL;
984    zend_op *opline_ptr;
985    zend_uint this_var = -1;
986
987    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
988
989    le = fetch_list_ptr->head;
990
991    /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
992
993    if (le) {
994        opline_ptr = (zend_op *)le->data;
995        if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
996            /* convert to FETCH_?(this) into IS_CV */
997            if (CG(active_op_array)->last == 0 ||
998                CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
999
1000                this_var = opline_ptr->result.u.var;
1001                if (CG(active_op_array)->this_var == -1) {
1002                    CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(opline_ptr->op1.u.constant), Z_STRLEN(opline_ptr->op1.u.constant));
1003                } else {
1004                    efree(Z_STRVAL(opline_ptr->op1.u.constant));
1005                }
1006                le = le->next;
1007                if (variable->op_type == IS_VAR &&
1008                    variable->u.var == this_var) {
1009                    variable->op_type = IS_CV;
1010                    variable->u.var = CG(active_op_array)->this_var;
1011                }
1012            } else if (CG(active_op_array)->this_var == -1) {
1013                CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
1014            }
1015        }
1016
1017        while (le) {
1018            opline_ptr = (zend_op *)le->data;
1019            opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1020            memcpy(opline, opline_ptr, sizeof(zend_op));
1021            if (opline->op1.op_type == IS_VAR &&
1022                opline->op1.u.var == this_var) {
1023                opline->op1.op_type = IS_CV;
1024                opline->op1.u.var = CG(active_op_array)->this_var;
1025            }
1026            switch (type) {
1027                case BP_VAR_R:
1028                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
1029                        zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
1030                    }
1031                    opline->opcode -= 3;
1032                    break;
1033                case BP_VAR_W:
1034                    break;
1035                case BP_VAR_RW:
1036                    opline->opcode += 3;
1037                    break;
1038                case BP_VAR_IS:
1039                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
1040                        zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
1041                    }
1042                    opline->opcode += 6; /* 3+3 */
1043                    break;
1044                case BP_VAR_FUNC_ARG:
1045                    opline->opcode += 9; /* 3+3+3 */
1046                    opline->extended_value = arg_offset;
1047                    break;
1048                case BP_VAR_UNSET:
1049                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
1050                        zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
1051                    }
1052                    opline->opcode += 12; /* 3+3+3+3 */
1053                    break;
1054            }
1055            le = le->next;
1056        }
1057        if (opline && type == BP_VAR_W && arg_offset) {
1058            opline->extended_value = ZEND_FETCH_MAKE_REF;
1059        }
1060    }
1061    zend_llist_destroy(fetch_list_ptr);
1062    zend_stack_del_top(&CG(bp_stack));
1063}
1064/* }}} */
1065
1066void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
1067{
1068    zend_op *opline;
1069
1070    if (Z_STRLEN(op2->u.constant) > 1) {
1071        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1072        opline->opcode = ZEND_ADD_STRING;
1073    } else if (Z_STRLEN(op2->u.constant) == 1) {
1074        int ch = *Z_STRVAL(op2->u.constant);
1075
1076        /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
1077        efree(Z_STRVAL(op2->u.constant));
1078        ZVAL_LONG(&op2->u.constant, ch);
1079        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1080        opline->opcode = ZEND_ADD_CHAR;
1081    } else { /* String can be empty after a variable at the end of a heredoc */
1082        efree(Z_STRVAL(op2->u.constant));
1083        return;
1084    }
1085
1086    if (op1) {
1087        opline->op1 = *op1;
1088        opline->result = *op1;
1089    } else {
1090        SET_UNUSED(opline->op1);
1091        opline->result.op_type = IS_TMP_VAR;
1092        opline->result.u.var = get_temporary_variable(CG(active_op_array));
1093    }
1094    opline->op2 = *op2;
1095    *result = opline->result;
1096}
1097/* }}} */
1098
1099void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
1100{
1101    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1102
1103    opline->opcode = ZEND_ADD_VAR;
1104
1105    if (op1) {
1106        opline->op1 = *op1;
1107        opline->result = *op1;
1108    } else {
1109        SET_UNUSED(opline->op1);
1110        opline->result.op_type = IS_TMP_VAR;
1111        opline->result.u.var = get_temporary_variable(CG(active_op_array));
1112    }
1113    opline->op2 = *op2;
1114    *result = opline->result;
1115}
1116/* }}} */
1117
1118void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
1119{
1120    if (op1->op_type==IS_TMP_VAR) {
1121        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1122
1123        opline->opcode = ZEND_FREE;
1124        opline->op1 = *op1;
1125        SET_UNUSED(opline->op2);
1126    } else if (op1->op_type==IS_VAR) {
1127        zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1128
1129        while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
1130            opline--;
1131        }
1132        if (opline->result.op_type == IS_VAR
1133            && opline->result.u.var == op1->u.var) {
1134            opline->result.u.EA.type |= EXT_TYPE_UNUSED;
1135        } else {
1136            while (opline>CG(active_op_array)->opcodes) {
1137                if (opline->opcode == ZEND_FETCH_DIM_R
1138                    && opline->op1.op_type == IS_VAR
1139                    && opline->op1.u.var == op1->u.var) {
1140                    /* This should the end of a list() construct
1141                     * Mark its result as unused
1142                     */
1143                    opline->extended_value = ZEND_FETCH_STANDARD;
1144                    break;
1145                } else if (opline->result.op_type==IS_VAR
1146                    && opline->result.u.var == op1->u.var) {
1147                    if (opline->opcode == ZEND_NEW) {
1148                        opline->result.u.EA.type |= EXT_TYPE_UNUSED;
1149                    }
1150                    break;
1151                }
1152                opline--;
1153            }
1154        }
1155    } else if (op1->op_type == IS_CONST) {
1156        zval_dtor(&op1->u.constant);
1157    }
1158}
1159/* }}} */
1160
1161int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
1162{
1163    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
1164        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
1165        zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
1166    }
1167    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
1168        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
1169        zend_error(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
1170    }
1171    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
1172        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
1173        zend_error(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
1174    }
1175    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
1176        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
1177        zend_error(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
1178    }
1179    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)) {
1180        zend_error(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
1181    }
1182    return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
1183}
1184/* }}} */
1185
1186void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
1187{
1188    zend_op_array op_array;
1189    char *name = function_name->u.constant.value.str.val;
1190    int name_len = function_name->u.constant.value.str.len;
1191    int function_begin_line = function_token->u.opline_num;
1192    zend_uint fn_flags;
1193    char *lcname;
1194    zend_bool orig_interactive;
1195    ALLOCA_FLAG(use_heap)
1196
1197    if (is_method) {
1198        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1199            if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
1200                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);
1201            }
1202            Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
1203        }
1204        fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
1205    } else {
1206        fn_flags = 0;
1207    }
1208    if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
1209        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));
1210    }
1211
1212    function_token->u.op_array = CG(active_op_array);
1213    lcname = zend_str_tolower_dup(name, name_len);
1214
1215    orig_interactive = CG(interactive);
1216    CG(interactive) = 0;
1217    init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
1218    CG(interactive) = orig_interactive;
1219
1220    op_array.function_name = name;
1221    op_array.return_reference = return_reference;
1222    op_array.fn_flags |= fn_flags;
1223    op_array.pass_rest_by_reference = 0;
1224
1225    op_array.scope = is_method?CG(active_class_entry):NULL;
1226    op_array.prototype = NULL;
1227
1228    op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
1229
1230    if (is_method) {
1231        if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
1232            zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
1233        }
1234
1235        if (fn_flags & ZEND_ACC_ABSTRACT) {
1236            CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1237        }
1238
1239        if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
1240            fn_flags |= ZEND_ACC_PUBLIC;
1241        }
1242
1243        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1244            if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1245                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1246                    zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1247                }
1248            } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1249                if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1250                    zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1251                }
1252            } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1253                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1254                    zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1255                }
1256            } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1257                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1258                    zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1259                }
1260            } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1261                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1262                    zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1263                }
1264            } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1265                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1266                    zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1267                }
1268            } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1269                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1270                    zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1271                }
1272            }
1273        } else {
1274            char *class_lcname;
1275
1276            class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
1277            zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
1278            /* Improve after RC: cache the lowercase class name */
1279
1280            if ((CG(active_class_entry)->name_length == name_len) && (!memcmp(class_lcname, lcname, name_len))) {
1281                if (!CG(active_class_entry)->constructor) {
1282                    CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1283                }
1284            } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
1285                if (CG(active_class_entry)->constructor) {
1286                    zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
1287                }
1288                CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1289            } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
1290                CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
1291            } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
1292                CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
1293            } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1294                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1295                    zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1296                }
1297                CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
1298            } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1299                if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1300                    zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1301                }
1302                CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
1303            } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1304                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1305                    zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1306                }
1307                CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
1308            } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1309                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1310                    zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1311                }
1312                CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
1313            } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1314                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1315                    zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1316                }
1317                CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
1318            } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1319                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1320                    zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1321                }
1322                CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
1323            } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1324                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1325                    zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1326                }
1327                CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
1328            } else if (!(fn_flags & ZEND_ACC_STATIC)) {
1329                CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
1330            }
1331            free_alloca(class_lcname, use_heap);
1332        }
1333
1334        efree(lcname);
1335    } else {
1336        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1337
1338        if (CG(current_namespace)) {
1339            /* Prefix function name with current namespace name */
1340            znode tmp;
1341
1342            tmp.u.constant = *CG(current_namespace);
1343            zval_copy_ctor(&tmp.u.constant);
1344            zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
1345            op_array.function_name = Z_STRVAL(tmp.u.constant);
1346            efree(lcname);
1347            name_len = Z_STRLEN(tmp.u.constant);
1348            lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
1349        }
1350
1351        opline->opcode = ZEND_DECLARE_FUNCTION;
1352        opline->op1.op_type = IS_CONST;
1353        build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
1354        opline->op2.op_type = IS_CONST;
1355        opline->op2.u.constant.type = IS_STRING;
1356        opline->op2.u.constant.value.str.val = lcname;
1357        opline->op2.u.constant.value.str.len = name_len;
1358        Z_SET_REFCOUNT(opline->op2.u.constant, 1);
1359        opline->extended_value = ZEND_DECLARE_FUNCTION;
1360        zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
1361    }
1362
1363    if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
1364        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1365
1366        opline->opcode = ZEND_EXT_NOP;
1367        opline->lineno = function_begin_line;
1368        SET_UNUSED(opline->op1);
1369        SET_UNUSED(opline->op2);
1370    }
1371
1372    {
1373        /* Push a seperator to the switch and foreach stacks */
1374        zend_switch_entry switch_entry;
1375
1376        switch_entry.cond.op_type = IS_UNUSED;
1377        switch_entry.default_case = 0;
1378        switch_entry.control_var = 0;
1379
1380        zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
1381
1382        {
1383            /* Foreach stack separator */
1384            zend_op dummy_opline;
1385
1386            dummy_opline.result.op_type = IS_UNUSED;
1387            dummy_opline.op1.op_type = IS_UNUSED;
1388
1389            zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
1390        }
1391    }
1392
1393    if (CG(doc_comment)) {
1394        CG(active_op_array)->doc_comment = CG(doc_comment);
1395        CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
1396        CG(doc_comment) = NULL;
1397        CG(doc_comment_len) = 0;
1398    }
1399
1400    zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
1401    CG(labels) = NULL;
1402}
1403/* }}} */
1404
1405void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC) /* {{{ */
1406{
1407    znode          function_name;
1408    zend_op_array *current_op_array = CG(active_op_array);
1409    int            current_op_number = get_next_op_number(CG(active_op_array));
1410    zend_op       *current_op;
1411
1412    function_name.op_type = IS_CONST;
1413    ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
1414
1415    zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
1416
1417    result->op_type = IS_TMP_VAR;
1418    result->u.var = get_temporary_variable(current_op_array);
1419
1420    current_op = &current_op_array->opcodes[current_op_number];
1421    current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
1422    zval_dtor(&current_op->op2.u.constant);
1423    ZVAL_LONG(&current_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant)));
1424    current_op->result = *result;
1425    CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
1426}
1427/* }}} */
1428
1429void zend_do_handle_exception(TSRMLS_D) /* {{{ */
1430{
1431    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1432
1433    opline->opcode = ZEND_HANDLE_EXCEPTION;
1434    SET_UNUSED(opline->op1);
1435    SET_UNUSED(opline->op2);
1436}
1437/* }}} */
1438
1439void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
1440{
1441    char lcname[16];
1442    int name_len;
1443
1444    zend_do_extended_info(TSRMLS_C);
1445    zend_do_return(NULL, 0 TSRMLS_CC);
1446
1447    pass_two(CG(active_op_array) TSRMLS_CC);
1448    zend_release_labels(TSRMLS_C);
1449
1450    if (CG(active_class_entry)) {
1451        zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
1452    } else {
1453        /* we don't care if the function name is longer, in fact lowercasing only
1454         * the beginning of the name speeds up the check process */
1455        name_len = strlen(CG(active_op_array)->function_name);
1456        zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
1457        lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
1458        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) {
1459            zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
1460        }
1461    }
1462
1463    CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
1464    CG(active_op_array) = function_token->u.op_array;
1465
1466
1467    /* Pop the switch and foreach seperators */
1468    zend_stack_del_top(&CG(switch_cond_stack));
1469    zend_stack_del_top(&CG(foreach_copy_stack));
1470}
1471/* }}} */
1472
1473void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, const znode *initialization, znode *class_type, const znode *varname, zend_uchar pass_by_reference TSRMLS_DC) /* {{{ */
1474{
1475    zend_op *opline;
1476    zend_arg_info *cur_arg_info;
1477
1478    if (class_type->op_type == IS_CONST &&
1479        Z_TYPE(class_type->u.constant) == IS_STRING &&
1480        Z_STRLEN(class_type->u.constant) == 0) {
1481        /* Usage of namespace as class name not in namespace */
1482        zval_dtor(&class_type->u.constant);
1483        zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
1484        return;
1485    }
1486
1487    if (var->op_type == IS_CV &&
1488        var->u.var == CG(active_op_array)->this_var &&
1489        (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
1490        zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
1491    } else if (var->op_type == IS_VAR &&
1492        CG(active_op_array)->scope &&
1493        ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
1494        (Z_TYPE(varname->u.constant) == IS_STRING) &&
1495        (Z_STRLEN(varname->u.constant) == sizeof("this")-1) &&
1496        (memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")) == 0)) {
1497        zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
1498    }
1499
1500    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1501    CG(active_op_array)->num_args++;
1502    opline->opcode = op;
1503    opline->result = *var;
1504    opline->op1 = *offset;
1505    if (op == ZEND_RECV_INIT) {
1506        opline->op2 = *initialization;
1507    } else {
1508        CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
1509        SET_UNUSED(opline->op2);
1510    }
1511    CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
1512    cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
1513    cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len);
1514    cur_arg_info->name_len = varname->u.constant.value.str.len;
1515    cur_arg_info->array_type_hint = 0;
1516    cur_arg_info->allow_null = 1;
1517    cur_arg_info->pass_by_reference = pass_by_reference;
1518    cur_arg_info->class_name = NULL;
1519    cur_arg_info->class_name_len = 0;
1520
1521    if (class_type->op_type != IS_UNUSED) {
1522        cur_arg_info->allow_null = 0;
1523        if (class_type->u.constant.type == IS_STRING) {
1524            if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
1525                zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
1526            }
1527            cur_arg_info->class_name = class_type->u.constant.value.str.val;
1528            cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
1529            if (op == ZEND_RECV_INIT) {
1530                if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1531                    cur_arg_info->allow_null = 1;
1532                } else {
1533                    zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
1534                }
1535            }
1536        } else {
1537            cur_arg_info->array_type_hint = 1;
1538            cur_arg_info->class_name = NULL;
1539            cur_arg_info->class_name_len = 0;
1540            if (op == ZEND_RECV_INIT) {
1541                if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
1542                    cur_arg_info->allow_null = 1;
1543                } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
1544                    zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
1545                }
1546            }
1547        }
1548    }
1549    opline->result.u.EA.type |= EXT_TYPE_UNUSED;
1550}
1551/* }}} */
1552
1553int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
1554{
1555    zend_function *function;
1556    char *lcname;
1557    char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
1558
1559    zend_resolve_non_class_name(function_name, check_namespace TSRMLS_CC);
1560
1561    if (check_namespace && CG(current_namespace) && !is_compound) {
1562            /* We assume we call function from the current namespace
1563            if it is not prefixed. */
1564
1565            /* In run-time PHP will check for function with full name and
1566            internal function with short name */
1567            zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
1568            return 1;
1569    }
1570
1571    lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
1572    if ((zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) ||
1573        ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
1574        (function->type == ZEND_INTERNAL_FUNCTION))) {
1575            zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
1576            efree(lcname);
1577            return 1; /* Dynamic */
1578    }
1579    efree(function_name->u.constant.value.str.val);
1580    function_name->u.constant.value.str.val = lcname;
1581
1582    zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *));
1583    zend_do_extended_fcall_begin(TSRMLS_C);
1584    return 0;
1585}
1586/* }}} */
1587
1588void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
1589{
1590    zend_op *last_op;
1591    int last_op_number;
1592    unsigned char *ptr = NULL;
1593
1594    zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
1595    zend_do_begin_variable_parse(TSRMLS_C);
1596
1597    last_op_number = get_next_op_number(CG(active_op_array))-1;
1598    last_op = &CG(active_op_array)->opcodes[last_op_number];
1599
1600    if ((last_op->op2.op_type == IS_CONST) && (last_op->op2.u.constant.type == IS_STRING) && (last_op->op2.u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1)
1601        && !zend_binary_strcasecmp(last_op->op2.u.constant.value.str.val, last_op->op2.u.constant.value.str.len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
1602        zend_error(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
1603    }
1604
1605    if (last_op->opcode == ZEND_FETCH_OBJ_R) {
1606        last_op->opcode = ZEND_INIT_METHOD_CALL;
1607        SET_UNUSED(last_op->result);
1608        Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
1609    } else {
1610        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1611        opline->opcode = ZEND_INIT_FCALL_BY_NAME;
1612        opline->op2 = *left_bracket;
1613        if (opline->op2.op_type == IS_CONST) {
1614            opline->op1.op_type = IS_CONST;
1615            Z_TYPE(opline->op1.u.constant) = IS_STRING;
1616            Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
1617            Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
1618            opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
1619        } else {
1620            opline->extended_value = 0;
1621            SET_UNUSED(opline->op1);
1622        }
1623    }
1624
1625    zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
1626    zend_do_extended_fcall_begin(TSRMLS_C);
1627}
1628/* }}} */
1629
1630void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
1631{
1632    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1633
1634    opline->opcode = ZEND_CLONE;
1635    opline->op1 = *expr;
1636    SET_UNUSED(opline->op2);
1637    opline->result.op_type = IS_VAR;
1638    opline->result.u.var = get_temporary_variable(CG(active_op_array));
1639    *result = opline->result;
1640}
1641/* }}} */
1642
1643void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
1644{
1645    unsigned char *ptr = NULL;
1646    zend_op *opline, *opline2;
1647
1648    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1649    if (ns_call) {
1650        char *slash;
1651        int prefix_len, name_len;
1652        /* In run-time PHP will check for function with full name and
1653           internal function with short name */
1654        opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
1655        opline->op2 = *function_name;
1656        opline->extended_value = 0;
1657        opline->op1.op_type = IS_CONST;
1658        Z_TYPE(opline->op1.u.constant) = IS_STRING;
1659        Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
1660        Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
1661        opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
1662        slash = zend_memrchr(Z_STRVAL(opline->op1.u.constant), '\\', Z_STRLEN(opline->op1.u.constant));
1663        prefix_len = slash-Z_STRVAL(opline->op1.u.constant)+1;
1664        name_len = Z_STRLEN(opline->op1.u.constant)-prefix_len;
1665        opline2 = get_next_op(CG(active_op_array) TSRMLS_CC);
1666        opline2->opcode = ZEND_OP_DATA;
1667        opline2->op1.op_type = IS_CONST;
1668        Z_TYPE(opline2->op1.u.constant) = IS_LONG;
1669        if(!slash) {
1670            zend_error(E_CORE_ERROR, "Namespaced name %s should contain slash", Z_STRVAL(opline->op1.u.constant));
1671        }
1672        /* this is the length of namespace prefix */
1673        Z_LVAL(opline2->op1.u.constant) = prefix_len;
1674        /* this is the hash of the non-prefixed part, lowercased */
1675        opline2->extended_value = zend_hash_func(slash+1, name_len+1);
1676        SET_UNUSED(opline2->op2);
1677    } else {
1678        opline->opcode = ZEND_INIT_FCALL_BY_NAME;
1679        opline->op2 = *function_name;
1680        if (opline->op2.op_type == IS_CONST) {
1681            opline->op1.op_type = IS_CONST;
1682            Z_TYPE(opline->op1.u.constant) = IS_STRING;
1683            Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
1684            Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
1685            opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
1686        } else {
1687            opline->extended_value = 0;
1688            SET_UNUSED(opline->op1);
1689        }
1690    }
1691
1692    zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
1693    zend_do_extended_fcall_begin(TSRMLS_C);
1694}
1695/* }}} */
1696
1697void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
1698{
1699    znode tmp;
1700    int len;
1701    zval **ns;
1702    char *lcname, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
1703
1704    if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
1705        /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
1706        memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
1707        --Z_STRLEN(element_name->u.constant);
1708        return;
1709    }
1710
1711    if(!check_namespace) {
1712        return;
1713    }
1714
1715    if (compound && CG(current_import)) {
1716        len = compound - Z_STRVAL(element_name->u.constant);
1717        lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
1718        /* Check if first part of compound name is an import name */
1719        if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
1720            /* Substitute import name */
1721            tmp.op_type = IS_CONST;
1722            tmp.u.constant = **ns;
1723            zval_copy_ctor(&tmp.u.constant);
1724            len += 1;
1725            Z_STRLEN(element_name->u.constant) -= len;
1726            memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
1727            zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
1728            *element_name = tmp;
1729            efree(lcname);
1730            return;
1731        }
1732        efree(lcname);
1733    }
1734
1735    if (CG(current_namespace)) {
1736        tmp = *element_name;
1737        Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
1738        Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
1739        memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
1740        memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace))]), "\\", sizeof("\\")-1);
1741        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);
1742        STR_FREE(Z_STRVAL(element_name->u.constant));
1743        *element_name = tmp;
1744    }
1745}
1746/* }}} */
1747
1748void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC) /* {{{ */
1749{
1750    char *compound;
1751    char *lcname;
1752    zval **ns;
1753    znode tmp;
1754    int len;
1755
1756    compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
1757    if (compound) {
1758        /* This is a compound class name that contains namespace prefix */
1759        if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
1760            /* The STRING name has "\" prefix */
1761            Z_STRLEN(class_name->u.constant) -= 1;
1762            memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
1763            Z_STRVAL(class_name->u.constant) = erealloc(
1764                Z_STRVAL(class_name->u.constant),
1765                Z_STRLEN(class_name->u.constant) + 1);
1766
1767            if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
1768                zend_error(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
1769            }
1770        } else {
1771            if (CG(current_import)) {
1772                len = compound - Z_STRVAL(class_name->u.constant);
1773                lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
1774                /* Check if first part of compound name is an import name */
1775                if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
1776                    /* Substitute import name */
1777                    tmp.op_type = IS_CONST;
1778                    tmp.u.constant = **ns;
1779                    zval_copy_ctor(&tmp.u.constant);
1780                    len += 1;
1781                    Z_STRLEN(class_name->u.constant) -= len;
1782                    memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
1783                    zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
1784                    *class_name = tmp;
1785                    efree(lcname);
1786                    return;
1787                }
1788                efree(lcname);
1789            }
1790            /* Here name is not prefixed with \ and not imported */
1791            if (CG(current_namespace)) {
1792                tmp.op_type = IS_CONST;
1793                tmp.u.constant = *CG(current_namespace);
1794                zval_copy_ctor(&tmp.u.constant);
1795                zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
1796                *class_name = tmp;
1797            }
1798        }
1799    } else if (CG(current_import) || CG(current_namespace)) {
1800        /* this is a plain name (without \) */
1801        lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
1802
1803        if (CG(current_import) &&
1804            zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
1805            /* The given name is an import name. Substitute it. */
1806            zval_dtor(&class_name->u.constant);
1807            class_name->u.constant = **ns;
1808            zval_copy_ctor(&class_name->u.constant);
1809        } else if (CG(current_namespace)) {
1810            /* plain name, no import - prepend current namespace to it */
1811            tmp.op_type = IS_CONST;
1812            tmp.u.constant = *CG(current_namespace);
1813            zval_copy_ctor(&tmp.u.constant);
1814            zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
1815            *class_name = tmp;
1816        }
1817        efree(lcname);
1818    }
1819}
1820/* }}} */
1821
1822void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
1823{
1824    long fetch_class_op_number;
1825    zend_op *opline;
1826
1827    if (class_name->op_type == IS_CONST &&
1828        Z_TYPE(class_name->u.constant) == IS_STRING &&
1829        Z_STRLEN(class_name->u.constant) == 0) {
1830        /* Usage of namespace as class name not in namespace */
1831        zval_dtor(&class_name->u.constant);
1832        zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
1833        return;
1834    }
1835
1836    fetch_class_op_number = get_next_op_number(CG(active_op_array));
1837    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1838
1839    opline->opcode = ZEND_FETCH_CLASS;
1840    SET_UNUSED(opline->op1);
1841    opline->extended_value = ZEND_FETCH_CLASS_GLOBAL;
1842    CG(catch_begin) = fetch_class_op_number;
1843    if (class_name->op_type == IS_CONST) {
1844        int fetch_type;
1845
1846        fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
1847        switch (fetch_type) {
1848            case ZEND_FETCH_CLASS_SELF:
1849            case ZEND_FETCH_CLASS_PARENT:
1850            case ZEND_FETCH_CLASS_STATIC:
1851                SET_UNUSED(opline->op2);
1852                opline->extended_value = fetch_type;
1853                zval_dtor(&class_name->u.constant);
1854                break;
1855            default:
1856                zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
1857                opline->op2 = *class_name;
1858                break;
1859        }
1860    } else {
1861        opline->op2 = *class_name;
1862    }
1863    opline->result.u.var = get_temporary_variable(CG(active_op_array));
1864    opline->result.u.EA.type = opline->extended_value;
1865    opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
1866    *result = opline->result;
1867}
1868/* }}} */
1869
1870void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
1871{
1872    zend_op_array *oparray = CG(active_op_array);
1873    zend_label dest;
1874
1875    if (!CG(labels)) {
1876        ALLOC_HASHTABLE(CG(labels));
1877        zend_hash_init(CG(labels), 4, NULL, NULL, 0);
1878    }
1879
1880    dest.brk_cont = oparray->current_brk_cont;
1881    dest.opline_num = get_next_op_number(oparray);
1882
1883    if (zend_hash_add(CG(labels), Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
1884        zend_error(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
1885    }
1886
1887    /* Done with label now */
1888    zval_dtor(&label->u.constant);
1889}
1890/* }}} */
1891
1892void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
1893{
1894    zend_label *dest;
1895    long current, distance;
1896
1897    if (CG(labels) == NULL ||
1898        zend_hash_find(CG(labels), Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void**)&dest) == FAILURE) {
1899
1900        if (pass2) {
1901            CG(in_compilation) = 1;
1902            CG(active_op_array) = op_array;
1903            CG(zend_lineno) = opline->lineno;
1904            zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL(opline->op2.u.constant));
1905        } else {
1906            /* Label is not defined. Delay to pass 2. */
1907            INC_BPC(op_array);
1908            return;
1909        }
1910    }
1911
1912    opline->op1.u.opline_num = dest->opline_num;
1913    zval_dtor(&opline->op2.u.constant);
1914
1915    /* Check that we are not moving into loop or switch */
1916    current = opline->extended_value;
1917    for (distance = 0; current != dest->brk_cont; distance++) {
1918        if (current == -1) {
1919            if (pass2) {
1920                CG(in_compilation) = 1;
1921                CG(active_op_array) = op_array;
1922                CG(zend_lineno) = opline->lineno;
1923            }
1924            zend_error(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
1925        }
1926        current = op_array->brk_cont_array[current].parent;
1927    }
1928
1929    if (distance == 0) {
1930        /* Nothing to break out of, optimize to ZEND_JMP */
1931        opline->opcode = ZEND_JMP;
1932        opline->extended_value = 0;
1933        SET_UNUSED(opline->op2);
1934    } else {
1935        /* Set real break distance */
1936        ZVAL_LONG(&opline->op2.u.constant, distance);
1937    }
1938
1939    if (pass2) {
1940        DEC_BPC(op_array);
1941    }
1942}
1943/* }}} */
1944
1945void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
1946{
1947    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1948
1949    opline->opcode = ZEND_GOTO;
1950    opline->extended_value = CG(active_op_array)->current_brk_cont;
1951    SET_UNUSED(opline->op1);
1952    opline->op2 = *label;
1953    zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
1954}
1955/* }}} */
1956
1957void zend_release_labels(TSRMLS_D) /* {{{ */
1958{
1959    if (CG(labels)) {
1960        zend_hash_destroy(CG(labels));
1961        FREE_HASHTABLE(CG(labels));
1962    }
1963    if (!zend_stack_is_empty(&CG(labels_stack))) {
1964        HashTable **pht;
1965
1966        zend_stack_top(&CG(labels_stack), (void**)&pht);
1967        CG(labels) = *pht;
1968        zend_stack_del_top(&CG(labels_stack));
1969    } else {
1970        CG(labels) = NULL;
1971    }
1972}
1973/* }}} */
1974
1975void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
1976{
1977    zend_uint length;
1978
1979    if (!result) {
1980        result = prefix;
1981    } else {
1982        *result = *prefix;
1983    }
1984
1985    if (is_class_member) {
1986        length = sizeof("::")-1 + result->u.constant.value.str.len + name->u.constant.value.str.len;
1987        result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
1988        memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
1989        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);
1990        STR_FREE(name->u.constant.value.str.val);
1991        result->u.constant.value.str.len = length;
1992    } else {
1993        length = sizeof("\\")-1 + result->u.constant.value.str.len + name->u.constant.value.str.len;
1994        result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
1995        memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "\\", sizeof("\\")-1);
1996        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);
1997        STR_FREE(name->u.constant.value.str.val);
1998        result->u.constant.value.str.len = length;
1999    }
2000}
2001/* }}} */
2002
2003int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
2004{
2005    znode class_node;
2006    unsigned char *ptr = NULL;
2007    zend_op *opline;
2008    ulong fetch_type = 0;
2009
2010    if (method_name->op_type == IS_CONST) {
2011        char *lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
2012        if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
2013            memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
2014            zval_dtor(&method_name->u.constant);
2015            SET_UNUSED(*method_name);
2016        }
2017        efree(lcname);
2018    }
2019
2020    if (class_name->op_type == IS_CONST &&
2021            ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2022        fetch_type = ZEND_FETCH_CLASS_GLOBAL;
2023        zend_resolve_class_name(class_name, &fetch_type, 1 TSRMLS_CC);
2024        class_node = *class_name;
2025    } else {
2026        zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
2027    }
2028    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2029    opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2030    opline->op1 = class_node;
2031    opline->op2 = *method_name;
2032
2033    zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
2034    zend_do_extended_fcall_begin(TSRMLS_C);
2035    return 1; /* Dynamic */
2036}
2037/* }}} */
2038
2039void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
2040{
2041    zend_op *opline;
2042
2043    if (is_method && function_name && function_name->op_type == IS_UNUSED) {
2044        /* clone */
2045        if (Z_LVAL(argument_list->u.constant) != 0) {
2046            zend_error(E_WARNING, "Clone method does not require arguments");
2047        }
2048        opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
2049    } else {
2050        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2051        if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
2052            opline->opcode = ZEND_DO_FCALL;
2053            opline->op1 = *function_name;
2054            ZVAL_LONG(&opline->op2.u.constant, zend_hash_func(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant) + 1));
2055        } else {
2056            opline->opcode = ZEND_DO_FCALL_BY_NAME;
2057            SET_UNUSED(opline->op1);
2058        }
2059    }
2060
2061    opline->result.u.var = get_temporary_variable(CG(active_op_array));
2062    opline->result.op_type = IS_VAR;
2063    *result = opline->result;
2064    SET_UNUSED(opline->op2);
2065
2066    zend_stack_del_top(&CG(function_call_stack));
2067    opline->extended_value = Z_LVAL(argument_list->u.constant);
2068}
2069/* }}} */
2070
2071void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{{ */
2072{
2073    zend_op *opline;
2074    int original_op=op;
2075    zend_function **function_ptr_ptr, *function_ptr;
2076    int send_by_reference;
2077    int send_function = 0;
2078
2079    zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
2080    function_ptr = *function_ptr_ptr;
2081
2082    if (original_op == ZEND_SEND_REF && !CG(allow_call_time_pass_reference)) {
2083        if (function_ptr &&
2084                function_ptr->common.function_name &&
2085                function_ptr->common.type == ZEND_USER_FUNCTION &&
2086                !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
2087            zend_error(E_DEPRECATED,
2088                        "Call-time pass-by-reference has been deprecated; "
2089                        "If you would like to pass it by reference, modify the declaration of %s().  "
2090                        "If you would like to enable call-time pass-by-reference, you can set "
2091                        "allow_call_time_pass_reference to true in your INI file", function_ptr->common.function_name);
2092        } else {
2093            zend_error(E_DEPRECATED, "Call-time pass-by-reference has been deprecated");
2094        }
2095    }
2096
2097    if (function_ptr) {
2098        if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
2099            if (param->op_type & (IS_VAR|IS_CV)) {
2100                send_by_reference = 1;
2101                if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2102                    /* Method call */
2103                    op = ZEND_SEND_VAR_NO_REF;
2104                    send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
2105                }
2106            } else {
2107                op = ZEND_SEND_VAL;
2108                send_by_reference = 0;
2109            }
2110        } else {
2111            send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
2112        }
2113    } else {
2114        send_by_reference = 0;
2115    }
2116
2117    if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2118        /* Method call */
2119        op = ZEND_SEND_VAR_NO_REF;
2120        send_function = ZEND_ARG_SEND_FUNCTION;
2121    } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
2122        op = ZEND_SEND_VAR_NO_REF;
2123    }
2124
2125    if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
2126        /* change to passing by reference */
2127        switch (param->op_type) {
2128            case IS_VAR:
2129            case IS_CV:
2130                op = ZEND_SEND_REF;
2131                break;
2132            default:
2133                zend_error(E_COMPILE_ERROR, "Only variables can be passed by reference");
2134                break;
2135        }
2136    }
2137
2138    if (original_op == ZEND_SEND_VAR) {
2139        switch (op) {
2140            case ZEND_SEND_VAR_NO_REF:
2141                zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2142                break;
2143            case ZEND_SEND_VAR:
2144                if (function_ptr) {
2145                    zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2146                } else {
2147                    zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
2148                }
2149                break;
2150            case ZEND_SEND_REF:
2151                zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
2152                break;
2153        }
2154    }
2155
2156    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2157
2158    if (op == ZEND_SEND_VAR_NO_REF) {
2159        if (function_ptr) {
2160            opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
2161        } else {
2162            opline->extended_value = send_function;
2163        }
2164    } else {
2165        if (function_ptr) {
2166            opline->extended_value = ZEND_DO_FCALL;
2167        } else {
2168            opline->extended_value = ZEND_DO_FCALL_BY_NAME;
2169        }
2170    }
2171    opline->opcode = op;
2172    opline->op1 = *param;
2173    opline->op2.u.opline_num = offset;
2174    SET_UNUSED(opline->op2);
2175}
2176/* }}} */
2177
2178static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
2179{
2180    zend_op *opline;
2181
2182    if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
2183        return (switch_entry->cond.op_type == IS_UNUSED);
2184    }
2185
2186    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2187
2188    opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2189    opline->op1 = switch_entry->cond;
2190    SET_UNUSED(opline->op2);
2191    opline->extended_value = 0;
2192    return 0;
2193}
2194/* }}} */
2195
2196static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
2197{
2198    zend_op *opline;
2199
2200    /* If we reach the seperator then stop applying the stack */
2201    if (foreach_copy->result.op_type == IS_UNUSED && foreach_copy->op1.op_type == IS_UNUSED) {
2202        return 1;
2203    }
2204
2205    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2206
2207    opline->opcode = (foreach_copy->result.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2208    opline->op1 = foreach_copy->result;
2209    SET_UNUSED(opline->op2);
2210    opline->extended_value = 1;
2211
2212    if (foreach_copy->op1.op_type != IS_UNUSED) {
2213        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2214
2215        opline->opcode = (foreach_copy->op1.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2216        opline->op1 = foreach_copy->op1;
2217        SET_UNUSED(opline->op2);
2218        opline->extended_value = 0;
2219    }
2220
2221    return 0;
2222}
2223/* }}} */
2224
2225void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
2226{
2227    zend_op *opline;
2228    int start_op_number, end_op_number;
2229
2230    if (do_end_vparse) {
2231        if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
2232            zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
2233        } else {
2234            zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
2235        }
2236    }
2237
2238    start_op_number = get_next_op_number(CG(active_op_array));
2239
2240#ifdef ZTS
2241    zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
2242    zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
2243#else
2244    zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
2245    zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
2246#endif
2247
2248    end_op_number = get_next_op_number(CG(active_op_array));
2249    while (start_op_number < end_op_number) {
2250        CG(active_op_array)->opcodes[start_op_number].op1.u.EA.type = EXT_TYPE_FREE_ON_RETURN;
2251        start_op_number++;
2252    }
2253
2254    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2255
2256    opline->opcode = ZEND_RETURN;
2257
2258    if (expr) {
2259        opline->op1 = *expr;
2260
2261        if (do_end_vparse && zend_is_function_or_method_call(expr)) {
2262            opline->extended_value = ZEND_RETURNS_FUNCTION;
2263        }
2264    } else {
2265        opline->op1.op_type = IS_CONST;
2266        INIT_ZVAL(opline->op1.u.constant);
2267    }
2268
2269    SET_UNUSED(opline->op2);
2270}
2271/* }}} */
2272
2273static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
2274{
2275    int try_catch_offset = CG(active_op_array)->last_try_catch++;
2276
2277    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);
2278    CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
2279    return try_catch_offset;
2280}
2281/* }}} */
2282
2283static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
2284{
2285    CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
2286}
2287/* }}} */
2288
2289void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
2290{
2291    open_parentheses->u.opline_num = get_next_op_number(CG(active_op_array));
2292}
2293/* }}} */
2294
2295void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{ */
2296{
2297    int jmp_op_number = get_next_op_number(CG(active_op_array));
2298    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2299    zend_llist jmp_list;
2300    zend_llist *jmp_list_ptr;
2301
2302    opline->opcode = ZEND_JMP;
2303    SET_UNUSED(opline->op1);
2304    SET_UNUSED(opline->op2);
2305    /* save for backpatching */
2306
2307    zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
2308    zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
2309    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2310    zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2311
2312    zend_add_catch_element(try_token->u.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2313}
2314/* }}} */
2315
2316void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
2317{
2318    CG(active_op_array)->last--;
2319    zend_do_if_end(TSRMLS_C);
2320    if (last_additional_catch->u.opline_num == -1) {
2321        CG(active_op_array)->opcodes[first_catch->u.opline_num].op1.u.EA.type = 1;
2322        CG(active_op_array)->opcodes[first_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2323    } else {
2324        CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].op1.u.EA.type = 1;
2325        CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2326    }
2327    DEC_BPC(CG(active_op_array));
2328}
2329/* }}} */
2330
2331void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
2332{
2333    try_token->u.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2334    INC_BPC(CG(active_op_array));
2335}
2336/* }}} */
2337
2338void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
2339{
2340    long catch_op_number;
2341    zend_op *opline;
2342    znode catch_class;
2343
2344    zend_do_fetch_class(&catch_class, class_name TSRMLS_CC);
2345
2346    catch_op_number = get_next_op_number(CG(active_op_array));
2347    if (catch_op_number > 0) {
2348        opline = &CG(active_op_array)->opcodes[catch_op_number-1];
2349        if (opline->opcode == ZEND_FETCH_CLASS) {
2350            opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
2351        }
2352    }
2353
2354    if (first_catch) {
2355        first_catch->u.opline_num = catch_op_number;
2356    }
2357
2358    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2359    opline->opcode = ZEND_CATCH;
2360    opline->op1 = catch_class;
2361/*  SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */
2362    opline->op2.op_type = IS_CV;
2363    opline->op2.u.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len);
2364    opline->op2.u.EA.type = 0;
2365    opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */
2366
2367    try_token->u.opline_num = catch_op_number;
2368}
2369/* }}} */
2370
2371void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */
2372{
2373    int jmp_op_number = get_next_op_number(CG(active_op_array));
2374    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2375    zend_llist *jmp_list_ptr;
2376
2377    opline->opcode = ZEND_JMP;
2378    SET_UNUSED(opline->op1);
2379    SET_UNUSED(opline->op2);
2380    /* save for backpatching */
2381
2382    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2383    zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2384
2385    CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2386}
2387/* }}} */
2388
2389void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
2390{
2391    zend_op *opline;
2392
2393    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2394    opline->opcode = ZEND_THROW;
2395    opline->op1 = *expr;
2396    SET_UNUSED(opline->op2);
2397}
2398/* }}} */
2399
2400ZEND_API void function_add_ref(zend_function *function) /* {{{ */
2401{
2402    if (function->type == ZEND_USER_FUNCTION) {
2403        zend_op_array *op_array = &function->op_array;
2404
2405        (*op_array->refcount)++;
2406        if (op_array->static_variables) {
2407            HashTable *static_variables = op_array->static_variables;
2408            zval *tmp_zval;
2409
2410            ALLOC_HASHTABLE(op_array->static_variables);
2411            zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
2412            zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
2413        }
2414    }
2415}
2416/* }}} */
2417
2418static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
2419{
2420    zend_function *function;
2421
2422    if (!ce->parent) {
2423        return;
2424    }
2425
2426    /* You cannot change create_object */
2427    ce->create_object = ce->parent->create_object;
2428
2429    /* Inherit special functions if needed */
2430    if (!ce->get_iterator) {
2431        ce->get_iterator = ce->parent->get_iterator;
2432    }
2433    if (!ce->iterator_funcs.funcs) {
2434        ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
2435    }
2436    if (!ce->__get) {
2437        ce->__get   = ce->parent->__get;
2438    }
2439    if (!ce->__set) {
2440        ce->__set = ce->parent->__set;
2441    }
2442    if (!ce->__unset) {
2443        ce->__unset = ce->parent->__unset;
2444    }
2445    if (!ce->__isset) {
2446        ce->__isset = ce->parent->__isset;
2447    }
2448    if (!ce->__call) {
2449        ce->__call = ce->parent->__call;
2450    }
2451    if (!ce->__callstatic) {
2452        ce->__callstatic = ce->parent->__callstatic;
2453    }
2454    if (!ce->__tostring) {
2455        ce->__tostring = ce->parent->__tostring;
2456    }
2457    if (!ce->clone) {
2458        ce->clone = ce->parent->clone;
2459    }
2460    if(!ce->serialize) {
2461        ce->serialize = ce->parent->serialize;
2462    }
2463    if(!ce->unserialize) {
2464        ce->unserialize = ce->parent->unserialize;
2465    }
2466    if (!ce->destructor) {
2467        ce->destructor   = ce->parent->destructor;
2468    }
2469    if (ce->constructor) {
2470        if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
2471            zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
2472                ce->parent->name, ce->parent->constructor->common.function_name,
2473                ce->name, ce->constructor->common.function_name
2474                );
2475        }
2476        return;
2477    }
2478
2479    if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
2480        /* inherit parent's constructor */
2481        zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL);
2482        function_add_ref(function);
2483    } else {
2484        /* Don't inherit the old style constructor if we already have the new style constructor */
2485        char *lc_class_name;
2486        char *lc_parent_class_name;
2487
2488        lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
2489        if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
2490            lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
2491            if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) &&
2492                    zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
2493                if (function->common.fn_flags & ZEND_ACC_CTOR) {
2494                    /* inherit parent's constructor */
2495                    zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), NULL);
2496                    function_add_ref(function);
2497                }
2498            }
2499            efree(lc_parent_class_name);
2500        }
2501        efree(lc_class_name);
2502    }
2503    ce->constructor = ce->parent->constructor;
2504}
2505/* }}} */
2506
2507char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
2508{
2509    if (fn_flags & ZEND_ACC_PRIVATE) {
2510        return "private";
2511    }
2512    if (fn_flags & ZEND_ACC_PROTECTED) {
2513        return "protected";
2514    }
2515    if (fn_flags & ZEND_ACC_PUBLIC) {
2516        return "public";
2517    }
2518    return "";
2519}
2520/* }}} */
2521
2522static void do_inherit_method(zend_function *function) /* {{{ */
2523{
2524    /* The class entry of the derived function intentionally remains the same
2525     * as that of the parent class.  That allows us to know in which context
2526     * we're running, and handle private method calls properly.
2527     */
2528    function_add_ref(function);
2529}
2530/* }}} */
2531
2532static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
2533{
2534    zend_uint i;
2535
2536    /* If it's a user function then arg_info == NULL means we don't have any parameters but
2537     * we still need to do the arg number checks.  We are only willing to ignore this for internal
2538     * functions because extensions don't always define arg_info.
2539     */
2540    if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
2541        return 1;
2542    }
2543
2544    /* Checks for constructors only if they are declared in an interface */
2545    if ((fe->common.fn_flags & ZEND_ACC_CTOR) && (proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
2546        return 1;
2547    }
2548
2549    /* check number of arguments */
2550    if (proto->common.required_num_args < fe->common.required_num_args
2551        || proto->common.num_args > fe->common.num_args) {
2552        return 0;
2553    }
2554
2555    if (fe->common.type != ZEND_USER_FUNCTION
2556        && proto->common.pass_rest_by_reference
2557        && !fe->common.pass_rest_by_reference) {
2558        return 0;
2559    }
2560
2561    /* by-ref constraints on return values are covariant */
2562    if (proto->common.return_reference && !fe->common.return_reference) {
2563        return 0;
2564    }
2565
2566    for (i=0; i < proto->common.num_args; i++) {
2567        if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)) {
2568            /* Only one has a type hint and the other one doesn't */
2569            return 0;
2570        }
2571        if (fe->common.arg_info[i].class_name
2572            && strcasecmp(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)!=0) {
2573            char *colon;
2574
2575            if (fe->common.type != ZEND_USER_FUNCTION) {
2576                return 0;
2577            } else if (strchr(proto->common.arg_info[i].class_name, '\\') != NULL ||
2578                (colon = zend_memrchr(fe->common.arg_info[i].class_name, '\\', fe->common.arg_info[i].class_name_len)) == NULL ||
2579                strcasecmp(colon+1, proto->common.arg_info[i].class_name) != 0) {
2580                zend_class_entry **fe_ce, **proto_ce;
2581                int found, found2;
2582
2583                found = zend_lookup_class(fe->common.arg_info[i].class_name, fe->common.arg_info[i].class_name_len, &fe_ce TSRMLS_CC);
2584                found2 = zend_lookup_class(proto->common.arg_info[i].class_name, proto->common.arg_info[i].class_name_len, &proto_ce TSRMLS_CC);
2585
2586                /* Check for class alias */
2587                if (found != SUCCESS || found2 != SUCCESS ||
2588                    (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
2589                    (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
2590                    *fe_ce != *proto_ce) {
2591                    return 0;
2592                }
2593            }
2594        }
2595        if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) {
2596            /* Only one has an array type hint and the other one doesn't */
2597            return 0;
2598        }
2599
2600        /* by-ref constraints on arguments are invariant */
2601        if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
2602            return 0;
2603        }
2604    }
2605
2606    if (proto->common.pass_rest_by_reference) {
2607        for (i=proto->common.num_args; i < fe->common.num_args; i++) {
2608            if (!fe->common.arg_info[i].pass_by_reference) {
2609                return 0;
2610            }
2611        }
2612    }
2613    return 1;
2614}
2615/* }}} */
2616
2617static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
2618{
2619    zend_uint child_flags;
2620    zend_uint parent_flags = parent->common.fn_flags;
2621    zend_function *child;
2622    TSRMLS_FETCH();
2623
2624    if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
2625        if (parent_flags & (ZEND_ACC_ABSTRACT)) {
2626            child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
2627        }
2628        return 1; /* method doesn't exist in child, copy from parent */
2629    }
2630
2631    if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
2632        && parent->common.fn_flags & ZEND_ACC_ABSTRACT
2633        && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
2634        && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
2635        zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
2636            parent->common.scope->name,
2637            child->common.function_name,
2638            child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
2639    }
2640
2641    if (parent_flags & ZEND_ACC_FINAL) {
2642        zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
2643    }
2644
2645    child_flags = child->common.fn_flags;
2646    /* You cannot change from static to non static and vice versa.
2647     */
2648    if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
2649        if (child->common.fn_flags & ZEND_ACC_STATIC) {
2650            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));
2651        } else {
2652            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));
2653        }
2654    }
2655
2656    /* Disallow making an inherited method abstract. */
2657    if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
2658        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));
2659    }
2660
2661    if (parent_flags & ZEND_ACC_CHANGED) {
2662        child->common.fn_flags |= ZEND_ACC_CHANGED;
2663    } else {
2664        /* Prevent derived classes from restricting access that was available in parent classes
2665         */
2666        if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
2667            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");
2668        } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
2669            && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
2670            child->common.fn_flags |= ZEND_ACC_CHANGED;
2671        }
2672    }
2673
2674    if (parent_flags & ZEND_ACC_PRIVATE) {
2675        child->common.prototype = NULL;
2676    } else if (parent_flags & ZEND_ACC_ABSTRACT) {
2677        child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
2678        child->common.prototype = parent;
2679    } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
2680        /* ctors only have a prototype if it comes from an interface */
2681        child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
2682    }
2683
2684    if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
2685        if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
2686            zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
2687        }
2688    } 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 */
2689        if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
2690            zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
2691        }
2692    }
2693
2694    return 0;
2695}
2696/* }}} */
2697
2698static 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) /* {{{ */
2699{
2700    zend_property_info *child_info;
2701    zend_class_entry *parent_ce = ce->parent;
2702
2703    if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
2704        if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
2705            child_info->flags |= ZEND_ACC_CHANGED;
2706        } else {
2707            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);
2708            if(ce->type & ZEND_INTERNAL_CLASS) {
2709                zend_duplicate_property_info_internal(child_info);
2710            } else {
2711                zend_duplicate_property_info(child_info);
2712            }
2713            child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
2714            child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
2715        }
2716        return 0; /* don't copy access information to child */
2717    }
2718
2719    if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
2720        if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
2721            zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
2722                (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
2723                (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
2724
2725        }
2726
2727        if(parent_info->flags & ZEND_ACC_CHANGED) {
2728            child_info->flags |= ZEND_ACC_CHANGED;
2729        }
2730
2731        if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
2732            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");
2733        } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
2734            if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
2735                /* Explicitly copy the default value from the parent (if it has one) */
2736                zval **pvalue;
2737
2738                if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
2739                    Z_ADDREF_PP(pvalue);
2740                    zend_hash_quick_del(&ce->default_properties, child_info->name, child_info->name_length+1, parent_info->h);
2741                    zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
2742                }
2743            }
2744            return 1; /* Inherit from the parent */
2745        } else if ((child_info->flags & ZEND_ACC_PUBLIC) && (parent_info->flags & ZEND_ACC_PROTECTED)) {
2746            char *prot_name;
2747            int prot_name_length;
2748
2749            zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
2750            if (child_info->flags & ZEND_ACC_STATIC) {
2751                zval **prop;
2752                HashTable *ht;
2753
2754                if (parent_ce->type != ce->type) {
2755                    /* User class extends internal class */
2756                    TSRMLS_FETCH();
2757
2758                    ht = CE_STATIC_MEMBERS(parent_ce);
2759                } else {
2760                    ht = &parent_ce->default_static_members;
2761                }
2762                if (zend_hash_find(ht, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
2763                    zend_hash_del(&ce->default_static_members, prot_name, prot_name_length+1);
2764                }
2765            } else {
2766                zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
2767            }
2768            pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
2769        }
2770        return 0;   /* Don't copy from parent */
2771    } else {
2772        return 1;   /* Copy from parent */
2773    }
2774}
2775/* }}} */
2776
2777static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
2778{
2779    if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
2780        zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
2781    }
2782    if (ce == iface) {
2783        zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
2784    }
2785}
2786/* }}} */
2787
2788ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
2789{
2790    /* expects interface to be contained in ce's interface list already */
2791    zend_uint i, ce_num, if_num = iface->num_interfaces;
2792    zend_class_entry *entry;
2793
2794    if (if_num==0) {
2795        return;
2796    }
2797    ce_num = ce->num_interfaces;
2798
2799    if (ce->type == ZEND_INTERNAL_CLASS) {
2800        ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
2801    } else {
2802        ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
2803    }
2804
2805    /* Inherit the interfaces, only if they're not already inherited by the class */
2806    while (if_num--) {
2807        entry = iface->interfaces[if_num];
2808        for (i = 0; i < ce_num; i++) {
2809            if (ce->interfaces[i] == entry) {
2810                break;
2811            }
2812        }
2813        if (i == ce_num) {
2814            ce->interfaces[ce->num_interfaces++] = entry;
2815        }
2816    }
2817
2818    /* and now call the implementing handlers */
2819    while (ce_num < ce->num_interfaces) {
2820        do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
2821    }
2822}
2823/* }}} */
2824
2825static int inherit_static_prop(zval **p TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
2826{
2827    HashTable *target = va_arg(args, HashTable*);
2828
2829    if (!zend_hash_quick_exists(target, key->arKey, key->nKeyLength, key->h)) {
2830        SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
2831        if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) {
2832            Z_ADDREF_PP(p);
2833        }
2834    }
2835    return ZEND_HASH_APPLY_KEEP;
2836}
2837/* }}} */
2838
2839#define zval_property_ctor(parent_ce, ce) \
2840    ((copy_ctor_func_t) (((parent_ce)->type != (ce)->type) ? zval_shared_property_ctor : zval_add_ref))
2841
2842ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
2843{
2844    if ((ce->ce_flags & ZEND_ACC_INTERFACE)
2845        && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
2846        zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
2847    }
2848    if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
2849        zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
2850    }
2851
2852    ce->parent = parent_ce;
2853    /* Copy serialize/unserialize callbacks */
2854    if (!ce->serialize) {
2855        ce->serialize   = parent_ce->serialize;
2856    }
2857    if (!ce->unserialize) {
2858        ce->unserialize = parent_ce->unserialize;
2859    }
2860
2861    /* Inherit interfaces */
2862    zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
2863
2864    /* Inherit properties */
2865    zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
2866    if (parent_ce->type != ce->type) {
2867        /* User class extends internal class */
2868        zend_update_class_constants(parent_ce  TSRMLS_CC);
2869        zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
2870    } else {
2871        zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
2872    }
2873    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);
2874
2875    zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
2876    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);
2877    do_inherit_parent_constructor(ce);
2878
2879    if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
2880        ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
2881    } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {
2882        /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
2883        zend_verify_abstract_class(ce TSRMLS_CC);
2884    }
2885}
2886/* }}} */
2887
2888static 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) /* {{{ */
2889{
2890    zval **old_constant;
2891
2892    if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
2893        if (*old_constant != *parent_constant) {
2894            zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
2895        }
2896        return 0;
2897    }
2898    return 1;
2899}
2900/* }}} */
2901
2902static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
2903{
2904    zend_class_entry **iface = va_arg(args, zend_class_entry**);
2905
2906    do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
2907
2908    return ZEND_HASH_APPLY_KEEP;
2909}
2910/* }}} */
2911
2912ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
2913{
2914    zend_uint i, ignore = 0;
2915    zend_uint current_iface_num = ce->num_interfaces;
2916    zend_uint parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
2917
2918    for (i = 0; i < ce->num_interfaces; i++) {
2919        if (ce->interfaces[i] == NULL) {
2920            memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
2921            i--;
2922        } else if (ce->interfaces[i] == iface) {
2923            if (i < parent_iface_num) {
2924                ignore = 1;
2925            } else {
2926                zend_error(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
2927            }
2928        }
2929    }
2930    if (ignore) {
2931        /* Check for attempt to redeclare interface constants */
2932        zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
2933    } else {
2934        if (ce->num_interfaces >= current_iface_num) {
2935            if (ce->type == ZEND_INTERNAL_CLASS) {
2936                ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
2937            } else {
2938                ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
2939            }
2940        }
2941        ce->interfaces[ce->num_interfaces++] = iface;
2942
2943        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);
2944        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);
2945
2946        do_implement_interface(ce, iface TSRMLS_CC);
2947        zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
2948    }
2949}
2950/* }}} */
2951
2952ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
2953{
2954    zend_function *function;
2955
2956    zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
2957    if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) {
2958        int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
2959        zend_function *old_function;
2960
2961        if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &old_function)==SUCCESS
2962            && old_function->type == ZEND_USER_FUNCTION
2963            && old_function->op_array.last > 0) {
2964            zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
2965                        function->common.function_name,
2966                        old_function->op_array.filename,
2967                        old_function->op_array.opcodes[0].lineno);
2968        } else {
2969            zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
2970        }
2971        return FAILURE;
2972    } else {
2973        (*function->op_array.refcount)++;
2974        function->op_array.static_variables = NULL; /* NULL out the unbound function */
2975        return SUCCESS;
2976    }
2977}
2978/* }}} */
2979
2980ZEND_API zend_class_entry *do_bind_class(const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
2981{
2982    zend_class_entry *ce, **pce;
2983
2984    if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
2985        zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
2986        return NULL;
2987    } else {
2988        ce = *pce;
2989    }
2990    ce->refcount++;
2991    if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
2992        ce->refcount--;
2993        if (!compile_time) {
2994            /* If we're in compile time, in practice, it's quite possible
2995             * that we'll never reach this class declaration at runtime,
2996             * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
2997             * approach to work.
2998             */
2999            zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
3000        }
3001        return NULL;
3002    } else {
3003        if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES))) {
3004            zend_verify_abstract_class(ce TSRMLS_CC);
3005        }
3006        return ce;
3007    }
3008}
3009/* }}} */
3010
3011ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time TSRMLS_DC) /* {{{ */
3012{
3013    zend_class_entry *ce, **pce;
3014    int found_ce;
3015
3016    found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
3017
3018    if (found_ce == FAILURE) {
3019        if (!compile_time) {
3020            /* If we're in compile time, in practice, it's quite possible
3021             * that we'll never reach this class declaration at runtime,
3022             * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
3023             * approach to work.
3024             */
3025            zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
3026        }
3027        return NULL;
3028    } else {
3029        ce = *pce;
3030    }
3031
3032    if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
3033        zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
3034    }
3035
3036    zend_do_inheritance(ce, parent_ce TSRMLS_CC);
3037
3038    ce->refcount++;
3039
3040    /* Register the derived class */
3041    if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
3042        zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
3043    }
3044    return ce;
3045}
3046/* }}} */
3047
3048void zend_do_early_binding(TSRMLS_D) /* {{{ */
3049{
3050    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
3051    HashTable *table;
3052
3053    while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
3054        opline--;
3055    }
3056
3057    switch (opline->opcode) {
3058        case ZEND_DECLARE_FUNCTION:
3059            if (do_bind_function(opline, CG(function_table), 1) == FAILURE) {
3060                return;
3061            }
3062            table = CG(function_table);
3063            break;
3064        case ZEND_DECLARE_CLASS:
3065            if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
3066                return;
3067            }
3068            table = CG(class_table);
3069            break;
3070        case ZEND_DECLARE_INHERITED_CLASS:
3071            {
3072                zend_op *fetch_class_opline = opline-1;
3073                zval *parent_name = &fetch_class_opline->op2.u.constant;
3074                zend_class_entry **pce;
3075
3076                if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
3077                        ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
3078                        ((*pce)->type == ZEND_INTERNAL_CLASS))) {
3079                    if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
3080                        zend_uint *opline_num = &CG(active_op_array)->early_binding;
3081
3082                        while (*opline_num != -1) {
3083                            opline_num = &CG(active_op_array)->opcodes[*opline_num].result.u.opline_num;
3084                        }
3085                        *opline_num = opline - CG(active_op_array)->opcodes;
3086                        opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
3087                        opline->result.op_type = IS_UNUSED;
3088                        opline->result.u.opline_num = -1;
3089                    }
3090                    return;
3091                }
3092                if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
3093                    return;
3094                }
3095                /* clear unnecessary ZEND_FETCH_CLASS opcode */
3096                zval_dtor(&fetch_class_opline->op2.u.constant);
3097                MAKE_NOP(fetch_class_opline);
3098
3099                table = CG(class_table);
3100                break;
3101            }
3102        case ZEND_VERIFY_ABSTRACT_CLASS:
3103        case ZEND_ADD_INTERFACE:
3104            /* We currently don't early-bind classes that implement interfaces */
3105            return;
3106        default:
3107            zend_error(E_COMPILE_ERROR, "Invalid binding type");
3108            return;
3109    }
3110
3111    zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
3112    zval_dtor(&opline->op1.u.constant);
3113    zval_dtor(&opline->op2.u.constant);
3114    MAKE_NOP(opline);
3115}
3116/* }}} */
3117
3118ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
3119{
3120    if (op_array->early_binding != -1) {
3121        zend_bool orig_in_compilation = CG(in_compilation);
3122        zend_uint opline_num = op_array->early_binding;
3123        zend_class_entry **pce;
3124
3125        CG(in_compilation) = 1;
3126        while (opline_num != -1) {
3127            if (zend_lookup_class(Z_STRVAL(op_array->opcodes[opline_num-1].op2.u.constant), Z_STRLEN(op_array->opcodes[opline_num-1].op2.u.constant), &pce TSRMLS_CC) == SUCCESS) {
3128                do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
3129            }
3130            opline_num = op_array->opcodes[opline_num].result.u.opline_num;
3131        }
3132        CG(in_compilation) = orig_in_compilation;
3133    }
3134}
3135/* }}} */
3136
3137void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
3138{
3139    int next_op_number = get_next_op_number(CG(active_op_array));
3140    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3141
3142    opline->opcode = ZEND_JMPNZ_EX;
3143    if (expr1->op_type == IS_TMP_VAR) {
3144        opline->result = *expr1;
3145    } else {
3146        opline->result.u.var = get_temporary_variable(CG(active_op_array));
3147        opline->result.op_type = IS_TMP_VAR;
3148    }
3149    opline->op1 = *expr1;
3150    SET_UNUSED(opline->op2);
3151
3152    op_token->u.opline_num = next_op_number;
3153
3154    *expr1 = opline->result;
3155}
3156/* }}} */
3157
3158void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
3159{
3160    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3161
3162    *result = *expr1; /* we saved the original result in expr1 */
3163    opline->opcode = ZEND_BOOL;
3164    opline->result = *result;
3165    opline->op1 = *expr2;
3166    SET_UNUSED(opline->op2);
3167
3168    CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3169}
3170/* }}} */
3171
3172void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
3173{
3174    int next_op_number = get_next_op_number(CG(active_op_array));
3175    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3176
3177    opline->opcode = ZEND_JMPZ_EX;
3178    if (expr1->op_type == IS_TMP_VAR) {
3179        opline->result = *expr1;
3180    } else {
3181        opline->result.u.var = get_temporary_variable(CG(active_op_array));
3182        opline->result.op_type = IS_TMP_VAR;
3183    }
3184    opline->op1 = *expr1;
3185    SET_UNUSED(opline->op2);
3186
3187    op_token->u.opline_num = next_op_number;
3188
3189    *expr1 = opline->result;
3190}
3191/* }}} */
3192
3193void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
3194{
3195    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3196
3197    *result = *expr1; /* we saved the original result in expr1 */
3198    opline->opcode = ZEND_BOOL;
3199    opline->result = *result;
3200    opline->op1 = *expr2;
3201    SET_UNUSED(opline->op2);
3202
3203    CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3204}
3205/* }}} */
3206
3207void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
3208{
3209    do_begin_loop(TSRMLS_C);
3210    INC_BPC(CG(active_op_array));
3211}
3212/* }}} */
3213
3214void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC) /* {{{ */
3215{
3216    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3217
3218    opline->opcode = ZEND_JMPNZ;
3219    opline->op1 = *expr;
3220    opline->op2.u.opline_num = do_token->u.opline_num;
3221    SET_UNUSED(opline->op2);
3222
3223    do_end_loop(expr_open_bracket->u.opline_num, 0 TSRMLS_CC);
3224
3225    DEC_BPC(CG(active_op_array));
3226}
3227/* }}} */
3228
3229void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
3230{
3231    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3232
3233    opline->opcode = op;
3234    opline->op1.u.opline_num = CG(active_op_array)->current_brk_cont;
3235    SET_UNUSED(opline->op1);
3236    if (expr) {
3237        opline->op2 = *expr;
3238    } else {
3239        Z_TYPE(opline->op2.u.constant) = IS_LONG;
3240        Z_LVAL(opline->op2.u.constant) = 1;
3241        INIT_PZVAL(&opline->op2.u.constant);
3242        opline->op2.op_type = IS_CONST;
3243    }
3244}
3245/* }}} */
3246
3247void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
3248{
3249    zend_switch_entry switch_entry;
3250
3251    switch_entry.cond = *cond;
3252    switch_entry.default_case = -1;
3253    switch_entry.control_var = -1;
3254    zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
3255
3256    do_begin_loop(TSRMLS_C);
3257
3258    INC_BPC(CG(active_op_array));
3259}
3260/* }}} */
3261
3262void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
3263{
3264    zend_op *opline;
3265    zend_switch_entry *switch_entry_ptr;
3266
3267    zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
3268
3269    /* add code to jmp to default case */
3270    if (switch_entry_ptr->default_case != -1) {
3271        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3272        opline->opcode = ZEND_JMP;
3273        SET_UNUSED(opline->op1);
3274        SET_UNUSED(opline->op2);
3275        opline->op1.u.opline_num = switch_entry_ptr->default_case;
3276    }
3277
3278    if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
3279        int next_op_number = get_next_op_number(CG(active_op_array));
3280
3281        CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
3282    }
3283
3284    /* remember break/continue loop information */
3285    CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
3286    CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
3287
3288    if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
3289        /* emit free for the switch condition*/
3290        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3291        opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
3292        opline->op1 = switch_entry_ptr->cond;
3293        SET_UNUSED(opline->op2);
3294    }
3295    if (switch_entry_ptr->cond.op_type == IS_CONST) {
3296        zval_dtor(&switch_entry_ptr->cond.u.constant);
3297    }
3298
3299    zend_stack_del_top(&CG(switch_cond_stack));
3300
3301    DEC_BPC(CG(active_op_array));
3302}
3303/* }}} */
3304
3305void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC) /* {{{ */
3306{
3307    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3308    int next_op_number;
3309    zend_switch_entry *switch_entry_ptr;
3310    znode result;
3311
3312    zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
3313
3314    if (switch_entry_ptr->control_var == -1) {
3315        switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
3316    }
3317    opline->opcode = ZEND_CASE;
3318    opline->result.u.var = switch_entry_ptr->control_var;
3319    opline->result.op_type = IS_TMP_VAR;
3320    opline->op1 = switch_entry_ptr->cond;
3321    opline->op2 = *case_expr;
3322    if (opline->op1.op_type == IS_CONST) {
3323        zval_copy_ctor(&opline->op1.u.constant);
3324    }
3325    result = opline->result;
3326
3327    next_op_number = get_next_op_number(CG(active_op_array));
3328    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3329    opline->opcode = ZEND_JMPZ;
3330    opline->op1 = result;
3331    SET_UNUSED(opline->op2);
3332    case_token->u.opline_num = next_op_number;
3333
3334    if (case_list->op_type==IS_UNUSED) {
3335        return;
3336    }
3337    next_op_number = get_next_op_number(CG(active_op_array));
3338    CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
3339}
3340/* }}} */
3341
3342void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
3343{
3344    int next_op_number = get_next_op_number(CG(active_op_array));
3345    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3346
3347    opline->opcode = ZEND_JMP;
3348    SET_UNUSED(opline->op1);
3349    SET_UNUSED(opline->op2);
3350    result->u.opline_num = next_op_number;
3351
3352    switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) {
3353        case ZEND_JMP:
3354            CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
3355            break;
3356        case ZEND_JMPZ:
3357            CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3358            break;
3359    }
3360}
3361/* }}} */
3362
3363void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
3364{
3365    int next_op_number = get_next_op_number(CG(active_op_array));
3366    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3367    zend_switch_entry *switch_entry_ptr;
3368
3369    zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
3370
3371    opline->opcode = ZEND_JMP;
3372    SET_UNUSED(opline->op1);
3373    SET_UNUSED(opline->op2);
3374    default_token->u.opline_num = next_op_number;
3375
3376    next_op_number = get_next_op_number(CG(active_op_array));
3377    switch_entry_ptr->default_case = next_op_number;
3378
3379    if (case_list->op_type==IS_UNUSED) {
3380        return;
3381    }
3382    CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
3383}
3384/* }}} */
3385
3386void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
3387{
3388    zend_op *opline;
3389    int doing_inheritance = 0;
3390    zend_class_entry *new_class_entry;
3391    char *lcname;
3392    int error = 0;
3393    zval **ns_name;
3394
3395    if (CG(active_class_entry)) {
3396        zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
3397        return;
3398    }
3399
3400    lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
3401
3402    if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
3403        efree(lcname);
3404        zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
3405    }
3406
3407    /* Class name must not conflict with import names */
3408    if (CG(current_import) &&
3409            zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
3410        error = 1;
3411    }
3412
3413    if (CG(current_namespace)) {
3414        /* Prefix class name with name of current namespace */
3415        znode tmp;
3416
3417        tmp.op_type = IS_CONST;
3418        tmp.u.constant = *CG(current_namespace);
3419        zval_copy_ctor(&tmp.u.constant);
3420        zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
3421        *class_name = tmp;
3422        efree(lcname);
3423        lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
3424    }
3425
3426    if (error) {
3427        char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
3428
3429        if (Z_STRLEN_PP(ns_name) != Z_STRLEN(class_name->u.constant) ||
3430            memcmp(tmp, lcname, Z_STRLEN(class_name->u.constant))) {
3431            zend_error(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
3432        }
3433        efree(tmp);
3434    }
3435
3436    new_class_entry = emalloc(sizeof(zend_class_entry));
3437    new_class_entry->type = ZEND_USER_CLASS;
3438    new_class_entry->name = class_name->u.constant.value.str.val;
3439    new_class_entry->name_length = class_name->u.constant.value.str.len;
3440
3441    zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
3442    new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
3443    new_class_entry->line_start = class_token->u.opline_num;
3444    new_class_entry->ce_flags |= class_token->u.EA.type;
3445
3446    if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
3447        switch (parent_class_name->u.EA.type) {
3448            case ZEND_FETCH_CLASS_SELF:
3449                zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
3450                break;
3451            case ZEND_FETCH_CLASS_PARENT:
3452                zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
3453                break;
3454            case ZEND_FETCH_CLASS_STATIC:
3455                zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
3456                break;
3457            default:
3458                break;
3459        }
3460        doing_inheritance = 1;
3461    }
3462
3463    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3464    opline->op1.op_type = IS_CONST;
3465    build_runtime_defined_function_key(&opline->op1.u.constant, lcname, new_class_entry->name_length TSRMLS_CC);
3466
3467    opline->op2.op_type = IS_CONST;
3468    opline->op2.u.constant.type = IS_STRING;
3469    Z_SET_REFCOUNT(opline->op2.u.constant, 1);
3470
3471    if (doing_inheritance) {
3472        opline->extended_value = parent_class_name->u.var;
3473        opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
3474    } else {
3475        opline->opcode = ZEND_DECLARE_CLASS;
3476    }
3477
3478    opline->op2.u.constant.value.str.val = lcname;
3479    opline->op2.u.constant.value.str.len = new_class_entry->name_length;
3480
3481    zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL);
3482    CG(active_class_entry) = new_class_entry;
3483
3484    opline->result.u.var = get_temporary_variable(CG(active_op_array));
3485    opline->result.op_type = IS_VAR;
3486    CG(implementing_class) = opline->result;
3487
3488    if (CG(doc_comment)) {
3489        CG(active_class_entry)->doc_comment = CG(doc_comment);
3490        CG(active_class_entry)->doc_comment_len = CG(doc_comment_len);
3491        CG(doc_comment) = NULL;
3492        CG(doc_comment_len) = 0;
3493    }
3494}
3495/* }}} */
3496
3497static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
3498{
3499    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3500
3501    opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
3502    opline->op1 = CG(implementing_class);
3503    SET_UNUSED(opline->op2);
3504}
3505/* }}} */
3506
3507void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
3508{
3509    zend_class_entry *ce = CG(active_class_entry);
3510
3511    if (ce->constructor) {
3512        ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
3513        if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
3514            zend_error(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
3515        }
3516    }
3517    if (ce->destructor) {
3518        ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
3519        if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
3520            zend_error(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
3521        }
3522    }
3523    if (ce->clone) {
3524        ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
3525        if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
3526            zend_error(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
3527        }
3528    }
3529
3530    ce->line_end = zend_get_compiled_lineno(TSRMLS_C);
3531
3532    if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
3533        && (parent_token || (ce->num_interfaces > 0))) {
3534        zend_verify_abstract_class(ce TSRMLS_CC);
3535        if (ce->num_interfaces) {
3536            do_verify_abstract_class(TSRMLS_C);
3537        }
3538    }
3539    /* Inherit interfaces; reset number to zero, we need it for above check and
3540     * will restore it during actual implementation.
3541     * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
3542     * zend_verify_abstract_class() */
3543    if (ce->num_interfaces > 0) {
3544        ce->interfaces = NULL;
3545        ce->num_interfaces = 0;
3546        ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
3547    }
3548    CG(active_class_entry) = NULL;
3549}
3550/* }}} */
3551
3552void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
3553{
3554    zend_op *opline;
3555
3556    switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
3557        case ZEND_FETCH_CLASS_SELF:
3558        case ZEND_FETCH_CLASS_PARENT:
3559        case ZEND_FETCH_CLASS_STATIC:
3560            zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
3561            break;
3562        default:
3563            break;
3564    }
3565
3566    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3567    opline->opcode = ZEND_ADD_INTERFACE;
3568    opline->op1 = CG(implementing_class);
3569    zend_resolve_class_name(interface_name, &opline->extended_value, 0 TSRMLS_CC);
3570    opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
3571    opline->op2 = *interface_name;
3572    CG(active_class_entry)->num_interfaces++;
3573}
3574/* }}} */
3575
3576ZEND_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) /* {{{ */
3577{
3578    char *prop_name;
3579    int prop_name_length;
3580
3581    prop_name_length = 1 + src1_length + 1 + src2_length;
3582    prop_name = pemalloc(prop_name_length + 1, internal);
3583    prop_name[0] = '\0';
3584    memcpy(prop_name + 1, src1, src1_length+1);
3585    memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
3586
3587    *dest = prop_name;
3588    *dest_length = prop_name_length;
3589}
3590/* }}} */
3591
3592static int zend_strnlen(const char* s, int maxlen) /* {{{ */
3593{
3594    int len = 0;
3595    while (*s++ && maxlen--) len++;
3596    return len;
3597}
3598/* }}} */
3599
3600ZEND_API int zend_unmangle_property_name(char *mangled_property, int len, char **class_name, char **prop_name) /* {{{ */
3601{
3602    int class_name_len;
3603
3604    *class_name = NULL;
3605
3606    if (mangled_property[0]!=0) {
3607        *prop_name = mangled_property;
3608        return SUCCESS;
3609    }
3610    if (len < 3 || mangled_property[1]==0) {
3611        zend_error(E_NOTICE, "Illegal member variable name");
3612        *prop_name = mangled_property;
3613        return FAILURE;
3614    }
3615
3616    class_name_len = zend_strnlen(mangled_property+1, --len - 1) + 1;
3617    if (class_name_len >= len || mangled_property[class_name_len]!=0) {
3618        zend_error(E_NOTICE, "Corrupt member variable name");
3619        *prop_name = mangled_property;
3620        return FAILURE;
3621    }
3622    *class_name = mangled_property+1;
3623    *prop_name = (*class_name)+class_name_len;
3624    return SUCCESS;
3625}
3626/* }}} */
3627
3628void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
3629{
3630    zval *property;
3631    zend_property_info *existing_property_info;
3632    char *comment = NULL;
3633    int comment_len = 0;
3634
3635    if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
3636        zend_error(E_COMPILE_ERROR, "Interfaces may not include member variables");
3637    }
3638
3639    if (access_type & ZEND_ACC_ABSTRACT) {
3640        zend_error(E_COMPILE_ERROR, "Properties cannot be declared abstract");
3641    }
3642
3643    if (access_type & ZEND_ACC_FINAL) {
3644        zend_error(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
3645                    CG(active_class_entry)->name, var_name->u.constant.value.str.val);
3646    }
3647
3648    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) {
3649        if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
3650            zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
3651        }
3652    }
3653    ALLOC_ZVAL(property);
3654
3655    if (value) {
3656        *property = value->u.constant;
3657    } else {
3658        INIT_PZVAL(property);
3659        Z_TYPE_P(property) = IS_NULL;
3660    }
3661
3662    if (CG(doc_comment)) {
3663        comment = CG(doc_comment);
3664        comment_len = CG(doc_comment_len);
3665        CG(doc_comment) = NULL;
3666        CG(doc_comment_len) = 0;
3667    }
3668
3669    zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value.str.val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
3670    efree(var_name->u.constant.value.str.val);
3671}
3672/* }}} */
3673
3674void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC) /* {{{ */
3675{
3676    zval *property;
3677
3678    if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
3679        zend_error(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
3680    }
3681
3682    ALLOC_ZVAL(property);
3683    *property = value->u.constant;
3684
3685    if (zend_hash_add(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) {
3686        FREE_ZVAL(property);
3687        zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
3688    }
3689    FREE_PNODE(var_name);
3690
3691    if (CG(doc_comment)) {
3692        efree(CG(doc_comment));
3693        CG(doc_comment) = NULL;
3694        CG(doc_comment_len) = 0;
3695    }
3696}
3697/* }}} */
3698
3699void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC) /* {{{ */
3700{
3701    zend_op opline;
3702    zend_llist *fetch_list_ptr;
3703
3704    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
3705
3706    if (object->op_type == IS_CV) {
3707        if (object->u.var == CG(active_op_array)->this_var) {
3708            SET_UNUSED(*object); /* this means $this for objects */
3709        }
3710    } else if (fetch_list_ptr->count == 1) {
3711        zend_llist_element *le = fetch_list_ptr->head;
3712        zend_op *opline_ptr = (zend_op *) le->data;
3713
3714        if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
3715            efree(Z_STRVAL(opline_ptr->op1.u.constant));
3716            SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
3717            opline_ptr->op2 = *property;
3718            /* if it was usual fetch, we change it to object fetch */
3719            switch (opline_ptr->opcode) {
3720                case ZEND_FETCH_W:
3721                    opline_ptr->opcode = ZEND_FETCH_OBJ_W;
3722                    break;
3723                case ZEND_FETCH_R:
3724                    opline_ptr->opcode = ZEND_FETCH_OBJ_R;
3725                    break;
3726                case ZEND_FETCH_RW:
3727                    opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
3728                    break;
3729                case ZEND_FETCH_IS:
3730                    opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
3731                    break;
3732                case ZEND_FETCH_UNSET:
3733                    opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
3734                    break;
3735                case ZEND_FETCH_FUNC_ARG:
3736                    opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
3737                    break;
3738            }
3739            *result = opline_ptr->result;
3740            return;
3741        }
3742    }
3743
3744    init_op(&opline TSRMLS_CC);
3745    opline.opcode = ZEND_FETCH_OBJ_W;   /* the backpatching routine assumes W */
3746    opline.result.op_type = IS_VAR;
3747    opline.result.u.EA.type = 0;
3748    opline.result.u.var = get_temporary_variable(CG(active_op_array));
3749    opline.op1 = *object;
3750    opline.op2 = *property;
3751    *result = opline.result;
3752
3753    zend_llist_add_element(fetch_list_ptr, &opline);
3754}
3755/* }}} */
3756
3757void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
3758{
3759    char *name, *cfilename;
3760    char haltoff[] = "__COMPILER_HALT_OFFSET__";
3761    int len, clen;
3762
3763    if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
3764        zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope");
3765    }
3766
3767    cfilename = zend_get_compiled_filename(TSRMLS_C);
3768    clen = strlen(cfilename);
3769    zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
3770    zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
3771    pefree(name, 0);
3772
3773    if (CG(in_namespace)) {
3774        zend_do_end_namespace(TSRMLS_C);
3775    }
3776}
3777/* }}} */
3778
3779void zend_do_declare_implicit_property(TSRMLS_D) /* {{{ */
3780{
3781/* Fixes bug #26182. Not sure why we needed to do this in the first place.
3782   Has to be checked with Zeev.
3783*/
3784#if ANDI_0
3785    zend_op *opline_ptr;
3786    zend_llist_element *le;
3787    zend_llist *fetch_list_ptr;
3788
3789
3790    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
3791
3792    if (fetch_list_ptr->count != 1) {
3793        return;
3794    }
3795
3796    le = fetch_list_ptr->head;
3797    opline_ptr = (zend_op *) le->data;
3798
3799    if (opline_ptr->op1.op_type == IS_UNUSED
3800        && CG(active_class_entry)
3801        && opline_ptr->op2.op_type == IS_CONST
3802        && !zend_hash_exists(&CG(active_class_entry)->properties_info, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
3803        znode property;
3804
3805        property = opline_ptr->op2;
3806        property.u.constant.value.str.val = estrndup(opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
3807        zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);
3808    }
3809#endif
3810}
3811/* }}} */
3812
3813void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
3814{
3815    zend_stack_push(&CG(object_stack), object, sizeof(znode));
3816}
3817/* }}} */
3818
3819void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */
3820{
3821    if (object) {
3822        znode *tmp;
3823
3824        zend_stack_top(&CG(object_stack), (void **) &tmp);
3825        *object = *tmp;
3826    }
3827    zend_stack_del_top(&CG(object_stack));
3828}
3829/* }}} */
3830
3831void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
3832{
3833    zend_op *opline;
3834    unsigned char *ptr = NULL;
3835
3836    new_token->u.opline_num = get_next_op_number(CG(active_op_array));
3837    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3838    opline->opcode = ZEND_NEW;
3839    opline->result.op_type = IS_VAR;
3840    opline->result.u.var = get_temporary_variable(CG(active_op_array));
3841    opline->op1 = *class_type;
3842    SET_UNUSED(opline->op2);
3843
3844    zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
3845}
3846/* }}} */
3847
3848void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC) /* {{{ */
3849{
3850    znode ctor_result;
3851
3852    zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
3853    zend_do_free(&ctor_result TSRMLS_CC);
3854
3855    CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
3856    *result = CG(active_op_array)->opcodes[new_token->u.opline_num].result;
3857}
3858/* }}} */
3859
3860static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
3861{
3862    zend_constant *c = NULL;
3863
3864    if (Z_STRVAL_P(const_name)[0] == '\\') {
3865        if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name), (void **) &c) == FAILURE) {
3866            char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1);
3867
3868            if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name), (void **) &c)==SUCCESS) {
3869                if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
3870                    efree(lookup_name);
3871                    return c;
3872                }
3873            }
3874            efree(lookup_name);
3875            return NULL;
3876        }
3877    } else if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)+1, (void **) &c) == FAILURE) {
3878        char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name));
3879
3880        if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
3881            if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
3882                efree(lookup_name);
3883                return c;
3884            }
3885        }
3886        efree(lookup_name);
3887        return NULL;
3888    }
3889    if (c->flags & CONST_CT_SUBST) {
3890        return c;
3891    }
3892    if (all_internal_constants_substitution &&
3893            (c->flags & CONST_PERSISTENT) &&
3894            !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
3895            Z_TYPE(c->value) != IS_CONSTANT &&
3896            Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
3897        return c;
3898    }
3899    return NULL;
3900}
3901/* }}} */
3902
3903static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
3904{
3905    zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
3906
3907    if (c) {
3908        zval_dtor(const_name);
3909        result->op_type = IS_CONST;
3910        result->u.constant = c->value;
3911        zval_copy_ctor(&result->u.constant);
3912        INIT_PZVAL(&result->u.constant);
3913        return 1;
3914    }
3915    return 0;
3916}
3917/* }}} */
3918
3919void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
3920{
3921    znode tmp;
3922    zend_op *opline;
3923    int type;
3924    char *compound;
3925    ulong fetch_type = 0;
3926
3927    if (constant_container) {
3928        switch (mode) {
3929            case ZEND_CT:
3930                /* this is a class constant */
3931                type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant));
3932
3933                if (ZEND_FETCH_CLASS_STATIC == type) {
3934                    zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
3935                } else if (ZEND_FETCH_CLASS_DEFAULT == type) {
3936                    zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
3937                }
3938                zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
3939                *result = *constant_container;
3940                result->u.constant.type = IS_CONSTANT | fetch_type;
3941                break;
3942            case ZEND_RT:
3943                if (constant_container->op_type == IS_CONST &&
3944                ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
3945                    zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
3946                } else {
3947                    zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
3948                    constant_container = &tmp;
3949                }
3950                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3951                opline->opcode = ZEND_FETCH_CONSTANT;
3952                opline->result.op_type = IS_TMP_VAR;
3953                opline->result.u.var = get_temporary_variable(CG(active_op_array));
3954                opline->op1 = *constant_container;
3955                opline->op2 = *constant_name;
3956                *result = opline->result;
3957                break;
3958        }
3959        return;
3960    }
3961    /* namespace constant */
3962    /* only one that did not contain \ from the start can be converted to string if unknown */
3963    switch (mode) {
3964        case ZEND_CT:
3965            compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
3966            /* this is a namespace constant, or an unprefixed constant */
3967
3968            if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
3969                break;
3970            }
3971
3972            zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
3973
3974            if(!compound) {
3975                fetch_type |= IS_CONSTANT_UNQUALIFIED;
3976            }
3977
3978            *result = *constant_name;
3979            result->u.constant.type = IS_CONSTANT | fetch_type;
3980            break;
3981        case ZEND_RT:
3982            compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
3983
3984            zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
3985
3986            if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
3987                break;
3988            }
3989
3990            opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3991            opline->opcode = ZEND_FETCH_CONSTANT;
3992            opline->result.op_type = IS_TMP_VAR;
3993            opline->result.u.var = get_temporary_variable(CG(active_op_array));
3994            *result = opline->result;
3995            SET_UNUSED(opline->op1);
3996            if(compound) {
3997                /* the name is unambiguous */
3998                opline->extended_value = 0;
3999            } else {
4000                opline->extended_value = IS_CONSTANT_UNQUALIFIED;
4001            }
4002            opline->op2 = *constant_name;
4003            break;
4004    }
4005}
4006/* }}} */
4007
4008void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
4009{
4010    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4011
4012    switch (cmd->op_type) {
4013        case IS_CONST:
4014        case IS_TMP_VAR:
4015            opline->opcode = ZEND_SEND_VAL;
4016            break;
4017        default:
4018            opline->opcode = ZEND_SEND_VAR;
4019            break;
4020    }
4021    opline->op1 = *cmd;
4022    opline->op2.u.opline_num = 1;
4023    opline->extended_value = ZEND_DO_FCALL;
4024    SET_UNUSED(opline->op2);
4025
4026    /* FIXME: exception support not added to this op2 */
4027    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4028    opline->opcode = ZEND_DO_FCALL;
4029    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4030    opline->result.op_type = IS_VAR;
4031    Z_STRVAL(opline->op1.u.constant) = estrndup("shell_exec", sizeof("shell_exec")-1);
4032    Z_STRLEN(opline->op1.u.constant) = sizeof("shell_exec")-1;
4033    INIT_PZVAL(&opline->op1.u.constant);
4034    Z_TYPE(opline->op1.u.constant) = IS_STRING;
4035    opline->op1.op_type = IS_CONST;
4036    opline->extended_value = 1;
4037    SET_UNUSED(opline->op2);
4038    ZVAL_LONG(&opline->op2.u.constant, zend_hash_func("shell_exec", sizeof("shell_exec")));
4039    *result = opline->result;
4040}
4041/* }}} */
4042
4043void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
4044{
4045    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4046
4047    opline->opcode = ZEND_INIT_ARRAY;
4048    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4049    opline->result.op_type = IS_TMP_VAR;
4050    *result = opline->result;
4051    if (expr) {
4052        opline->op1 = *expr;
4053        if (offset) {
4054            opline->op2 = *offset;
4055        } else {
4056            SET_UNUSED(opline->op2);
4057        }
4058    } else {
4059        SET_UNUSED(opline->op1);
4060        SET_UNUSED(opline->op2);
4061    }
4062    opline->extended_value = is_ref;
4063}
4064/* }}} */
4065
4066void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
4067{
4068    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4069
4070    opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
4071    opline->result = *result;
4072    opline->op1 = *expr;
4073    if (offset) {
4074        opline->op2 = *offset;
4075    } else {
4076        SET_UNUSED(opline->op2);
4077    }
4078    opline->extended_value = is_ref;
4079}
4080/* }}} */
4081
4082void zend_do_add_static_array_element(znode *result, znode *offset, const znode *expr) /* {{{ */
4083{
4084    zval *element;
4085
4086    ALLOC_ZVAL(element);
4087    *element = expr->u.constant;
4088    if (offset) {
4089        switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
4090            case IS_CONSTANT:
4091                /* Ugly hack to denote that this value has a constant index */
4092                Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
4093                Z_STRVAL(offset->u.constant) = erealloc(Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3);
4094                Z_STRVAL(offset->u.constant)[Z_STRLEN(offset->u.constant)+1] = Z_TYPE(offset->u.constant);
4095                Z_STRVAL(offset->u.constant)[Z_STRLEN(offset->u.constant)+2] = 0;
4096                zend_symtable_update(result->u.constant.value.ht, Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
4097                zval_dtor(&offset->u.constant);
4098                break;
4099            case IS_STRING:
4100                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);
4101                zval_dtor(&offset->u.constant);
4102                break;
4103            case IS_NULL:
4104                zend_symtable_update(Z_ARRVAL(result->u.constant), "", 1, &element, sizeof(zval *), NULL);
4105                break;
4106            case IS_LONG:
4107            case IS_BOOL:
4108                zend_hash_index_update(Z_ARRVAL(result->u.constant), Z_LVAL(offset->u.constant), &element, sizeof(zval *), NULL);
4109                break;
4110            case IS_DOUBLE:
4111                zend_hash_index_update(Z_ARRVAL(result->u.constant), zend_dval_to_lval(Z_DVAL(offset->u.constant)), &element, sizeof(zval *), NULL);
4112                break;
4113            case IS_CONSTANT_ARRAY:
4114                zend_error(E_ERROR, "Illegal offset type");
4115                break;
4116        }
4117    } else {
4118        zend_hash_next_index_insert(Z_ARRVAL(result->u.constant), &element, sizeof(zval *), NULL);
4119    }
4120}
4121/* }}} */
4122
4123void zend_do_add_list_element(const znode *element TSRMLS_DC) /* {{{ */
4124{
4125    list_llist_element lle;
4126
4127    if (element) {
4128        zend_check_writable_variable(element);
4129
4130        lle.var = *element;
4131        zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
4132        zend_llist_prepend_element(&CG(list_llist), &lle);
4133    }
4134    (*((int *)CG(dimension_llist).tail->data))++;
4135}
4136/* }}} */
4137
4138void zend_do_new_list_begin(TSRMLS_D) /* {{{ */
4139{
4140    int current_dimension = 0;
4141    zend_llist_add_element(&CG(dimension_llist), &current_dimension);
4142}
4143/* }}} */
4144
4145void zend_do_new_list_end(TSRMLS_D) /* {{{ */
4146{
4147    zend_llist_remove_tail(&CG(dimension_llist));
4148    (*((int *)CG(dimension_llist).tail->data))++;
4149}
4150/* }}} */
4151
4152void zend_do_list_init(TSRMLS_D) /* {{{ */
4153{
4154    zend_stack_push(&CG(list_stack), &CG(list_llist), sizeof(zend_llist));
4155    zend_stack_push(&CG(list_stack), &CG(dimension_llist), sizeof(zend_llist));
4156    zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
4157    zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
4158    zend_do_new_list_begin(TSRMLS_C);
4159}
4160/* }}} */
4161
4162void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
4163{
4164    zend_llist_element *le;
4165    zend_llist_element *dimension;
4166    zend_op *opline;
4167    znode last_container;
4168
4169    le = CG(list_llist).head;
4170    while (le) {
4171        zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
4172        dimension = tmp_dimension_llist->head;
4173        while (dimension) {
4174            opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4175            if (dimension == tmp_dimension_llist->head) { /* first */
4176                last_container = *expr;
4177                switch (expr->op_type) {
4178                    case IS_VAR:
4179                    case IS_CV:
4180                        opline->opcode = ZEND_FETCH_DIM_R;
4181                        break;
4182                    case IS_TMP_VAR:
4183                        opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
4184                        break;
4185                    case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */
4186                        zval_copy_ctor(&expr->u.constant);
4187                        opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
4188                        break;
4189                }
4190                opline->extended_value = ZEND_FETCH_ADD_LOCK;
4191            } else {
4192                opline->opcode = ZEND_FETCH_DIM_R;
4193            }
4194            opline->result.op_type = IS_VAR;
4195            opline->result.u.EA.type = 0;
4196            opline->result.u.var = get_temporary_variable(CG(active_op_array));
4197            opline->op1 = last_container;
4198            opline->op2.op_type = IS_CONST;
4199            Z_TYPE(opline->op2.u.constant) = IS_LONG;
4200            Z_LVAL(opline->op2.u.constant) = *((int *) dimension->data);
4201            INIT_PZVAL(&opline->op2.u.constant);
4202            last_container = opline->result;
4203            dimension = dimension->next;
4204        }
4205        ((list_llist_element *) le->data)->value = last_container;
4206        zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
4207        zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
4208        zend_do_free(result TSRMLS_CC);
4209        le = le->next;
4210    }
4211    zend_llist_destroy(&CG(dimension_llist));
4212    zend_llist_destroy(&CG(list_llist));
4213    *result = *expr;
4214    {
4215        zend_llist *p;
4216
4217        /* restore previous lists */
4218        zend_stack_top(&CG(list_stack), (void **) &p);
4219        CG(dimension_llist) = *p;
4220        zend_stack_del_top(&CG(list_stack));
4221        zend_stack_top(&CG(list_stack), (void **) &p);
4222        CG(list_llist) = *p;
4223        zend_stack_del_top(&CG(list_stack));
4224    }
4225}
4226/* }}} */
4227
4228void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
4229{
4230    zval *tmp;
4231    zend_op *opline;
4232    znode lval;
4233    znode result;
4234
4235    ALLOC_ZVAL(tmp);
4236
4237    if (static_assignment) {
4238        *tmp = static_assignment->u.constant;
4239    } else {
4240        INIT_ZVAL(*tmp);
4241    }
4242    if (!CG(active_op_array)->static_variables) {
4243        ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
4244        zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
4245    }
4246    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);
4247
4248    if (varname->op_type == IS_CONST) {
4249        if (Z_TYPE(varname->u.constant) != IS_STRING) {
4250            convert_to_string(&varname->u.constant);
4251        }
4252    }
4253
4254    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4255    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 */
4256    opline->result.op_type = IS_VAR;
4257    opline->result.u.EA.type = 0;
4258    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4259    opline->op1 = *varname;
4260    SET_UNUSED(opline->op2);
4261    opline->op2.u.EA.type = ZEND_FETCH_STATIC;
4262    result = opline->result;
4263
4264    if (varname->op_type == IS_CONST) {
4265        zval_copy_ctor(&varname->u.constant);
4266    }
4267    fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
4268
4269    if (fetch_type == ZEND_FETCH_LEXICAL) {
4270        znode dummy;
4271
4272        zend_do_begin_variable_parse(TSRMLS_C);
4273        zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
4274        zend_do_free(&dummy TSRMLS_CC);
4275    } else {
4276        zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
4277    }
4278    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
4279
4280/*  zval_dtor(&varname->u.constant); */
4281}
4282/* }}} */
4283
4284void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
4285{
4286    znode value;
4287
4288    if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
4289            memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
4290        zend_error(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
4291        return;
4292    }
4293
4294    value.op_type = IS_CONST;
4295    ZVAL_NULL(&value.u.constant);
4296    Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
4297    Z_SET_REFCOUNT_P(&value.u.constant, 1);
4298    Z_UNSET_ISREF_P(&value.u.constant);
4299
4300    zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
4301}
4302/* }}} */
4303
4304void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
4305{
4306    zend_op *opline;
4307    znode lval;
4308    znode result;
4309
4310    if (varname->op_type == IS_CONST) {
4311        if (Z_TYPE(varname->u.constant) != IS_STRING) {
4312            convert_to_string(&varname->u.constant);
4313        }
4314    }
4315
4316    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4317    opline->opcode = ZEND_FETCH_W;      /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
4318    opline->result.op_type = IS_VAR;
4319    opline->result.u.EA.type = 0;
4320    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4321    opline->op1 = *varname;
4322    SET_UNUSED(opline->op2);
4323    opline->op2.u.EA.type = fetch_type;
4324    result = opline->result;
4325
4326    if (varname->op_type == IS_CONST) {
4327        zval_copy_ctor(&varname->u.constant);
4328    }
4329    fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
4330
4331    zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
4332    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
4333}
4334/* }}} */
4335
4336void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC) /* {{{ */
4337{
4338    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4339
4340    opline->opcode = ZEND_CAST;
4341    opline->result.op_type = IS_TMP_VAR;
4342    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4343    opline->op1 = *expr;
4344    SET_UNUSED(opline->op2);
4345    opline->extended_value = type;
4346    *result = opline->result;
4347}
4348/* }}} */
4349
4350void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
4351{
4352    zend_do_extended_fcall_begin(TSRMLS_C);
4353    {
4354        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4355
4356        opline->opcode = ZEND_INCLUDE_OR_EVAL;
4357        opline->result.op_type = IS_VAR;
4358        opline->result.u.var = get_temporary_variable(CG(active_op_array));
4359        opline->op1 = *op1;
4360        SET_UNUSED(opline->op2);
4361        Z_LVAL(opline->op2.u.constant) = type;
4362        *result = opline->result;
4363    }
4364    zend_do_extended_fcall_end(TSRMLS_C);
4365}
4366/* }}} */
4367
4368void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC) /* {{{ */
4369{
4370    int i;
4371
4372    zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
4373    for (i=1; i<num_references->u.constant.value.lval; i++) {
4374        fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
4375        *variable = *result;
4376    }
4377    zend_do_begin_variable_parse(TSRMLS_C);
4378    fetch_simple_variable(result, variable, 1 TSRMLS_CC);
4379    /* there is a chance someone is accessing $this */
4380    if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
4381        CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
4382    }
4383}
4384/* }}} */
4385
4386void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
4387{
4388    zend_op *last_op;
4389
4390    zend_check_writable_variable(variable);
4391
4392    if (variable->op_type == IS_CV) {
4393        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4394        opline->opcode = ZEND_UNSET_VAR;
4395        opline->op1 = *variable;
4396        SET_UNUSED(opline->op2);
4397        opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
4398        SET_UNUSED(opline->result);
4399        opline->extended_value = ZEND_QUICK_SET;
4400    } else {
4401        last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
4402
4403        switch (last_op->opcode) {
4404            case ZEND_FETCH_UNSET:
4405                last_op->opcode = ZEND_UNSET_VAR;
4406                break;
4407            case ZEND_FETCH_DIM_UNSET:
4408                last_op->opcode = ZEND_UNSET_DIM;
4409                break;
4410            case ZEND_FETCH_OBJ_UNSET:
4411                last_op->opcode = ZEND_UNSET_OBJ;
4412                break;
4413
4414        }
4415    }
4416}
4417/* }}} */
4418
4419void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC) /* {{{ */
4420{
4421    zend_op *last_op;
4422
4423    zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
4424
4425    zend_check_writable_variable(variable);
4426
4427    if (variable->op_type == IS_CV) {
4428        last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
4429        last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
4430        last_op->op1 = *variable;
4431        SET_UNUSED(last_op->op2);
4432        last_op->op2.u.EA.type = ZEND_FETCH_LOCAL;
4433        last_op->result.u.var = get_temporary_variable(CG(active_op_array));
4434        last_op->extended_value = ZEND_QUICK_SET;
4435    } else {
4436        last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
4437
4438        switch (last_op->opcode) {
4439            case ZEND_FETCH_IS:
4440                last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
4441                break;
4442            case ZEND_FETCH_DIM_IS:
4443                last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
4444                break;
4445            case ZEND_FETCH_OBJ_IS:
4446                last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
4447                break;
4448        }
4449        last_op->extended_value = 0;
4450    }
4451    last_op->result.op_type = IS_TMP_VAR;
4452    last_op->extended_value |= type;
4453
4454    *result = last_op->result;
4455}
4456/* }}} */
4457
4458void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC) /* {{{ */
4459{
4460    int last_op_number = get_next_op_number(CG(active_op_array));
4461    zend_op *opline;
4462
4463    if (last_op_number > 0) {
4464        opline = &CG(active_op_array)->opcodes[last_op_number-1];
4465        if (opline->opcode == ZEND_FETCH_CLASS) {
4466            opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
4467        }
4468    }
4469
4470    if (expr->op_type == IS_CONST) {
4471        zend_error(E_COMPILE_ERROR, "instanceof expects an object instance, constant given");
4472    }
4473
4474    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4475    opline->opcode = ZEND_INSTANCEOF;
4476    opline->result.op_type = IS_TMP_VAR;
4477    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4478    opline->op1 = *expr;
4479
4480    opline->op2 = *class_znode;
4481
4482    *result = opline->result;
4483}
4484/* }}} */
4485
4486void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC) /* {{{ */
4487{
4488    zend_op *opline;
4489    zend_bool is_variable;
4490    zend_bool push_container = 0;
4491    zend_op dummy_opline;
4492
4493    if (variable) {
4494        if (zend_is_function_or_method_call(array)) {
4495            is_variable = 0;
4496        } else {
4497            is_variable = 1;
4498        }
4499        /* save the location of FETCH_W instruction(s) */
4500        open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
4501        zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
4502        if (CG(active_op_array)->last > 0 &&
4503                CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
4504            /* Only lock the container if we are fetching from a real container and not $this */
4505            if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1.op_type == IS_VAR) {
4506                CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
4507                push_container = 1;
4508            }
4509        }
4510    } else {
4511        is_variable = 0;
4512        open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
4513    }
4514
4515    /* save the location of FE_RESET */
4516    foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
4517
4518    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4519
4520    /* Preform array reset */
4521    opline->opcode = ZEND_FE_RESET;
4522    opline->result.op_type = IS_VAR;
4523    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4524    opline->op1 = *array;
4525    SET_UNUSED(opline->op2);
4526    opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
4527
4528    dummy_opline.result = opline->result;
4529    if (push_container) {
4530        dummy_opline.op1 = CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1;
4531    } else {
4532        znode tmp;
4533
4534        tmp.op_type = IS_UNUSED;
4535        dummy_opline.op1 = tmp;
4536    }
4537    zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
4538
4539    /* save the location of FE_FETCH */
4540    as_token->u.opline_num = get_next_op_number(CG(active_op_array));
4541
4542    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4543    opline->opcode = ZEND_FE_FETCH;
4544    opline->result.op_type = IS_VAR;
4545    opline->result.u.var = get_temporary_variable(CG(active_op_array));
4546    opline->op1 = dummy_opline.result;
4547    opline->extended_value = 0;
4548    SET_UNUSED(opline->op2);
4549
4550    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4551    opline->opcode = ZEND_OP_DATA;
4552    SET_UNUSED(opline->op1);
4553    SET_UNUSED(opline->op2);
4554    SET_UNUSED(opline->result);
4555}
4556/* }}} */
4557
4558void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC) /* {{{ */
4559{
4560    zend_op *opline;
4561    znode dummy, value_node;
4562    zend_bool assign_by_ref=0;
4563
4564    opline = &CG(active_op_array)->opcodes[as_token->u.opline_num];
4565    if (key->op_type != IS_UNUSED) {
4566        znode *tmp;
4567
4568        /* switch between the key and value... */
4569        tmp = key;
4570        key = value;
4571        value = tmp;
4572
4573        /* Mark extended_value in case both key and value are being used */
4574        opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
4575    }
4576
4577    if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) {
4578        zend_error(E_COMPILE_ERROR, "Key element cannot be a reference");
4579    }
4580
4581    if (value->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE) {
4582        assign_by_ref = 1;
4583        if (!(opline-1)->extended_value) {
4584            zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
4585        }
4586        /* Mark extended_value for assign-by-reference */
4587        opline->extended_value |= ZEND_FE_FETCH_BYREF;
4588        CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
4589    } else {
4590        zend_op *foreach_copy;
4591        zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.opline_num];
4592        zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.opline_num];
4593
4594        /* Change "write context" into "read context" */
4595        fetch->extended_value = 0;  /* reset ZEND_FE_RESET_VARIABLE */
4596        while (fetch != end) {
4597            --fetch;
4598            if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2.op_type == IS_UNUSED) {
4599                zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
4600            }
4601            fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
4602        }
4603        /* prevent double SWITCH_FREE */
4604        zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
4605        foreach_copy->op1.op_type = IS_UNUSED;
4606    }
4607
4608    value_node = opline->result;
4609
4610    if (assign_by_ref) {
4611        zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
4612        /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
4613        zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
4614    } else {
4615        zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
4616        zend_do_free(&dummy TSRMLS_CC);
4617    }
4618
4619    if (key->op_type != IS_UNUSED) {
4620        znode key_node;
4621
4622        opline = &CG(active_op_array)->opcodes[as_token->u.opline_num+1];
4623        opline->result.op_type = IS_TMP_VAR;
4624        opline->result.u.EA.type = 0;
4625        opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
4626        key_node = opline->result;
4627
4628        zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
4629        zend_do_free(&dummy TSRMLS_CC);
4630    }
4631
4632    do_begin_loop(TSRMLS_C);
4633    INC_BPC(CG(active_op_array));
4634}
4635/* }}} */
4636
4637void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC) /* {{{ */
4638{
4639    zend_op *container_ptr;
4640    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4641
4642    opline->opcode = ZEND_JMP;
4643    opline->op1.u.opline_num = as_token->u.opline_num;
4644    SET_UNUSED(opline->op1);
4645    SET_UNUSED(opline->op2);
4646
4647    CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
4648    CG(active_op_array)->opcodes[as_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
4649
4650    do_end_loop(as_token->u.opline_num, 1 TSRMLS_CC);
4651
4652    zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
4653    generate_free_foreach_copy(container_ptr TSRMLS_CC);
4654    zend_stack_del_top(&CG(foreach_copy_stack));
4655
4656    DEC_BPC(CG(active_op_array));
4657}
4658/* }}} */
4659
4660void zend_do_declare_begin(TSRMLS_D) /* {{{ */
4661{
4662    zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables));
4663}
4664/* }}} */
4665
4666void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
4667{
4668    if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
4669        convert_to_long(&val->u.constant);
4670        CG(declarables).ticks = val->u.constant;
4671#ifdef ZEND_MULTIBYTE
4672    } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
4673        zend_encoding *new_encoding, *old_encoding;
4674        zend_encoding_filter old_input_filter;
4675
4676        if ((Z_TYPE(val->u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
4677            zend_error(E_COMPILE_ERROR, "Cannot use constants as encoding");
4678        }
4679
4680        /*
4681         * Check that the pragma comes before any opcodes. If the compilation
4682         * got as far as this, the previous portion of the script must have been
4683         * parseable according to the .ini script_encoding setting. We still
4684         * want to tell them to put declare() at the top.
4685         */
4686        {
4687            int num = CG(active_op_array)->last;
4688            /* ignore ZEND_EXT_STMT and ZEND_TICKS */
4689            while (num > 0 &&
4690                         (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
4691                            CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
4692                --num;
4693            }
4694
4695            if (num > 0) {
4696                zend_error(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
4697            }
4698        }
4699        CG(encoding_declared) = 1;
4700
4701        convert_to_string(&val->u.constant);
4702        new_encoding = zend_multibyte_fetch_encoding(val->u.constant.