Back to index

php5  5.3.10
zend_compile.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | Zend Engine                                                          |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 2.00 of the Zend license,     |
00008    | that is bundled with this package in the file LICENSE, and is        | 
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.zend.com/license/2_00.txt.                                |
00011    | If you did not receive a copy of the Zend license and are unable to  |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@zend.com so we can mail you a copy immediately.              |
00014    +----------------------------------------------------------------------+
00015    | Authors: Andi Gutmans <andi@zend.com>                                |
00016    |          Zeev Suraski <zeev@zend.com>                                |
00017    +----------------------------------------------------------------------+
00018 */
00019 
00020 /* $Id: zend_compile.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #include <zend_language_parser.h>
00023 #include "zend.h"
00024 #include "zend_compile.h"
00025 #include "zend_constants.h"
00026 #include "zend_llist.h"
00027 #include "zend_API.h"
00028 #include "zend_exceptions.h"
00029 #include "tsrm_virtual_cwd.h"
00030 
00031 #ifdef ZEND_MULTIBYTE
00032 #include "zend_multibyte.h"
00033 #endif /* ZEND_MULTIBYTE */
00034 
00035 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
00036 ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
00037 
00038 #ifndef ZTS
00039 ZEND_API zend_compiler_globals compiler_globals;
00040 ZEND_API zend_executor_globals executor_globals;
00041 #endif
00042 
00043 static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
00044 {
00045        property_info->name = estrndup(property_info->name, property_info->name_length);
00046        if (property_info->doc_comment) {
00047               property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
00048        }
00049 }
00050 /* }}} */
00051 
00052 
00053 static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
00054 {
00055        property_info->name = zend_strndup(property_info->name, property_info->name_length);
00056 }
00057 /* }}} */
00058 
00059 
00060 static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
00061 {
00062        efree(property_info->name);
00063        if (property_info->doc_comment) {
00064               efree(property_info->doc_comment);
00065        }
00066 }
00067 /* }}} */
00068 
00069 
00070 static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
00071 {
00072        free(property_info->name);
00073 }
00074 /* }}} */
00075 
00076 static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
00077 {
00078        char char_pos_buf[32];
00079        uint char_pos_len;
00080        char *filename;
00081 
00082        char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
00083        if (CG(active_op_array)->filename) {
00084               filename = CG(active_op_array)->filename;
00085        } else {
00086               filename = "-";
00087        }
00088 
00089        /* NULL, name length, filename length, last accepting char position length */
00090        result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
00091 #ifdef ZEND_MULTIBYTE
00092        /* must be binary safe */
00093        result->value.str.val = (char *) safe_emalloc(result->value.str.len, 1, 1);
00094        result->value.str.val[0] = '\0';
00095        sprintf(result->value.str.val+1, "%s%s%s", name, filename, char_pos_buf);
00096 #else
00097        zend_spprintf(&result->value.str.val, 0, "%c%s%s%s", '\0', name, filename, char_pos_buf);
00098 #endif /* ZEND_MULTIBYTE */
00099        result->type = IS_STRING;
00100        Z_SET_REFCOUNT_P(result, 1);
00101 }
00102 /* }}} */
00103 
00104 
00105 int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
00106 {
00107        auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
00108        return 0;
00109 }
00110 /* }}} */
00111 
00112 
00113 ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */
00114 {
00115        zend_auto_global *auto_global;
00116 
00117        if (zend_hash_find(CG(auto_globals), varname, varname_length+1, (void **) &auto_global)==FAILURE) {
00118               return FAILURE;
00119        }
00120        auto_global->armed = 0;
00121        return SUCCESS;
00122 }
00123 /* }}} */
00124 
00125 
00126 static void init_compiler_declarables(TSRMLS_D) /* {{{ */
00127 {
00128        Z_TYPE(CG(declarables).ticks) = IS_LONG;
00129        Z_LVAL(CG(declarables).ticks) = 0;
00130 }
00131 /* }}} */
00132 
00133 
00134 void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
00135 {
00136        zend_stack_init(&CG(bp_stack));
00137        zend_stack_init(&CG(function_call_stack));
00138        zend_stack_init(&CG(switch_cond_stack));
00139        zend_stack_init(&CG(foreach_copy_stack));
00140        zend_stack_init(&CG(object_stack));
00141        zend_stack_init(&CG(declare_stack));
00142        CG(active_class_entry) = NULL;
00143        zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
00144        zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
00145        zend_stack_init(&CG(list_stack));
00146        CG(in_compilation) = 0;
00147        CG(start_lineno) = 0;
00148        CG(current_namespace) = NULL;
00149        CG(in_namespace) = 0;
00150        CG(has_bracketed_namespaces) = 0;
00151        CG(current_import) = NULL;
00152        init_compiler_declarables(TSRMLS_C);
00153        zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
00154        zend_stack_init(&CG(labels_stack));
00155        CG(labels) = NULL;
00156 
00157 #ifdef ZEND_MULTIBYTE
00158        CG(script_encoding_list) = NULL;
00159        CG(script_encoding_list_size) = 0;
00160        CG(internal_encoding) = NULL;
00161        CG(encoding_detector) = NULL;
00162        CG(encoding_converter) = NULL;
00163        CG(encoding_oddlen) = NULL;
00164        CG(encoding_declared) = 0;
00165 #endif /* ZEND_MULTIBYTE */
00166 }
00167 /* }}} */
00168 
00169 
00170 ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
00171 {
00172        TSRMLS_FETCH();
00173 
00174        zend_file_handle_dtor(fh TSRMLS_CC);
00175 }
00176 /* }}} */
00177 
00178 
00179 void init_compiler(TSRMLS_D) /* {{{ */
00180 {
00181        CG(active_op_array) = NULL;
00182        zend_init_compiler_data_structures(TSRMLS_C);
00183        zend_init_rsrc_list(TSRMLS_C);
00184        zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
00185        zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
00186        CG(unclean_shutdown) = 0;
00187 }
00188 /* }}} */
00189 
00190 
00191 void shutdown_compiler(TSRMLS_D) /* {{{ */
00192 {
00193        zend_stack_destroy(&CG(bp_stack));
00194        zend_stack_destroy(&CG(function_call_stack));
00195        zend_stack_destroy(&CG(switch_cond_stack));
00196        zend_stack_destroy(&CG(foreach_copy_stack));
00197        zend_stack_destroy(&CG(object_stack));
00198        zend_stack_destroy(&CG(declare_stack));
00199        zend_stack_destroy(&CG(list_stack));
00200        zend_hash_destroy(&CG(filenames_table));
00201        zend_llist_destroy(&CG(open_files));
00202        zend_stack_destroy(&CG(labels_stack));
00203 
00204 #ifdef ZEND_MULTIBYTE
00205        if (CG(script_encoding_list)) {
00206               efree(CG(script_encoding_list));
00207        }
00208 #endif /* ZEND_MULTIBYTE */
00209 }
00210 /* }}} */
00211 
00212 
00213 ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
00214 {
00215        char **pp, *p;
00216        int length = strlen(new_compiled_filename);
00217 
00218        if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
00219               CG(compiled_filename) = *pp;
00220               return *pp;
00221        }
00222        p = estrndup(new_compiled_filename, length);
00223        zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
00224        CG(compiled_filename) = p;
00225        return p;
00226 }
00227 /* }}} */
00228 
00229 
00230 ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
00231 {
00232        CG(compiled_filename) = original_compiled_filename;
00233 }
00234 /* }}} */
00235 
00236 
00237 ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
00238 {
00239        return CG(compiled_filename);
00240 }
00241 /* }}} */
00242 
00243 
00244 ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
00245 {
00246        return CG(zend_lineno);
00247 }
00248 /* }}} */
00249 
00250 
00251 ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
00252 {
00253        return CG(in_compilation);
00254 }
00255 /* }}} */
00256 
00257 
00258 static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
00259 {
00260        return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
00261 }
00262 /* }}} */
00263 
00264 static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ */
00265 {
00266        int i = 0;
00267        ulong hash_value = zend_inline_hash_func(name, name_len+1);
00268 
00269        while (i < op_array->last_var) {
00270               if (op_array->vars[i].hash_value == hash_value &&
00271                   op_array->vars[i].name_len == name_len &&
00272                   strcmp(op_array->vars[i].name, name) == 0) {
00273                 efree(name);
00274                 return i;
00275               }
00276               i++;
00277        }
00278        i = op_array->last_var;
00279        op_array->last_var++;
00280        if (op_array->last_var > op_array->size_var) {
00281               op_array->size_var += 16; /* FIXME */
00282               op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
00283        }
00284        op_array->vars[i].name = name; /* estrndup(name, name_len); */
00285        op_array->vars[i].name_len = name_len;
00286        op_array->vars[i].hash_value = hash_value;
00287        return i;
00288 }
00289 /* }}} */
00290 
00291 
00292 void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
00293 {
00294        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00295 
00296        opline->opcode = op;
00297        opline->result.op_type = IS_TMP_VAR;
00298        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00299        opline->op1 = *op1;
00300        opline->op2 = *op2;
00301        *result = opline->result;
00302 }
00303 /* }}} */
00304 
00305 void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
00306 {
00307        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00308 
00309        opline->opcode = op;
00310        opline->result.op_type = IS_TMP_VAR;
00311        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00312        opline->op1 = *op1;
00313        *result = opline->result;
00314        SET_UNUSED(opline->op2);
00315 }
00316 /* }}} */
00317 
00318 #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;  }
00319 
00320 
00321 static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
00322 {
00323        data_op->opcode = ZEND_OP_DATA;
00324        data_op->op1 = *value;
00325        SET_UNUSED(data_op->op2);
00326 }
00327 /* }}} */
00328 
00329 void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
00330 {
00331        int last_op_number = get_next_op_number(CG(active_op_array));
00332        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00333 
00334        if (last_op_number > 0) {
00335               zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
00336 
00337               switch (last_op->opcode) {
00338                      case ZEND_FETCH_OBJ_RW:
00339                             last_op->opcode = op;
00340                             last_op->extended_value = ZEND_ASSIGN_OBJ;
00341 
00342                             zend_do_op_data(opline, op2 TSRMLS_CC);
00343                             SET_UNUSED(opline->result);
00344                             *result = last_op->result;
00345                             return;
00346                      case ZEND_FETCH_DIM_RW:
00347                             last_op->opcode = op;
00348                             last_op->extended_value = ZEND_ASSIGN_DIM;
00349 
00350                             zend_do_op_data(opline, op2 TSRMLS_CC);
00351                             opline->op2.u.var = get_temporary_variable(CG(active_op_array));
00352                             opline->op2.u.EA.type = 0;
00353                             opline->op2.op_type = IS_VAR;
00354                             SET_UNUSED(opline->result);
00355                             *result = last_op->result;
00356                             return;
00357                      default:
00358                             break;
00359               }
00360        }
00361 
00362        opline->opcode = op;
00363        opline->op1 = *op1;
00364        opline->op2 = *op2;
00365        opline->result.op_type = IS_VAR;
00366        opline->result.u.EA.type = 0;
00367        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00368        *result = opline->result;
00369 }
00370 /* }}} */
00371 
00372 void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
00373 {
00374        zend_op opline;
00375        zend_op *opline_ptr;
00376        zend_llist *fetch_list_ptr;
00377 
00378        if (varname->op_type == IS_CONST) {
00379               if (Z_TYPE(varname->u.constant) != IS_STRING) {
00380                      convert_to_string(&varname->u.constant);
00381               }
00382               if (!zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC) &&
00383                   !(varname->u.constant.value.str.len == (sizeof("this")-1) &&
00384                     !memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
00385                   (CG(active_op_array)->last == 0 ||
00386                    CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
00387                      result->op_type = IS_CV;
00388                      result->u.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
00389                      result->u.EA.type = 0;
00390                      varname->u.constant.value.str.val = CG(active_op_array)->vars[result->u.var].name;
00391                      return;
00392               }
00393        }
00394 
00395        if (bp) {
00396               opline_ptr = &opline;
00397               init_op(opline_ptr TSRMLS_CC);
00398        } else {
00399               opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
00400        }
00401 
00402        opline_ptr->opcode = op;
00403        opline_ptr->result.op_type = IS_VAR;
00404        opline_ptr->result.u.EA.type = 0;
00405        opline_ptr->result.u.var = get_temporary_variable(CG(active_op_array));
00406        opline_ptr->op1 = *varname;
00407        *result = opline_ptr->result;
00408        SET_UNUSED(opline_ptr->op2);
00409 
00410        opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
00411        if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
00412               if (zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC)) {
00413                      opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
00414               }
00415        }
00416 
00417        if (bp) {
00418               zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
00419               zend_llist_add_element(fetch_list_ptr, opline_ptr);
00420        }
00421 }
00422 /* }}} */
00423 
00424 void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
00425 {
00426        /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
00427        fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
00428 }
00429 /* }}} */
00430 
00431 void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
00432 {
00433        znode class_node;
00434        zend_llist *fetch_list_ptr;
00435        zend_llist_element *le;
00436        zend_op *opline_ptr;
00437        zend_op opline;
00438 
00439        zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
00440        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
00441        if (result->op_type == IS_CV) {
00442               init_op(&opline TSRMLS_CC);
00443 
00444               opline.opcode = ZEND_FETCH_W;
00445               opline.result.op_type = IS_VAR;
00446               opline.result.u.EA.type = 0;
00447               opline.result.u.var = get_temporary_variable(CG(active_op_array));
00448               opline.op1.op_type = IS_CONST;
00449               opline.op1.u.constant.type = IS_STRING;
00450               opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
00451               opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
00452               SET_UNUSED(opline.op2);
00453               opline.op2 = class_node;
00454               opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
00455               *result = opline.result;
00456 
00457               zend_llist_add_element(fetch_list_ptr, &opline);
00458        } else {
00459               le = fetch_list_ptr->head;
00460 
00461               opline_ptr = (zend_op *)le->data;
00462               if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1.op_type == IS_CV) {
00463                      init_op(&opline TSRMLS_CC);
00464                      opline.opcode = ZEND_FETCH_W;
00465                      opline.result.op_type = IS_VAR;
00466                      opline.result.u.EA.type = 0;
00467                      opline.result.u.var = get_temporary_variable(CG(active_op_array));
00468                      opline.op1.op_type = IS_CONST;
00469                      opline.op1.u.constant.type = IS_STRING;
00470                      opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
00471                      opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
00472                      SET_UNUSED(opline.op2);
00473                      opline.op2 = class_node;
00474                      opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
00475                      opline_ptr->op1 = opline.result;
00476 
00477                      zend_llist_prepend_element(fetch_list_ptr, &opline);
00478               } else {
00479                      opline_ptr->op2 = class_node;
00480                      opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
00481               }
00482        }
00483 }
00484 /* }}} */
00485 
00486 void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
00487 {
00488        fetch_simple_variable(result, varname, 1 TSRMLS_CC);
00489 
00490        fetch_array_dim(result, result, first_dim TSRMLS_CC);
00491 }
00492 /* }}} */
00493 
00494 void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
00495 {
00496        zend_op opline;
00497        zend_llist *fetch_list_ptr;
00498 
00499        init_op(&opline TSRMLS_CC);
00500        opline.opcode = ZEND_FETCH_DIM_W;  /* the backpatching routine assumes W */
00501        opline.result.op_type = IS_VAR;
00502        opline.result.u.EA.type = 0;
00503        opline.result.u.var = get_temporary_variable(CG(active_op_array));
00504        opline.op1 = *parent;
00505        opline.op2 = *dim;
00506        opline.extended_value = ZEND_FETCH_STANDARD;
00507        *result = opline.result;
00508 
00509        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
00510        zend_llist_add_element(fetch_list_ptr, &opline);
00511 }
00512 /* }}} */
00513 
00514 void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
00515 {
00516        fetch_array_dim(result, parent, offset TSRMLS_CC);
00517 }
00518 /* }}} */
00519 
00520 void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
00521 {
00522        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00523 
00524        opline->result.op_type = IS_TMP_VAR;
00525        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00526        opline->opcode = ZEND_PRINT;
00527        opline->op1 = *arg;
00528        SET_UNUSED(opline->op2);
00529        *result = opline->result;
00530 }
00531 /* }}} */
00532 
00533 void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
00534 {
00535        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00536 
00537        opline->opcode = ZEND_ECHO;
00538        opline->op1 = *arg;
00539        SET_UNUSED(opline->op2);
00540 }
00541 /* }}} */
00542 
00543 void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
00544 {
00545        char *method_type;
00546 
00547        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
00548               Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
00549               method_type = "Interface";
00550        } else {
00551               method_type = "Abstract";
00552        }
00553 
00554        if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
00555               if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) {
00556                      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);
00557               }
00558               if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
00559                      zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00560 
00561                      opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
00562                      SET_UNUSED(opline->op1);
00563                      SET_UNUSED(opline->op2);
00564               } else {
00565                      /* we had code in the function body */
00566                      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);
00567               }
00568        } else {
00569               if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) {
00570                      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);
00571               }
00572        }
00573 }
00574 /* }}} */
00575 
00576 static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
00577 {
00578        if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
00579               && (opline->op1.u.constant.type == IS_STRING)
00580               && (opline->op1.u.constant.value.str.len == (sizeof("this")-1))
00581               && !memcmp(opline->op1.u.constant.value.str.val, "this", sizeof("this"))) {
00582               return 1;
00583        } else {
00584               return 0;
00585        }
00586 }
00587 /* }}} */
00588 
00589 void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC) /* {{{ */
00590 {
00591        int last_op_number;
00592        zend_op *opline;
00593 
00594        if (value->op_type == IS_CV) {
00595               zend_llist *fetch_list_ptr;
00596 
00597               zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
00598               if (fetch_list_ptr && fetch_list_ptr->head) {
00599                      opline = (zend_op *)fetch_list_ptr->head->data;
00600 
00601                      if (opline->opcode == ZEND_FETCH_DIM_W &&
00602                          opline->op1.op_type == IS_CV &&
00603                          opline->op1.u.var == value->u.var) {
00604 
00605                             opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00606                             opline->opcode = ZEND_FETCH_R;
00607                             opline->result.op_type = IS_VAR;
00608                             opline->result.u.EA.type = 0;
00609                             opline->result.u.var = get_temporary_variable(CG(active_op_array));
00610                             opline->op1.op_type = IS_CONST;
00611                             ZVAL_STRINGL(&opline->op1.u.constant,
00612                                    CG(active_op_array)->vars[value->u.var].name, 
00613                                    CG(active_op_array)->vars[value->u.var].name_len, 1);
00614                             SET_UNUSED(opline->op2);
00615                             opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
00616                             value = &opline->result;
00617                      }
00618               }
00619        }
00620 
00621        zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
00622 
00623        last_op_number = get_next_op_number(CG(active_op_array));
00624        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00625 
00626        if (variable->op_type == IS_CV) {
00627               if (variable->u.var == CG(active_op_array)->this_var) {
00628                      zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
00629               }
00630        } else if (variable->op_type == IS_VAR) {
00631               int n = 0;
00632 
00633               while (last_op_number - n > 0) {
00634                      zend_op *last_op;
00635 
00636                      last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
00637 
00638                      if (last_op->result.op_type == IS_VAR &&
00639                          last_op->result.u.var == variable->u.var) {
00640                             if (last_op->opcode == ZEND_FETCH_OBJ_W) {
00641                                    if (n > 0) {
00642                                           int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
00643                                           *opline = *last_op;
00644                                           MAKE_NOP(last_op);
00645                                           /* last_op = opline; */
00646                                           opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00647                                           /* get_next_op can realloc, we need to move last_op */
00648                                           last_op = &CG(active_op_array)->opcodes[opline_no];
00649                                    }
00650                                    last_op->opcode = ZEND_ASSIGN_OBJ;
00651                                    zend_do_op_data(opline, value TSRMLS_CC);
00652                                    SET_UNUSED(opline->result);
00653                                    *result = last_op->result;
00654                                    return;
00655                             } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
00656                                    if (n > 0) {
00657                                           int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
00658                                           *opline = *last_op;
00659                                           MAKE_NOP(last_op);
00660                                           /* last_op = opline; */
00661                                           /* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
00662                                           opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00663                                           /* get_next_op can realloc, we need to move last_op */
00664                                           last_op = &CG(active_op_array)->opcodes[opline_no];
00665                                    }
00666                                    last_op->opcode = ZEND_ASSIGN_DIM;
00667                                    zend_do_op_data(opline, value TSRMLS_CC);
00668                                    opline->op2.u.var = get_temporary_variable(CG(active_op_array));
00669                                    opline->op2.u.EA.type = 0;
00670                                    opline->op2.op_type = IS_VAR;
00671                                    SET_UNUSED(opline->result);
00672                                    *result = last_op->result;
00673                                    return;
00674                             } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
00675                                    zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
00676                             } else {
00677                                    break;
00678                             }
00679                      }
00680                      n++;
00681               }
00682        }
00683 
00684        opline->opcode = ZEND_ASSIGN;
00685        opline->op1 = *variable;
00686        opline->op2 = *value;
00687        opline->result.op_type = IS_VAR;
00688        opline->result.u.EA.type = 0;
00689        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00690        *result = opline->result;
00691 }
00692 /* }}} */
00693 
00694 static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
00695 {
00696        zend_uint type = variable->u.EA.type;
00697 
00698        return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
00699 }
00700 /* }}} */
00701 
00702 void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
00703 {
00704        zend_op *opline;
00705 
00706        if (lvar->op_type == IS_CV) {
00707               if (lvar->u.var == CG(active_op_array)->this_var) {
00708                      zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
00709               }
00710        } else if (lvar->op_type == IS_VAR) {
00711               int last_op_number = get_next_op_number(CG(active_op_array));
00712 
00713               if (last_op_number > 0) {
00714                      opline = &CG(active_op_array)->opcodes[last_op_number-1];
00715                      if (opline_is_fetch_this(opline TSRMLS_CC)) {
00716                             zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
00717                      }
00718               }
00719        }
00720 
00721        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00722        opline->opcode = ZEND_ASSIGN_REF;
00723        if (zend_is_function_or_method_call(rvar)) {
00724               opline->extended_value = ZEND_RETURNS_FUNCTION;
00725        } else if (rvar->u.EA.type & ZEND_PARSED_NEW) {
00726               opline->extended_value = ZEND_RETURNS_NEW;
00727        } else {
00728               opline->extended_value = 0;
00729        }
00730        if (result) {
00731               opline->result.op_type = IS_VAR;
00732               opline->result.u.EA.type = 0;
00733               opline->result.u.var = get_temporary_variable(CG(active_op_array));
00734               *result = opline->result;
00735        } else {
00736               /* SET_UNUSED(opline->result); */
00737               opline->result.u.EA.type |= EXT_TYPE_UNUSED;
00738        }
00739        opline->op1 = *lvar;
00740        opline->op2 = *rvar;
00741 }
00742 /* }}} */
00743 
00744 static inline void do_begin_loop(TSRMLS_D) /* {{{ */
00745 {
00746        zend_brk_cont_element *brk_cont_element;
00747        int parent;
00748 
00749        parent = CG(active_op_array)->current_brk_cont;
00750        CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
00751        brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
00752        brk_cont_element->start = get_next_op_number(CG(active_op_array));
00753        brk_cont_element->parent = parent;
00754 }
00755 /* }}} */
00756 
00757 static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
00758 {
00759        if (!has_loop_var) {
00760               /* The start fileld is used to free temporary variables in case of exceptions.
00761                * We won't try to free something of we don't have loop variable.
00762                */
00763               CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
00764        }
00765        CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
00766        CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
00767        CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
00768 }
00769 /* }}} */
00770 
00771 void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
00772 {
00773        int while_cond_op_number = get_next_op_number(CG(active_op_array));
00774        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00775 
00776        opline->opcode = ZEND_JMPZ;
00777        opline->op1 = *expr;
00778        close_bracket_token->u.opline_num = while_cond_op_number;
00779        SET_UNUSED(opline->op2);
00780 
00781        do_begin_loop(TSRMLS_C);
00782        INC_BPC(CG(active_op_array));
00783 }
00784 /* }}} */
00785 
00786 void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
00787 {
00788        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00789 
00790        /* add unconditional jump */
00791        opline->opcode = ZEND_JMP;
00792        opline->op1.u.opline_num = while_token->u.opline_num;
00793        SET_UNUSED(opline->op1);
00794        SET_UNUSED(opline->op2);
00795 
00796        /* update while's conditional jmp */
00797        CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
00798 
00799        do_end_loop(while_token->u.opline_num, 0 TSRMLS_CC);
00800 
00801        DEC_BPC(CG(active_op_array));
00802 }
00803 /* }}} */
00804 
00805 void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
00806 {
00807        int for_cond_op_number = get_next_op_number(CG(active_op_array));
00808        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00809 
00810        opline->opcode = ZEND_JMPZNZ;
00811        opline->op1 = *expr;  /* the conditional expression */
00812        second_semicolon_token->u.opline_num = for_cond_op_number;
00813        SET_UNUSED(opline->op2);
00814 }
00815 /* }}} */
00816 
00817 void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
00818 {
00819        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00820 
00821        opline->opcode = ZEND_JMP;
00822        opline->op1.u.opline_num = cond_start->u.opline_num;
00823        CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
00824        SET_UNUSED(opline->op1);
00825        SET_UNUSED(opline->op2);
00826 
00827        do_begin_loop(TSRMLS_C);
00828 
00829        INC_BPC(CG(active_op_array));
00830 }
00831 /* }}} */
00832 
00833 void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
00834 {
00835        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00836 
00837        opline->opcode = ZEND_JMP;
00838        opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1;
00839        CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
00840        SET_UNUSED(opline->op1);
00841        SET_UNUSED(opline->op2);
00842 
00843        do_end_loop(second_semicolon_token->u.opline_num+1, 0 TSRMLS_CC);
00844 
00845        DEC_BPC(CG(active_op_array));
00846 }
00847 /* }}} */
00848 
00849 void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
00850 {
00851        int last_op_number = get_next_op_number(CG(active_op_array));
00852        zend_op *opline;
00853 
00854        if (last_op_number > 0) {
00855               zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
00856 
00857               if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
00858                      last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
00859                      last_op->result.op_type = IS_VAR;
00860                      last_op->result.u.EA.type = 0;
00861                      last_op->result.u.var = get_temporary_variable(CG(active_op_array));
00862                      *result = last_op->result;
00863                      return;
00864               }
00865        }
00866 
00867        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00868        opline->opcode = op;
00869        opline->op1 = *op1;
00870        SET_UNUSED(opline->op2);
00871        opline->result.op_type = IS_VAR;
00872        opline->result.u.EA.type = 0;
00873        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00874        *result = opline->result;
00875 }
00876 /* }}} */
00877 
00878 void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
00879 {
00880        int last_op_number = get_next_op_number(CG(active_op_array));
00881        zend_op *opline;
00882 
00883        if (last_op_number > 0) {
00884               zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
00885 
00886               if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
00887                      last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
00888                      last_op->result.op_type = IS_TMP_VAR;
00889                      last_op->result.u.var = get_temporary_variable(CG(active_op_array));
00890                      *result = last_op->result;
00891                      return;
00892               }
00893        }
00894 
00895        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00896        opline->opcode = op;
00897        opline->op1 = *op1;
00898        SET_UNUSED(opline->op2);
00899        opline->result.op_type = IS_TMP_VAR;
00900        opline->result.u.var = get_temporary_variable(CG(active_op_array));
00901        *result = opline->result;
00902 }
00903 /* }}} */
00904 
00905 void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
00906 {
00907        int if_cond_op_number = get_next_op_number(CG(active_op_array));
00908        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00909 
00910        opline->opcode = ZEND_JMPZ;
00911        opline->op1 = *cond;
00912        closing_bracket_token->u.opline_num = if_cond_op_number;
00913        SET_UNUSED(opline->op2);
00914        INC_BPC(CG(active_op_array));
00915 }
00916 /* }}} */
00917 
00918 void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
00919 {
00920        int if_end_op_number = get_next_op_number(CG(active_op_array));
00921        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
00922        zend_llist *jmp_list_ptr;
00923 
00924        opline->opcode = ZEND_JMP;
00925        /* save for backpatching */
00926        if (initialize) {
00927               zend_llist jmp_list;
00928 
00929               zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
00930               zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
00931        }
00932        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
00933        zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
00934 
00935        CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1;
00936        SET_UNUSED(opline->op1);
00937        SET_UNUSED(opline->op2);
00938 }
00939 /* }}} */
00940 
00941 void zend_do_if_end(TSRMLS_D) /* {{{ */
00942 {
00943        int next_op_number = get_next_op_number(CG(active_op_array));
00944        zend_llist *jmp_list_ptr;
00945        zend_llist_element *le;
00946 
00947        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
00948        for (le=jmp_list_ptr->head; le; le = le->next) {
00949               CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number;
00950        }
00951        zend_llist_destroy(jmp_list_ptr);
00952        zend_stack_del_top(&CG(bp_stack));
00953        DEC_BPC(CG(active_op_array));
00954 }
00955 /* }}} */
00956 
00957 void zend_check_writable_variable(const znode *variable) /* {{{ */
00958 {
00959        zend_uint type = variable->u.EA.type;
00960 
00961        if (type & ZEND_PARSED_METHOD_CALL) {
00962               zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
00963        }
00964        if (type == ZEND_PARSED_FUNCTION_CALL) {
00965               zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
00966        }
00967 }
00968 /* }}} */
00969 
00970 void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
00971 {
00972        zend_llist fetch_list;
00973 
00974        zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
00975        zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
00976 }
00977 /* }}} */
00978 
00979 void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
00980 {
00981        zend_llist *fetch_list_ptr;
00982        zend_llist_element *le;
00983        zend_op *opline = NULL;
00984        zend_op *opline_ptr;
00985        zend_uint this_var = -1;
00986 
00987        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
00988 
00989        le = fetch_list_ptr->head;
00990 
00991        /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
00992 
00993        if (le) {
00994               opline_ptr = (zend_op *)le->data;
00995               if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
00996                      /* convert to FETCH_?(this) into IS_CV */
00997                      if (CG(active_op_array)->last == 0 ||
00998                          CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
00999 
01000                             this_var = opline_ptr->result.u.var;
01001                             if (CG(active_op_array)->this_var == -1) {
01002                                    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));
01003                             } else {
01004                                    efree(Z_STRVAL(opline_ptr->op1.u.constant));
01005                             }
01006                             le = le->next;
01007                             if (variable->op_type == IS_VAR &&
01008                                 variable->u.var == this_var) {
01009                                    variable->op_type = IS_CV;
01010                                    variable->u.var = CG(active_op_array)->this_var;
01011                             }
01012                      } else if (CG(active_op_array)->this_var == -1) {
01013                             CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
01014                      }
01015               }
01016 
01017               while (le) {
01018                      opline_ptr = (zend_op *)le->data;
01019                      opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01020                      memcpy(opline, opline_ptr, sizeof(zend_op));
01021                      if (opline->op1.op_type == IS_VAR &&
01022                          opline->op1.u.var == this_var) {
01023                             opline->op1.op_type = IS_CV;
01024                             opline->op1.u.var = CG(active_op_array)->this_var;
01025                      }
01026                      switch (type) {
01027                             case BP_VAR_R:
01028                                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
01029                                           zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
01030                                    }
01031                                    opline->opcode -= 3;
01032                                    break;
01033                             case BP_VAR_W:
01034                                    break;
01035                             case BP_VAR_RW:
01036                                    opline->opcode += 3;
01037                                    break;
01038                             case BP_VAR_IS:
01039                                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
01040                                           zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
01041                                    }
01042                                    opline->opcode += 6; /* 3+3 */
01043                                    break;
01044                             case BP_VAR_FUNC_ARG:
01045                                    opline->opcode += 9; /* 3+3+3 */
01046                                    opline->extended_value = arg_offset;
01047                                    break;
01048                             case BP_VAR_UNSET:
01049                                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
01050                                           zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
01051                                    }
01052                                    opline->opcode += 12; /* 3+3+3+3 */
01053                                    break;
01054                      }
01055                      le = le->next;
01056               }
01057               if (opline && type == BP_VAR_W && arg_offset) {
01058                      opline->extended_value = ZEND_FETCH_MAKE_REF;
01059               }
01060        }
01061        zend_llist_destroy(fetch_list_ptr);
01062        zend_stack_del_top(&CG(bp_stack));
01063 }
01064 /* }}} */
01065 
01066 void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
01067 {
01068        zend_op *opline;
01069 
01070        if (Z_STRLEN(op2->u.constant) > 1) {
01071               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01072               opline->opcode = ZEND_ADD_STRING;
01073        } else if (Z_STRLEN(op2->u.constant) == 1) {
01074               int ch = *Z_STRVAL(op2->u.constant);
01075 
01076               /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
01077               efree(Z_STRVAL(op2->u.constant));
01078               ZVAL_LONG(&op2->u.constant, ch);
01079               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01080               opline->opcode = ZEND_ADD_CHAR;
01081        } else { /* String can be empty after a variable at the end of a heredoc */
01082               efree(Z_STRVAL(op2->u.constant));
01083               return;
01084        }
01085 
01086        if (op1) {
01087               opline->op1 = *op1;
01088               opline->result = *op1;
01089        } else {
01090               SET_UNUSED(opline->op1);
01091               opline->result.op_type = IS_TMP_VAR;
01092               opline->result.u.var = get_temporary_variable(CG(active_op_array));
01093        }
01094        opline->op2 = *op2;
01095        *result = opline->result;
01096 }
01097 /* }}} */
01098 
01099 void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
01100 {
01101        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01102 
01103        opline->opcode = ZEND_ADD_VAR;
01104 
01105        if (op1) {
01106               opline->op1 = *op1;
01107               opline->result = *op1;
01108        } else {
01109               SET_UNUSED(opline->op1);
01110               opline->result.op_type = IS_TMP_VAR;
01111               opline->result.u.var = get_temporary_variable(CG(active_op_array));
01112        }
01113        opline->op2 = *op2;
01114        *result = opline->result;
01115 }
01116 /* }}} */
01117 
01118 void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
01119 {
01120        if (op1->op_type==IS_TMP_VAR) {
01121               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01122 
01123               opline->opcode = ZEND_FREE;
01124               opline->op1 = *op1;
01125               SET_UNUSED(opline->op2);
01126        } else if (op1->op_type==IS_VAR) {
01127               zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
01128 
01129               while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
01130                      opline--;
01131               }
01132               if (opline->result.op_type == IS_VAR
01133                      && opline->result.u.var == op1->u.var) {
01134                      opline->result.u.EA.type |= EXT_TYPE_UNUSED;
01135               } else {
01136                      while (opline>CG(active_op_array)->opcodes) {
01137                             if (opline->opcode == ZEND_FETCH_DIM_R
01138                                 && opline->op1.op_type == IS_VAR
01139                                 && opline->op1.u.var == op1->u.var) {
01140                                    /* This should the end of a list() construct
01141                                     * Mark its result as unused
01142                                     */
01143                                    opline->extended_value = ZEND_FETCH_STANDARD;
01144                                    break;
01145                             } else if (opline->result.op_type==IS_VAR
01146                                    && opline->result.u.var == op1->u.var) {
01147                                    if (opline->opcode == ZEND_NEW) {
01148                                           opline->result.u.EA.type |= EXT_TYPE_UNUSED;
01149                                    }
01150                                    break;
01151                             }
01152                             opline--;
01153                      }
01154               }
01155        } else if (op1->op_type == IS_CONST) {
01156               zval_dtor(&op1->u.constant);
01157        }
01158 }
01159 /* }}} */
01160 
01161 int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
01162 {
01163        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
01164               && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
01165               zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
01166        }
01167        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
01168               && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
01169               zend_error(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
01170        }
01171        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
01172               && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
01173               zend_error(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
01174        }
01175        if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
01176               && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
01177               zend_error(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
01178        }
01179        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)) {
01180               zend_error(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
01181        }
01182        return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
01183 }
01184 /* }}} */
01185 
01186 void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
01187 {
01188        zend_op_array op_array;
01189        char *name = function_name->u.constant.value.str.val;
01190        int name_len = function_name->u.constant.value.str.len;
01191        int function_begin_line = function_token->u.opline_num;
01192        zend_uint fn_flags;
01193        char *lcname;
01194        zend_bool orig_interactive;
01195        ALLOCA_FLAG(use_heap)
01196 
01197        if (is_method) {
01198               if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
01199                      if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
01200                             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);
01201                      }
01202                      Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
01203               }
01204               fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
01205        } else {
01206               fn_flags = 0;
01207        }
01208        if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
01209               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));
01210        }
01211 
01212        function_token->u.op_array = CG(active_op_array);
01213        lcname = zend_str_tolower_dup(name, name_len);
01214 
01215        orig_interactive = CG(interactive);
01216        CG(interactive) = 0;
01217        init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
01218        CG(interactive) = orig_interactive;
01219 
01220        op_array.function_name = name;
01221        op_array.return_reference = return_reference;
01222        op_array.fn_flags |= fn_flags;
01223        op_array.pass_rest_by_reference = 0;
01224 
01225        op_array.scope = is_method?CG(active_class_entry):NULL;
01226        op_array.prototype = NULL;
01227 
01228        op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
01229 
01230        if (is_method) {
01231               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) {
01232                      zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
01233               }
01234 
01235               if (fn_flags & ZEND_ACC_ABSTRACT) {
01236                      CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
01237               }
01238 
01239               if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
01240                      fn_flags |= ZEND_ACC_PUBLIC;
01241               }
01242 
01243               if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
01244                      if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
01245                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01246                                    zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
01247                             }
01248                      } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
01249                             if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
01250                                    zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
01251                             }
01252                      } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
01253                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01254                                    zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
01255                             }
01256                      } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
01257                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01258                                    zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
01259                             }
01260                      } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
01261                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01262                                    zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
01263                             }
01264                      } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
01265                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01266                                    zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
01267                             }
01268                      } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
01269                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01270                                    zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
01271                             }
01272                      }
01273               } else {
01274                      char *class_lcname;
01275                      
01276                      class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
01277                      zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
01278                      /* Improve after RC: cache the lowercase class name */
01279 
01280                      if ((CG(active_class_entry)->name_length == name_len) && (!memcmp(class_lcname, lcname, name_len))) {
01281                             if (!CG(active_class_entry)->constructor) {
01282                                    CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
01283                             }
01284                      } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
01285                             if (CG(active_class_entry)->constructor) {
01286                                    zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
01287                             }
01288                             CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
01289                      } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
01290                             CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
01291                      } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
01292                             CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
01293                      } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
01294                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01295                                    zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
01296                             }
01297                             CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
01298                      } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
01299                             if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
01300                                    zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
01301                             }
01302                             CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
01303                      } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
01304                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01305                                    zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
01306                             }
01307                             CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
01308                      } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
01309                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01310                                    zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
01311                             }
01312                             CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
01313                      } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
01314                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01315                                    zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
01316                             }
01317                             CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
01318                      } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
01319                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01320                                    zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
01321                             }
01322                             CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
01323                      } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
01324                             if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
01325                                    zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
01326                             }                           
01327                             CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
01328                      } else if (!(fn_flags & ZEND_ACC_STATIC)) {
01329                             CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
01330                      }
01331                      free_alloca(class_lcname, use_heap);
01332               }
01333 
01334               efree(lcname);
01335        } else {
01336               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01337 
01338               if (CG(current_namespace)) {
01339                      /* Prefix function name with current namespcae name */
01340                      znode tmp;
01341 
01342                      tmp.u.constant = *CG(current_namespace);
01343                      zval_copy_ctor(&tmp.u.constant);
01344                      zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
01345                      op_array.function_name = Z_STRVAL(tmp.u.constant);
01346                      efree(lcname);
01347                      name_len = Z_STRLEN(tmp.u.constant);
01348                      lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
01349               }
01350 
01351               opline->opcode = ZEND_DECLARE_FUNCTION;
01352               opline->op1.op_type = IS_CONST;
01353               build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
01354               opline->op2.op_type = IS_CONST;
01355               opline->op2.u.constant.type = IS_STRING;
01356               opline->op2.u.constant.value.str.val = lcname;
01357               opline->op2.u.constant.value.str.len = name_len;
01358               Z_SET_REFCOUNT(opline->op2.u.constant, 1);
01359               opline->extended_value = ZEND_DECLARE_FUNCTION;
01360               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));
01361        }
01362 
01363        if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
01364               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01365 
01366               opline->opcode = ZEND_EXT_NOP;
01367               opline->lineno = function_begin_line;
01368               SET_UNUSED(opline->op1);
01369               SET_UNUSED(opline->op2);
01370        }
01371 
01372        {
01373               /* Push a seperator to the switch and foreach stacks */
01374               zend_switch_entry switch_entry;
01375 
01376               switch_entry.cond.op_type = IS_UNUSED;
01377               switch_entry.default_case = 0;
01378               switch_entry.control_var = 0;
01379 
01380               zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
01381 
01382               {
01383                      /* Foreach stack separator */
01384                      zend_op dummy_opline;
01385 
01386                      dummy_opline.result.op_type = IS_UNUSED;
01387                      dummy_opline.op1.op_type = IS_UNUSED;
01388 
01389                      zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
01390               }
01391        }
01392 
01393        if (CG(doc_comment)) {
01394               CG(active_op_array)->doc_comment = CG(doc_comment);
01395               CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
01396               CG(doc_comment) = NULL;
01397               CG(doc_comment_len) = 0;
01398        }
01399 
01400        zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
01401        CG(labels) = NULL;
01402 }
01403 /* }}} */
01404 
01405 void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC) /* {{{ */
01406 {
01407        znode          function_name;
01408        zend_op_array *current_op_array = CG(active_op_array);
01409        int            current_op_number = get_next_op_number(CG(active_op_array));
01410        zend_op       *current_op;
01411 
01412        function_name.op_type = IS_CONST;
01413        ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
01414 
01415        zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
01416 
01417        result->op_type = IS_TMP_VAR;
01418        result->u.var = get_temporary_variable(current_op_array);
01419 
01420        current_op = &current_op_array->opcodes[current_op_number];
01421        current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
01422        zval_dtor(&current_op->op2.u.constant);
01423        ZVAL_LONG(&current_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant)));
01424        current_op->result = *result;
01425        CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
01426 }
01427 /* }}} */
01428 
01429 void zend_do_handle_exception(TSRMLS_D) /* {{{ */
01430 {
01431        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01432 
01433        opline->opcode = ZEND_HANDLE_EXCEPTION;
01434        SET_UNUSED(opline->op1);
01435        SET_UNUSED(opline->op2);
01436 }
01437 /* }}} */
01438 
01439 void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
01440 {
01441        char lcname[16];
01442        int name_len;
01443 
01444        zend_do_extended_info(TSRMLS_C);
01445        zend_do_return(NULL, 0 TSRMLS_CC);
01446 
01447        pass_two(CG(active_op_array) TSRMLS_CC);
01448        zend_release_labels(TSRMLS_C);
01449 
01450        if (CG(active_class_entry)) {
01451               zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
01452        } else {
01453               /* we don't care if the function name is longer, in fact lowercasing only 
01454                * the beginning of the name speeds up the check process */
01455               name_len = strlen(CG(active_op_array)->function_name);
01456               zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
01457               lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
01458               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) {
01459                      zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
01460               }             
01461        }
01462 
01463        CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
01464        CG(active_op_array) = function_token->u.op_array;
01465 
01466 
01467        /* Pop the switch and foreach seperators */
01468        zend_stack_del_top(&CG(switch_cond_stack));
01469        zend_stack_del_top(&CG(foreach_copy_stack));
01470 }
01471 /* }}} */
01472 
01473 void 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) /* {{{ */
01474 {
01475        zend_op *opline;
01476        zend_arg_info *cur_arg_info;
01477 
01478        if (class_type->op_type == IS_CONST &&
01479            Z_TYPE(class_type->u.constant) == IS_STRING &&
01480            Z_STRLEN(class_type->u.constant) == 0) {
01481               /* Usage of namespace as class name not in namespace */
01482               zval_dtor(&class_type->u.constant);
01483               zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
01484               return;
01485        }
01486 
01487        if (var->op_type == IS_CV &&
01488            var->u.var == CG(active_op_array)->this_var &&
01489            (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
01490               zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
01491        } else if (var->op_type == IS_VAR &&
01492            CG(active_op_array)->scope &&
01493               ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
01494               (Z_TYPE(varname->u.constant) == IS_STRING) &&
01495               (Z_STRLEN(varname->u.constant) == sizeof("this")-1) &&
01496               (memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")) == 0)) {
01497               zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
01498        }
01499 
01500        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01501        CG(active_op_array)->num_args++;
01502        opline->opcode = op;
01503        opline->result = *var;
01504        opline->op1 = *offset;
01505        if (op == ZEND_RECV_INIT) {
01506               opline->op2 = *initialization;
01507        } else {
01508               CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
01509               SET_UNUSED(opline->op2);
01510        }
01511        CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
01512        cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
01513        cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len);
01514        cur_arg_info->name_len = varname->u.constant.value.str.len;
01515        cur_arg_info->array_type_hint = 0;
01516        cur_arg_info->allow_null = 1;
01517        cur_arg_info->pass_by_reference = pass_by_reference;
01518        cur_arg_info->class_name = NULL;
01519        cur_arg_info->class_name_len = 0;
01520 
01521        if (class_type->op_type != IS_UNUSED) {
01522               cur_arg_info->allow_null = 0;
01523               if (class_type->u.constant.type == IS_STRING) {
01524                      if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
01525                             zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC);
01526                      }
01527                      cur_arg_info->class_name = class_type->u.constant.value.str.val;
01528                      cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
01529                      if (op == ZEND_RECV_INIT) {
01530                             if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
01531                                    cur_arg_info->allow_null = 1;
01532                             } else {
01533                                    zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
01534                             }
01535                      }
01536               } else {
01537                      cur_arg_info->array_type_hint = 1;
01538                      cur_arg_info->class_name = NULL;
01539                      cur_arg_info->class_name_len = 0;
01540                      if (op == ZEND_RECV_INIT) {
01541                             if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
01542                                    cur_arg_info->allow_null = 1;
01543                             } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY && Z_TYPE(initialization->u.constant) != IS_CONSTANT_ARRAY) {
01544                                    zend_error(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
01545                             }
01546                      }
01547               }
01548        }
01549        opline->result.u.EA.type |= EXT_TYPE_UNUSED;
01550 }
01551 /* }}} */
01552 
01553 int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
01554 {
01555        zend_function *function;
01556        char *lcname;
01557        char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
01558 
01559        zend_resolve_non_class_name(function_name, check_namespace TSRMLS_CC);
01560 
01561        if (check_namespace && CG(current_namespace) && !is_compound) {
01562                      /* We assume we call function from the current namespace
01563                      if it is not prefixed. */
01564 
01565                      /* In run-time PHP will check for function with full name and
01566                      internal function with short name */
01567                      zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
01568                      return 1;
01569        } 
01570 
01571        lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
01572        if ((zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) ||
01573               ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
01574               (function->type == ZEND_INTERNAL_FUNCTION))) {
01575                      zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
01576                      efree(lcname);
01577                      return 1; /* Dynamic */
01578        } 
01579        efree(function_name->u.constant.value.str.val);
01580        function_name->u.constant.value.str.val = lcname;
01581        
01582        zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *));
01583        zend_do_extended_fcall_begin(TSRMLS_C);
01584        return 0;
01585 }
01586 /* }}} */
01587 
01588 void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
01589 {
01590        zend_op *last_op;
01591        int last_op_number;
01592        unsigned char *ptr = NULL;
01593 
01594        zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
01595        zend_do_begin_variable_parse(TSRMLS_C);
01596 
01597        last_op_number = get_next_op_number(CG(active_op_array))-1;
01598        last_op = &CG(active_op_array)->opcodes[last_op_number];
01599 
01600        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)
01601               && !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)) {
01602               zend_error(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
01603        }
01604 
01605        if (last_op->opcode == ZEND_FETCH_OBJ_R) {
01606               last_op->opcode = ZEND_INIT_METHOD_CALL;
01607               SET_UNUSED(last_op->result);
01608               Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
01609        } else {
01610               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01611               opline->opcode = ZEND_INIT_FCALL_BY_NAME;
01612               opline->op2 = *left_bracket;
01613               if (opline->op2.op_type == IS_CONST) {
01614                      opline->op1.op_type = IS_CONST;
01615                      Z_TYPE(opline->op1.u.constant) = IS_STRING;
01616                      Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
01617                      Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
01618                      opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
01619               } else {
01620                      opline->extended_value = 0;
01621                      SET_UNUSED(opline->op1);
01622               }
01623        }
01624 
01625        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
01626        zend_do_extended_fcall_begin(TSRMLS_C);
01627 }
01628 /* }}} */
01629 
01630 void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
01631 {
01632        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01633 
01634        opline->opcode = ZEND_CLONE;
01635        opline->op1 = *expr;
01636        SET_UNUSED(opline->op2);
01637        opline->result.op_type = IS_VAR;
01638        opline->result.u.var = get_temporary_variable(CG(active_op_array));
01639        *result = opline->result;
01640 }
01641 /* }}} */
01642 
01643 void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
01644 {
01645        unsigned char *ptr = NULL;
01646        zend_op *opline, *opline2;
01647 
01648        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01649        if (ns_call) {
01650               char *slash;
01651               int prefix_len, name_len;
01652               /* In run-time PHP will check for function with full name and
01653                  internal function with short name */
01654               opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
01655               opline->op2 = *function_name;
01656               opline->extended_value = 0;
01657               opline->op1.op_type = IS_CONST;
01658               Z_TYPE(opline->op1.u.constant) = IS_STRING;
01659               Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
01660               Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
01661               opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
01662               slash = zend_memrchr(Z_STRVAL(opline->op1.u.constant), '\\', Z_STRLEN(opline->op1.u.constant));
01663               prefix_len = slash-Z_STRVAL(opline->op1.u.constant)+1;
01664               name_len = Z_STRLEN(opline->op1.u.constant)-prefix_len;
01665               opline2 = get_next_op(CG(active_op_array) TSRMLS_CC);
01666               opline2->opcode = ZEND_OP_DATA;
01667               opline2->op1.op_type = IS_CONST;
01668               Z_TYPE(opline2->op1.u.constant) = IS_LONG;
01669               if(!slash) {
01670                      zend_error(E_CORE_ERROR, "Namespaced name %s should contain slash", Z_STRVAL(opline->op1.u.constant));
01671               }
01672               /* this is the length of namespace prefix */
01673               Z_LVAL(opline2->op1.u.constant) = prefix_len;
01674               /* this is the hash of the non-prefixed part, lowercased */
01675               opline2->extended_value = zend_hash_func(slash+1, name_len+1);
01676               SET_UNUSED(opline2->op2);
01677        } else {
01678               opline->opcode = ZEND_INIT_FCALL_BY_NAME;
01679               opline->op2 = *function_name;
01680               if (opline->op2.op_type == IS_CONST) {
01681                      opline->op1.op_type = IS_CONST;
01682                      Z_TYPE(opline->op1.u.constant) = IS_STRING;
01683                      Z_STRVAL(opline->op1.u.constant) = zend_str_tolower_dup(Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant));
01684                      Z_STRLEN(opline->op1.u.constant) = Z_STRLEN(opline->op2.u.constant);
01685                      opline->extended_value = zend_hash_func(Z_STRVAL(opline->op1.u.constant), Z_STRLEN(opline->op1.u.constant) + 1);
01686               } else {
01687                      opline->extended_value = 0;
01688                      SET_UNUSED(opline->op1);
01689               }
01690        }
01691 
01692        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
01693        zend_do_extended_fcall_begin(TSRMLS_C);
01694 }
01695 /* }}} */
01696 
01697 void zend_resolve_non_class_name(znode *element_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
01698 {
01699        znode tmp;
01700        int len;
01701        zval **ns;
01702        char *lcname, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
01703 
01704        if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
01705               /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
01706               memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
01707               --Z_STRLEN(element_name->u.constant);
01708               return;
01709        }
01710 
01711        if(!check_namespace) {
01712               return;
01713        }
01714 
01715        if (compound && CG(current_import)) {
01716               len = compound - Z_STRVAL(element_name->u.constant);
01717               lcname = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
01718               /* Check if first part of compound name is an import name */
01719               if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
01720                      /* Substitute import name */
01721                      tmp.op_type = IS_CONST;
01722                      tmp.u.constant = **ns;
01723                      zval_copy_ctor(&tmp.u.constant);
01724                      len += 1;
01725                      Z_STRLEN(element_name->u.constant) -= len;
01726                      memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
01727                      zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
01728                      *element_name = tmp;
01729                      efree(lcname);
01730                      return;
01731               }
01732               efree(lcname);
01733        }
01734 
01735        if (CG(current_namespace)) {
01736               tmp = *element_name;
01737               Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
01738               Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
01739               memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
01740               memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace))]), "\\", sizeof("\\")-1);
01741               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);
01742               STR_FREE(Z_STRVAL(element_name->u.constant));
01743               *element_name = tmp;
01744        }
01745 }
01746 /* }}} */
01747 
01748 void zend_resolve_class_name(znode *class_name, ulong *fetch_type, int check_ns_name TSRMLS_DC) /* {{{ */
01749 {
01750        char *compound;
01751        char *lcname;
01752        zval **ns;
01753        znode tmp;
01754        int len;
01755 
01756        compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
01757        if (compound) {
01758               /* This is a compound class name that contains namespace prefix */
01759               if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
01760                   /* The STRING name has "\" prefix */
01761                   Z_STRLEN(class_name->u.constant) -= 1;
01762                   memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
01763                      Z_STRVAL(class_name->u.constant) = erealloc(
01764                             Z_STRVAL(class_name->u.constant),
01765                             Z_STRLEN(class_name->u.constant) + 1);
01766 
01767                      if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
01768                             zend_error(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
01769                      }
01770               } else { 
01771                      if (CG(current_import)) {
01772                             len = compound - Z_STRVAL(class_name->u.constant);
01773                             lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
01774                             /* Check if first part of compound name is an import name */
01775                             if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
01776                                    /* Substitute import name */
01777                                    tmp.op_type = IS_CONST;
01778                                    tmp.u.constant = **ns;
01779                                    zval_copy_ctor(&tmp.u.constant);
01780                                    len += 1;
01781                                    Z_STRLEN(class_name->u.constant) -= len;
01782                                    memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
01783                                    zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
01784                                    *class_name = tmp;
01785                                    efree(lcname);
01786                                    return;
01787                             }
01788                             efree(lcname);
01789                      }
01790                      /* Here name is not prefixed with \ and not imported */
01791                      if (CG(current_namespace)) {
01792                             tmp.op_type = IS_CONST;
01793                             tmp.u.constant = *CG(current_namespace);
01794                             zval_copy_ctor(&tmp.u.constant);
01795                             zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
01796                             *class_name = tmp;
01797                      }
01798               }
01799        } else if (CG(current_import) || CG(current_namespace)) {
01800               /* this is a plain name (without \) */
01801               lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
01802 
01803               if (CG(current_import) &&
01804                   zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
01805                   /* The given name is an import name. Substitute it. */
01806                      zval_dtor(&class_name->u.constant);
01807                      class_name->u.constant = **ns;
01808                      zval_copy_ctor(&class_name->u.constant);
01809               } else if (CG(current_namespace)) {
01810                      /* plain name, no import - prepend current namespace to it */
01811                      tmp.op_type = IS_CONST;
01812                      tmp.u.constant = *CG(current_namespace);
01813                      zval_copy_ctor(&tmp.u.constant);
01814                      zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
01815                      *class_name = tmp;
01816               }
01817               efree(lcname);
01818        }
01819 }
01820 /* }}} */
01821 
01822 void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
01823 {
01824        long fetch_class_op_number;
01825        zend_op *opline;
01826 
01827        if (class_name->op_type == IS_CONST &&
01828            Z_TYPE(class_name->u.constant) == IS_STRING &&
01829            Z_STRLEN(class_name->u.constant) == 0) {
01830               /* Usage of namespace as class name not in namespace */
01831               zval_dtor(&class_name->u.constant);
01832               zend_error(E_COMPILE_ERROR, "Cannot use 'namespace' as a class name");
01833               return;
01834        }
01835 
01836        fetch_class_op_number = get_next_op_number(CG(active_op_array));
01837        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01838 
01839        opline->opcode = ZEND_FETCH_CLASS;
01840        SET_UNUSED(opline->op1);
01841        opline->extended_value = ZEND_FETCH_CLASS_GLOBAL;
01842        CG(catch_begin) = fetch_class_op_number;
01843        if (class_name->op_type == IS_CONST) {
01844               int fetch_type;
01845 
01846               fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
01847               switch (fetch_type) {
01848                      case ZEND_FETCH_CLASS_SELF:
01849                      case ZEND_FETCH_CLASS_PARENT:
01850                      case ZEND_FETCH_CLASS_STATIC:
01851                             SET_UNUSED(opline->op2);
01852                             opline->extended_value = fetch_type;
01853                             zval_dtor(&class_name->u.constant);
01854                             break;
01855                      default:
01856                             zend_resolve_class_name(class_name, &opline->extended_value, 0 TSRMLS_CC);
01857                             opline->op2 = *class_name;
01858                             break;
01859               }
01860        } else {
01861               opline->op2 = *class_name;
01862        }
01863        opline->result.u.var = get_temporary_variable(CG(active_op_array));
01864        opline->result.u.EA.type = opline->extended_value;
01865        opline->result.op_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
01866        *result = opline->result;
01867 }
01868 /* }}} */
01869 
01870 void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
01871 {
01872        zend_op_array *oparray = CG(active_op_array);
01873        zend_label dest;
01874 
01875        if (!CG(labels)) {
01876               ALLOC_HASHTABLE(CG(labels));
01877               zend_hash_init(CG(labels), 4, NULL, NULL, 0);
01878        }
01879 
01880        dest.brk_cont = oparray->current_brk_cont;
01881        dest.opline_num = get_next_op_number(oparray);
01882 
01883        if (zend_hash_add(CG(labels), Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
01884               zend_error(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
01885        }
01886 
01887        /* Done with label now */
01888        zval_dtor(&label->u.constant);
01889 }
01890 /* }}} */
01891 
01892 void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
01893 {
01894        zend_label *dest;
01895        long current, distance;
01896 
01897        if (CG(labels) == NULL ||
01898               zend_hash_find(CG(labels), Z_STRVAL(opline->op2.u.constant), Z_STRLEN(opline->op2.u.constant)+1, (void**)&dest) == FAILURE) {
01899 
01900               if (pass2) {
01901                      CG(in_compilation) = 1;
01902                      CG(active_op_array) = op_array;
01903                      CG(zend_lineno) = opline->lineno;
01904                      zend_error(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL(opline->op2.u.constant));
01905               } else {
01906                      /* Label is not defined. Delay to pass 2. */
01907                      INC_BPC(op_array);
01908                      return;
01909               }
01910        }
01911 
01912        opline->op1.u.opline_num = dest->opline_num;
01913        zval_dtor(&opline->op2.u.constant);
01914 
01915        /* Check that we are not moving into loop or switch */
01916        current = opline->extended_value;
01917        for (distance = 0; current != dest->brk_cont; distance++) {
01918               if (current == -1) {
01919                      if (pass2) {
01920                             CG(in_compilation) = 1;
01921                             CG(active_op_array) = op_array;
01922                             CG(zend_lineno) = opline->lineno;
01923                      }
01924                      zend_error(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
01925               }
01926               current = op_array->brk_cont_array[current].parent;
01927        }
01928 
01929        if (distance == 0) {
01930               /* Nothing to break out of, optimize to ZEND_JMP */
01931               opline->opcode = ZEND_JMP;
01932               opline->extended_value = 0;
01933               SET_UNUSED(opline->op2);
01934        } else {
01935               /* Set real break distance */
01936               ZVAL_LONG(&opline->op2.u.constant, distance);
01937        }
01938 
01939        if (pass2) {
01940               DEC_BPC(op_array);
01941        }
01942 }
01943 /* }}} */
01944 
01945 void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
01946 {
01947        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
01948 
01949        opline->opcode = ZEND_GOTO;
01950        opline->extended_value = CG(active_op_array)->current_brk_cont;
01951        SET_UNUSED(opline->op1);
01952        opline->op2 = *label;
01953        zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
01954 }
01955 /* }}} */
01956 
01957 void zend_release_labels(TSRMLS_D) /* {{{ */
01958 {
01959        if (CG(labels)) {
01960               zend_hash_destroy(CG(labels));
01961               FREE_HASHTABLE(CG(labels));
01962        }
01963        if (!zend_stack_is_empty(&CG(labels_stack))) {
01964               HashTable **pht;
01965 
01966               zend_stack_top(&CG(labels_stack), (void**)&pht);
01967               CG(labels) = *pht;
01968               zend_stack_del_top(&CG(labels_stack));
01969        } else {
01970               CG(labels) = NULL;
01971        }
01972 }
01973 /* }}} */
01974 
01975 void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
01976 {
01977        zend_uint length;
01978 
01979        if (!result) {
01980               result = prefix;
01981        } else {
01982               *result = *prefix;
01983        }
01984 
01985        if (is_class_member) {
01986               length = sizeof("::")-1 + result->u.constant.value.str.len + name->u.constant.value.str.len;
01987               result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
01988               memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
01989               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);
01990               STR_FREE(name->u.constant.value.str.val);
01991               result->u.constant.value.str.len = length;
01992        } else {
01993               length = sizeof("\\")-1 + result->u.constant.value.str.len + name->u.constant.value.str.len;
01994               result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
01995               memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "\\", sizeof("\\")-1);
01996               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);
01997               STR_FREE(name->u.constant.value.str.val);
01998               result->u.constant.value.str.len = length;
01999        }
02000 }
02001 /* }}} */
02002 
02003 int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
02004 {
02005        znode class_node;
02006        unsigned char *ptr = NULL;
02007        zend_op *opline;
02008        ulong fetch_type = 0;
02009 
02010        if (method_name->op_type == IS_CONST) {
02011               char *lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
02012               if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
02013                      memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
02014                      zval_dtor(&method_name->u.constant);
02015                      SET_UNUSED(*method_name);
02016               }
02017               efree(lcname);
02018        }
02019 
02020        if (class_name->op_type == IS_CONST &&
02021                      ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
02022               fetch_type = ZEND_FETCH_CLASS_GLOBAL;
02023               zend_resolve_class_name(class_name, &fetch_type, 1 TSRMLS_CC);
02024               class_node = *class_name;
02025        } else {
02026               zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
02027        }
02028        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02029        opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
02030        opline->op1 = class_node;
02031        opline->op2 = *method_name;
02032 
02033        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
02034        zend_do_extended_fcall_begin(TSRMLS_C);
02035        return 1; /* Dynamic */
02036 }
02037 /* }}} */
02038 
02039 void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
02040 {
02041        zend_op *opline;
02042 
02043        if (is_method && function_name && function_name->op_type == IS_UNUSED) {
02044               /* clone */
02045               if (Z_LVAL(argument_list->u.constant) != 0) {
02046                      zend_error(E_WARNING, "Clone method does not require arguments");
02047               }
02048               opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
02049        } else {
02050               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02051               if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
02052                      opline->opcode = ZEND_DO_FCALL;
02053                      opline->op1 = *function_name;
02054                      ZVAL_LONG(&opline->op2.u.constant, zend_hash_func(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant) + 1));
02055               } else {
02056                      opline->opcode = ZEND_DO_FCALL_BY_NAME;
02057                      SET_UNUSED(opline->op1);
02058               }
02059        }
02060 
02061        opline->result.u.var = get_temporary_variable(CG(active_op_array));
02062        opline->result.op_type = IS_VAR;
02063        *result = opline->result;
02064        SET_UNUSED(opline->op2);
02065 
02066        zend_stack_del_top(&CG(function_call_stack));
02067        opline->extended_value = Z_LVAL(argument_list->u.constant);
02068 }
02069 /* }}} */
02070 
02071 void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{{ */
02072 {
02073        zend_op *opline;
02074        int original_op=op;
02075        zend_function **function_ptr_ptr, *function_ptr;
02076        int send_by_reference;
02077        int send_function = 0;
02078 
02079        zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
02080        function_ptr = *function_ptr_ptr;
02081 
02082        if (original_op == ZEND_SEND_REF && !CG(allow_call_time_pass_reference)) {
02083               if (function_ptr &&
02084                             function_ptr->common.function_name &&
02085                             function_ptr->common.type == ZEND_USER_FUNCTION &&
02086                             !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
02087                      zend_error(E_DEPRECATED,
02088                                           "Call-time pass-by-reference has been deprecated; "
02089                                           "If you would like to pass it by reference, modify the declaration of %s().  "
02090                                           "If you would like to enable call-time pass-by-reference, you can set "
02091                                           "allow_call_time_pass_reference to true in your INI file", function_ptr->common.function_name);
02092               } else {
02093                      zend_error(E_DEPRECATED, "Call-time pass-by-reference has been deprecated");
02094               }
02095        }
02096 
02097        if (function_ptr) {
02098               if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
02099                      if (param->op_type & (IS_VAR|IS_CV)) {
02100                             send_by_reference = 1;
02101                             if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
02102                                    /* Method call */
02103                                    op = ZEND_SEND_VAR_NO_REF;
02104                                    send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
02105                             }
02106                      } else {
02107                             op = ZEND_SEND_VAL;
02108                             send_by_reference = 0;
02109                      }
02110               } else {
02111                      send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
02112               }
02113        } else {
02114               send_by_reference = 0;
02115        }
02116 
02117        if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
02118               /* Method call */
02119               op = ZEND_SEND_VAR_NO_REF;
02120               send_function = ZEND_ARG_SEND_FUNCTION;
02121        } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
02122               op = ZEND_SEND_VAR_NO_REF;
02123        }
02124 
02125        if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
02126               /* change to passing by reference */
02127               switch (param->op_type) {
02128                      case IS_VAR:
02129                      case IS_CV:
02130                             op = ZEND_SEND_REF;
02131                             break;
02132                      default:
02133                             zend_error(E_COMPILE_ERROR, "Only variables can be passed by reference");
02134                             break;
02135               }
02136        }
02137 
02138        if (original_op == ZEND_SEND_VAR) {
02139               switch (op) {
02140                      case ZEND_SEND_VAR_NO_REF:
02141                             zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
02142                             break;
02143                      case ZEND_SEND_VAR:
02144                             if (function_ptr) {
02145                                    zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
02146                             } else {
02147                                    zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
02148                             }
02149                             break;
02150                      case ZEND_SEND_REF:
02151                             zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
02152                             break;
02153               }
02154        }
02155 
02156        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02157 
02158        if (op == ZEND_SEND_VAR_NO_REF) {
02159               if (function_ptr) {
02160                      opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
02161               } else {
02162                      opline->extended_value = send_function;
02163               }
02164        } else {
02165               if (function_ptr) {
02166                      opline->extended_value = ZEND_DO_FCALL;
02167               } else {
02168                      opline->extended_value = ZEND_DO_FCALL_BY_NAME;
02169               }
02170        }
02171        opline->opcode = op;
02172        opline->op1 = *param;
02173        opline->op2.u.opline_num = offset;
02174        SET_UNUSED(opline->op2);
02175 }
02176 /* }}} */
02177 
02178 static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
02179 {
02180        zend_op *opline;
02181 
02182        if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
02183               return (switch_entry->cond.op_type == IS_UNUSED);
02184        }
02185 
02186        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02187 
02188        opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
02189        opline->op1 = switch_entry->cond;
02190        SET_UNUSED(opline->op2);
02191        opline->extended_value = 0;
02192        return 0;
02193 }
02194 /* }}} */
02195 
02196 static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
02197 {
02198        zend_op *opline;
02199 
02200        /* If we reach the seperator then stop applying the stack */
02201        if (foreach_copy->result.op_type == IS_UNUSED && foreach_copy->op1.op_type == IS_UNUSED) {
02202               return 1;
02203        }
02204 
02205        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02206 
02207        opline->opcode = (foreach_copy->result.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
02208        opline->op1 = foreach_copy->result;
02209        SET_UNUSED(opline->op2);
02210        opline->extended_value = 1;
02211 
02212        if (foreach_copy->op1.op_type != IS_UNUSED) {
02213               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02214 
02215               opline->opcode = (foreach_copy->op1.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
02216               opline->op1 = foreach_copy->op1;
02217               SET_UNUSED(opline->op2);
02218               opline->extended_value = 0;
02219        }
02220 
02221        return 0;
02222 }
02223 /* }}} */
02224 
02225 void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
02226 {
02227        zend_op *opline;
02228        int start_op_number, end_op_number;
02229 
02230        if (do_end_vparse) {
02231               if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
02232                      zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
02233               } else {
02234                      zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
02235               }
02236        }
02237 
02238        start_op_number = get_next_op_number(CG(active_op_array));
02239 
02240 #ifdef ZTS
02241        zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
02242        zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
02243 #else
02244        zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
02245        zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
02246 #endif
02247 
02248        end_op_number = get_next_op_number(CG(active_op_array));
02249        while (start_op_number < end_op_number) {
02250               CG(active_op_array)->opcodes[start_op_number].op1.u.EA.type = EXT_TYPE_FREE_ON_RETURN;
02251               start_op_number++;
02252        }
02253 
02254        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02255 
02256        opline->opcode = ZEND_RETURN;
02257 
02258        if (expr) {
02259               opline->op1 = *expr;
02260 
02261               if (do_end_vparse && zend_is_function_or_method_call(expr)) {
02262                      opline->extended_value = ZEND_RETURNS_FUNCTION;
02263               }
02264        } else {
02265               opline->op1.op_type = IS_CONST;
02266               INIT_ZVAL(opline->op1.u.constant);
02267        }
02268 
02269        SET_UNUSED(opline->op2);
02270 }
02271 /* }}} */
02272 
02273 static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
02274 {
02275        int try_catch_offset = CG(active_op_array)->last_try_catch++;
02276 
02277        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);
02278        CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
02279        return try_catch_offset;
02280 }
02281 /* }}} */
02282 
02283 static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
02284 {
02285        CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
02286 }
02287 /* }}} */
02288 
02289 void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
02290 {
02291        open_parentheses->u.opline_num = get_next_op_number(CG(active_op_array));
02292 }
02293 /* }}} */
02294 
02295 void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{ */
02296 {
02297        int jmp_op_number = get_next_op_number(CG(active_op_array));
02298        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02299        zend_llist jmp_list;
02300        zend_llist *jmp_list_ptr;
02301 
02302        opline->opcode = ZEND_JMP;
02303        SET_UNUSED(opline->op1);
02304        SET_UNUSED(opline->op2);
02305        /* save for backpatching */
02306 
02307        zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
02308        zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
02309        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
02310        zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
02311 
02312        zend_add_catch_element(try_token->u.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC);
02313 }
02314 /* }}} */
02315 
02316 void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
02317 {
02318        CG(active_op_array)->last--;
02319        zend_do_if_end(TSRMLS_C);
02320        if (last_additional_catch->u.opline_num == -1) {
02321               CG(active_op_array)->opcodes[first_catch->u.opline_num].op1.u.EA.type = 1;
02322               CG(active_op_array)->opcodes[first_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
02323        } else {
02324               CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].op1.u.EA.type = 1;
02325               CG(active_op_array)->opcodes[last_additional_catch->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
02326        }
02327        DEC_BPC(CG(active_op_array));
02328 }
02329 /* }}} */
02330 
02331 void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
02332 {
02333        try_token->u.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
02334        INC_BPC(CG(active_op_array));
02335 }
02336 /* }}} */
02337 
02338 void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
02339 {
02340        long catch_op_number;
02341        zend_op *opline;
02342        znode catch_class;
02343 
02344        zend_do_fetch_class(&catch_class, class_name TSRMLS_CC);
02345 
02346        catch_op_number = get_next_op_number(CG(active_op_array));
02347        if (catch_op_number > 0) {
02348               opline = &CG(active_op_array)->opcodes[catch_op_number-1];
02349               if (opline->opcode == ZEND_FETCH_CLASS) {
02350                      opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
02351               }
02352        }
02353 
02354        if (first_catch) {
02355               first_catch->u.opline_num = catch_op_number;
02356        }
02357 
02358        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02359        opline->opcode = ZEND_CATCH;
02360        opline->op1 = catch_class;
02361 /*     SET_UNUSED(opline->op1); */ /* FIXME: Define IS_CLASS or something like that */
02362        opline->op2.op_type = IS_CV;
02363        opline->op2.u.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len);
02364        opline->op2.u.EA.type = 0;
02365        opline->op1.u.EA.type = 0; /* 1 means it's the last catch in the block */
02366 
02367        try_token->u.opline_num = catch_op_number;
02368 }
02369 /* }}} */
02370 
02371 void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */
02372 {
02373        int jmp_op_number = get_next_op_number(CG(active_op_array));
02374        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02375        zend_llist *jmp_list_ptr;
02376 
02377        opline->opcode = ZEND_JMP;
02378        SET_UNUSED(opline->op1);
02379        SET_UNUSED(opline->op2);
02380        /* save for backpatching */
02381 
02382        zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
02383        zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
02384 
02385        CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
02386 }
02387 /* }}} */
02388 
02389 void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
02390 {
02391        zend_op *opline;
02392 
02393        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
02394        opline->opcode = ZEND_THROW;
02395        opline->op1 = *expr;
02396        SET_UNUSED(opline->op2);
02397 }
02398 /* }}} */
02399 
02400 ZEND_API void function_add_ref(zend_function *function) /* {{{ */
02401 {
02402        if (function->type == ZEND_USER_FUNCTION) {
02403               zend_op_array *op_array = &function->op_array;
02404 
02405               (*op_array->refcount)++;
02406               if (op_array->static_variables) {
02407                      HashTable *static_variables = op_array->static_variables;
02408                      zval *tmp_zval;
02409 
02410                      ALLOC_HASHTABLE(op_array->static_variables);
02411                      zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
02412                      zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
02413               }
02414        }
02415 }
02416 /* }}} */
02417 
02418 static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
02419 {
02420        zend_function *function;
02421 
02422        if (!ce->parent) {
02423               return;
02424        }
02425 
02426        /* You cannot change create_object */
02427        ce->create_object = ce->parent->create_object;
02428 
02429        /* Inherit special functions if needed */
02430        if (!ce->get_iterator) {
02431               ce->get_iterator = ce->parent->get_iterator;
02432        }
02433        if (!ce->iterator_funcs.funcs) {
02434               ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
02435        }
02436        if (!ce->__get) {
02437               ce->__get   = ce->parent->__get;
02438        }
02439        if (!ce->__set) {
02440               ce->__set = ce->parent->__set;
02441        }
02442        if (!ce->__unset) {
02443               ce->__unset = ce->parent->__unset;
02444        }
02445        if (!ce->__isset) {
02446               ce->__isset = ce->parent->__isset;
02447        }
02448        if (!ce->__call) {
02449               ce->__call = ce->parent->__call;
02450        }
02451        if (!ce->__callstatic) {
02452               ce->__callstatic = ce->parent->__callstatic;
02453        }
02454        if (!ce->__tostring) {
02455               ce->__tostring = ce->parent->__tostring;
02456        }
02457        if (!ce->clone) {
02458               ce->clone = ce->parent->clone;
02459        }
02460        if(!ce->serialize) {
02461               ce->serialize = ce->parent->serialize;
02462        }
02463        if(!ce->unserialize) {
02464               ce->unserialize = ce->parent->unserialize;
02465        }
02466        if (!ce->destructor) {
02467               ce->destructor   = ce->parent->destructor;
02468        }
02469        if (ce->constructor) {
02470               if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
02471                      zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
02472                             ce->parent->name, ce->parent->constructor->common.function_name,
02473                             ce->name, ce->constructor->common.function_name
02474                             );
02475               }
02476               return;
02477        }
02478 
02479        if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
02480               /* inherit parent's constructor */
02481               zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL);
02482               function_add_ref(function);
02483        } else {
02484               /* Don't inherit the old style constructor if we already have the new style constructor */
02485               char *lc_class_name;
02486               char *lc_parent_class_name;
02487 
02488               lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
02489               if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
02490                      lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
02491                      if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) && 
02492                                    zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
02493                             if (function->common.fn_flags & ZEND_ACC_CTOR) {
02494                                    /* inherit parent's constructor */
02495                                    zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), NULL);
02496                                    function_add_ref(function);
02497                             }
02498                      }
02499                      efree(lc_parent_class_name);
02500               }
02501               efree(lc_class_name);
02502        }
02503        ce->constructor = ce->parent->constructor;
02504 }
02505 /* }}} */
02506 
02507 char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
02508 {
02509        if (fn_flags & ZEND_ACC_PRIVATE) {
02510               return "private";
02511        }
02512        if (fn_flags & ZEND_ACC_PROTECTED) {
02513               return "protected";
02514        }
02515        if (fn_flags & ZEND_ACC_PUBLIC) {
02516               return "public";
02517        }
02518        return "";
02519 }
02520 /* }}} */
02521 
02522 static void do_inherit_method(zend_function *function) /* {{{ */
02523 {
02524        /* The class entry of the derived function intentionally remains the same
02525         * as that of the parent class.  That allows us to know in which context
02526         * we're running, and handle private method calls properly.
02527         */
02528        function_add_ref(function);
02529 }
02530 /* }}} */
02531 
02532 static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
02533 {
02534        zend_uint i;
02535 
02536        /* If it's a user function then arg_info == NULL means we don't have any parameters but
02537         * we still need to do the arg number checks.  We are only willing to ignore this for internal
02538         * functions because extensions don't always define arg_info.
02539         */
02540        if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
02541               return 1;
02542        }
02543 
02544        /* Checks for constructors only if they are declared in an interface */
02545        if ((fe->common.fn_flags & ZEND_ACC_CTOR) && (proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0) {
02546               return 1;
02547        }
02548 
02549        /* check number of arguments */
02550        if (proto->common.required_num_args < fe->common.required_num_args
02551               || proto->common.num_args > fe->common.num_args) {
02552               return 0;
02553        }
02554 
02555        if (fe->common.type != ZEND_USER_FUNCTION
02556               && proto->common.pass_rest_by_reference
02557               && !fe->common.pass_rest_by_reference) {
02558               return 0;
02559        }
02560 
02561        /* by-ref constraints on return values are covariant */
02562        if (proto->common.return_reference && !fe->common.return_reference) {
02563               return 0;
02564        }
02565 
02566        for (i=0; i < proto->common.num_args; i++) {
02567               if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)) {
02568                      /* Only one has a type hint and the other one doesn't */
02569                      return 0;
02570               }
02571               if (fe->common.arg_info[i].class_name
02572                      && strcasecmp(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)!=0) {
02573                      char *colon;
02574 
02575                      if (fe->common.type != ZEND_USER_FUNCTION) {
02576                             return 0;
02577                      } else if (strchr(proto->common.arg_info[i].class_name, '\\') != NULL ||
02578                          (colon = zend_memrchr(fe->common.arg_info[i].class_name, '\\', fe->common.arg_info[i].class_name_len)) == NULL ||
02579                          strcasecmp(colon+1, proto->common.arg_info[i].class_name) != 0) {
02580                             zend_class_entry **fe_ce, **proto_ce;
02581                             int found, found2;
02582                             
02583                             found = zend_lookup_class(fe->common.arg_info[i].class_name, fe->common.arg_info[i].class_name_len, &fe_ce TSRMLS_CC);
02584                             found2 = zend_lookup_class(proto->common.arg_info[i].class_name, proto->common.arg_info[i].class_name_len, &proto_ce TSRMLS_CC);
02585                             
02586                             /* Check for class alias */
02587                             if (found != SUCCESS || found2 != SUCCESS ||
02588                                    (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
02589                                    (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
02590                                    *fe_ce != *proto_ce) {
02591                                    return 0;
02592                             }
02593                      }
02594               }
02595               if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) {
02596                      /* Only one has an array type hint and the other one doesn't */
02597                      return 0;
02598               }
02599 
02600               /* by-ref constraints on arguments are invariant */
02601               if (fe->common.arg_info[i].pass_by_reference != proto->common.arg_info[i].pass_by_reference) {
02602                      return 0;
02603               }
02604        }
02605 
02606        if (proto->common.pass_rest_by_reference) {
02607               for (i=proto->common.num_args; i < fe->common.num_args; i++) {
02608                      if (!fe->common.arg_info[i].pass_by_reference) {
02609                             return 0;
02610                      }
02611               }
02612        }
02613        return 1;
02614 }
02615 /* }}} */
02616 
02617 static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
02618 {
02619        zend_uint child_flags;
02620        zend_uint parent_flags = parent->common.fn_flags;
02621        zend_function *child;
02622        TSRMLS_FETCH();
02623 
02624        if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
02625               if (parent_flags & (ZEND_ACC_ABSTRACT)) {
02626                      child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
02627               }
02628               return 1; /* method doesn't exist in child, copy from parent */
02629        }
02630 
02631        if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
02632               && parent->common.fn_flags & ZEND_ACC_ABSTRACT
02633               && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
02634               && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
02635               zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)", 
02636                      parent->common.scope->name,
02637                      child->common.function_name,
02638                      child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
02639        }
02640 
02641        if (parent_flags & ZEND_ACC_FINAL) {
02642               zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
02643        }
02644 
02645        child_flags   = child->common.fn_flags;
02646        /* You cannot change from static to non static and vice versa.
02647         */
02648        if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
02649               if (child->common.fn_flags & ZEND_ACC_STATIC) {
02650                      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));
02651               } else {
02652                      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));
02653               }
02654        }
02655 
02656        /* Disallow making an inherited method abstract. */
02657        if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
02658               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));
02659        }
02660 
02661        if (parent_flags & ZEND_ACC_CHANGED) {
02662               child->common.fn_flags |= ZEND_ACC_CHANGED;
02663        } else {
02664               /* Prevent derived classes from restricting access that was available in parent classes
02665                */
02666               if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
02667                      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");
02668               } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
02669                      && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
02670                      child->common.fn_flags |= ZEND_ACC_CHANGED;
02671               }
02672        }
02673 
02674        if (parent_flags & ZEND_ACC_PRIVATE) {
02675               child->common.prototype = NULL;           
02676        } else if (parent_flags & ZEND_ACC_ABSTRACT) {
02677               child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
02678               child->common.prototype = parent;
02679        } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
02680               /* ctors only have a prototype if it comes from an interface */
02681               child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
02682        }
02683 
02684        if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
02685               if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
02686                      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);
02687               }
02688        } 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 */
02689               if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
02690                      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);
02691               }
02692        }
02693 
02694        return 0;
02695 }
02696 /* }}} */
02697 
02698 static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce) /* {{{ */
02699 {
02700        zend_property_info *child_info;
02701        zend_class_entry *parent_ce = ce->parent;
02702 
02703        if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
02704               if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
02705                      child_info->flags |= ZEND_ACC_CHANGED;
02706               } else {
02707                      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);
02708                      if(ce->type & ZEND_INTERNAL_CLASS) {
02709                             zend_duplicate_property_info_internal(child_info);
02710                      } else {
02711                             zend_duplicate_property_info(child_info);
02712                      }
02713                      child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
02714                      child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
02715               }
02716               return 0; /* don't copy access information to child */
02717        }
02718 
02719        if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
02720               if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
02721                      zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
02722                             (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
02723                             (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
02724                             
02725               }
02726 
02727               if(parent_info->flags & ZEND_ACC_CHANGED) {
02728                      child_info->flags |= ZEND_ACC_CHANGED;
02729               }
02730 
02731               if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
02732                      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");
02733               } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
02734                      if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
02735                             /* Explicitly copy the default value from the parent (if it has one) */
02736                             zval **pvalue;
02737        
02738                             if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
02739                                    Z_ADDREF_PP(pvalue);
02740                                    zend_hash_quick_del(&ce->default_properties, child_info->name, child_info->name_length+1, parent_info->h);
02741                                    zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
02742                             }
02743                      }
02744                      return 1; /* Inherit from the parent */
02745               } else if ((child_info->flags & ZEND_ACC_PUBLIC) && (parent_info->flags & ZEND_ACC_PROTECTED)) {
02746                      char *prot_name;
02747                      int prot_name_length;
02748 
02749                      zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
02750                      if (child_info->flags & ZEND_ACC_STATIC) {
02751                             zval **prop;
02752                             HashTable *ht;
02753 
02754                             if (parent_ce->type != ce->type) {
02755                                    /* User class extends internal class */
02756                                    TSRMLS_FETCH();
02757 
02758                                    ht = CE_STATIC_MEMBERS(parent_ce);
02759                             } else {
02760                                    ht = &parent_ce->default_static_members;
02761                             }
02762                             if (zend_hash_find(ht, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
02763                                    zend_hash_del(&ce->default_static_members, prot_name, prot_name_length+1);
02764                             }
02765                      } else {
02766                             zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
02767                      }
02768                      pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
02769               }
02770               return 0;     /* Don't copy from parent */
02771        } else {
02772               return 1;     /* Copy from parent */
02773        }
02774 }
02775 /* }}} */
02776 
02777 static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
02778 {
02779        if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
02780               zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
02781        }
02782        if (ce == iface) {
02783               zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
02784        }
02785 }
02786 /* }}} */
02787 
02788 ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
02789 {
02790        /* expects interface to be contained in ce's interface list already */
02791        zend_uint i, ce_num, if_num = iface->num_interfaces;
02792        zend_class_entry *entry;
02793 
02794        if (if_num==0) {
02795               return;
02796        }
02797        ce_num = ce->num_interfaces;
02798 
02799        if (ce->type == ZEND_INTERNAL_CLASS) {
02800               ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
02801        } else {
02802               ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
02803        }
02804 
02805        /* Inherit the interfaces, only if they're not already inherited by the class */
02806        while (if_num--) {
02807               entry = iface->interfaces[if_num];
02808               for (i = 0; i < ce_num; i++) {
02809                      if (ce->interfaces[i] == entry) {
02810                             break;
02811                      }
02812               }
02813               if (i == ce_num) {
02814                      ce->interfaces[ce->num_interfaces++] = entry;
02815               }
02816        }
02817 
02818        /* and now call the implementing handlers */
02819        while (ce_num < ce->num_interfaces) {
02820               do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
02821        }
02822 }
02823 /* }}} */
02824 
02825 static int inherit_static_prop(zval **p TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
02826 {
02827        HashTable *target = va_arg(args, HashTable*);
02828 
02829        if (!zend_hash_quick_exists(target, key->arKey, key->nKeyLength, key->h)) {
02830               SEPARATE_ZVAL_TO_MAKE_IS_REF(p);
02831               if (zend_hash_quick_add(target, key->arKey, key->nKeyLength, key->h, p, sizeof(zval*), NULL) == SUCCESS) {
02832                      Z_ADDREF_PP(p);
02833               }
02834        }
02835        return ZEND_HASH_APPLY_KEEP;
02836 }
02837 /* }}} */
02838 
02839 #define zval_property_ctor(parent_ce, ce) \
02840        ((copy_ctor_func_t) (((parent_ce)->type != (ce)->type) ? zval_shared_property_ctor : zval_add_ref))
02841 
02842 ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
02843 {
02844        if ((ce->ce_flags & ZEND_ACC_INTERFACE)
02845               && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
02846               zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
02847        }
02848        if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
02849               zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
02850        }
02851 
02852        ce->parent = parent_ce;
02853        /* Copy serialize/unserialize callbacks */
02854        if (!ce->serialize) {
02855               ce->serialize   = parent_ce->serialize;
02856        }
02857        if (!ce->unserialize) {
02858               ce->unserialize = parent_ce->unserialize;
02859        }
02860 
02861        /* Inherit interfaces */
02862        zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
02863 
02864        /* Inherit properties */
02865        zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
02866        if (parent_ce->type != ce->type) {
02867               /* User class extends internal class */
02868               zend_update_class_constants(parent_ce  TSRMLS_CC);
02869               zend_hash_apply_with_arguments(CE_STATIC_MEMBERS(parent_ce) TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
02870        } else {
02871               zend_hash_apply_with_arguments(&parent_ce->default_static_members TSRMLS_CC, (apply_func_args_t)inherit_static_prop, 1, &ce->default_static_members);
02872        }
02873        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);
02874 
02875        zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
02876        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);
02877        do_inherit_parent_constructor(ce);
02878 
02879        if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
02880               ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
02881        } else if (!(ce->ce_flags & ZEND_ACC_IMPLEMENT_INTERFACES)) {
02882               /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
02883               zend_verify_abstract_class(ce TSRMLS_CC);
02884        }
02885 }
02886 /* }}} */
02887 
02888 static zend_bool do_inherit_constant_check(HashTable *child_constants_table, const zval **parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface) /* {{{ */
02889 {
02890        zval **old_constant;
02891 
02892        if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
02893               if (*old_constant != *parent_constant) {
02894                      zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
02895               }
02896               return 0;
02897        }
02898        return 1;
02899 }
02900 /* }}} */
02901 
02902 static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
02903 {
02904        zend_class_entry **iface = va_arg(args, zend_class_entry**);
02905 
02906        do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
02907 
02908        return ZEND_HASH_APPLY_KEEP;
02909 }
02910 /* }}} */
02911 
02912 ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
02913 {
02914        zend_uint i, ignore = 0;
02915        zend_uint current_iface_num = ce->num_interfaces;
02916        zend_uint parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
02917 
02918        for (i = 0; i < ce->num_interfaces; i++) {
02919               if (ce->interfaces[i] == NULL) {
02920                      memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
02921                      i--;
02922               } else if (ce->interfaces[i] == iface) {
02923                      if (i < parent_iface_num) {
02924                             ignore = 1;
02925                      } else {
02926                             zend_error(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
02927                      }
02928               }
02929        }
02930        if (ignore) {
02931               /* Check for attempt to redeclare interface constants */
02932               zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
02933        } else {
02934               if (ce->num_interfaces >= current_iface_num) {
02935                      if (ce->type == ZEND_INTERNAL_CLASS) {
02936                             ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
02937                      } else {
02938                             ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
02939                      }
02940               }
02941               ce->interfaces[ce->num_interfaces++] = iface;
02942        
02943               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);
02944               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);
02945        
02946               do_implement_interface(ce, iface TSRMLS_CC);
02947               zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
02948        }
02949 }
02950 /* }}} */
02951 
02952 ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
02953 {
02954        zend_function *function;
02955 
02956        zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
02957        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) {
02958               int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
02959               zend_function *old_function;
02960 
02961               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
02962                      && old_function->type == ZEND_USER_FUNCTION
02963                      && old_function->op_array.last > 0) {
02964                      zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
02965                                           function->common.function_name,
02966                                           old_function->op_array.filename,
02967                                           old_function->op_array.opcodes[0].lineno);
02968               } else {
02969                      zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
02970               }
02971               return FAILURE;
02972        } else {
02973               (*function->op_array.refcount)++;
02974               function->op_array.static_variables = NULL; /* NULL out the unbound function */
02975               return SUCCESS;
02976        }
02977 }
02978 /* }}} */
02979 
02980 ZEND_API zend_class_entry *do_bind_class(const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
02981 {
02982        zend_class_entry *ce, **pce;
02983 
02984        if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
02985               zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
02986               return NULL;
02987        } else {
02988               ce = *pce;
02989        }
02990        ce->refcount++;
02991        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) {
02992               ce->refcount--;
02993               if (!compile_time) {
02994                      /* If we're in compile time, in practice, it's quite possible
02995                       * that we'll never reach this class declaration at runtime,
02996                       * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
02997                       * approach to work.
02998                       */
02999                      zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
03000               }
03001               return NULL;
03002        } else {
03003               if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES))) {
03004                      zend_verify_abstract_class(ce TSRMLS_CC);
03005               }
03006               return ce;
03007        }
03008 }
03009 /* }}} */
03010 
03011 ZEND_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) /* {{{ */
03012 {
03013        zend_class_entry *ce, **pce;
03014        int found_ce;
03015 
03016        found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
03017 
03018        if (found_ce == FAILURE) {
03019               if (!compile_time) {
03020                      /* If we're in compile time, in practice, it's quite possible
03021                       * that we'll never reach this class declaration at runtime,
03022                       * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
03023                       * approach to work.
03024                       */
03025                      zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
03026               }
03027               return NULL;
03028        } else {
03029               ce = *pce;
03030        }
03031 
03032        if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
03033               zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
03034        }
03035 
03036        zend_do_inheritance(ce, parent_ce TSRMLS_CC);
03037 
03038        ce->refcount++;
03039 
03040        /* Register the derived class */
03041        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) {
03042               zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
03043        }
03044        return ce;
03045 }
03046 /* }}} */
03047 
03048 void zend_do_early_binding(TSRMLS_D) /* {{{ */
03049 {
03050        zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
03051        HashTable *table;
03052 
03053        while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
03054               opline--;
03055        }
03056 
03057        switch (opline->opcode) {
03058               case ZEND_DECLARE_FUNCTION:
03059                      if (do_bind_function(opline, CG(function_table), 1) == FAILURE) {
03060                             return;
03061                      }
03062                      table = CG(function_table);
03063                      break;
03064               case ZEND_DECLARE_CLASS:
03065                      if (do_bind_class(opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
03066                             return;
03067                      }
03068                      table = CG(class_table);
03069                      break;
03070               case ZEND_DECLARE_INHERITED_CLASS:
03071                      {
03072                             zend_op *fetch_class_opline = opline-1;
03073                             zval *parent_name = &fetch_class_opline->op2.u.constant;
03074                             zend_class_entry **pce;
03075 
03076                             if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
03077                                           ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
03078                                           ((*pce)->type == ZEND_INTERNAL_CLASS))) {
03079                                    if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
03080                                           zend_uint *opline_num = &CG(active_op_array)->early_binding;
03081 
03082                                           while (*opline_num != -1) {
03083                                                  opline_num = &CG(active_op_array)->opcodes[*opline_num].result.u.opline_num;
03084                                           }
03085                                           *opline_num = opline - CG(active_op_array)->opcodes;
03086                                           opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
03087                                           opline->result.op_type = IS_UNUSED;
03088                                           opline->result.u.opline_num = -1;
03089                                    }
03090                                    return;
03091                             }
03092                             if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
03093                                    return;
03094                             }
03095                             /* clear unnecessary ZEND_FETCH_CLASS opcode */
03096                             zval_dtor(&fetch_class_opline->op2.u.constant);
03097                             MAKE_NOP(fetch_class_opline);
03098 
03099                             table = CG(class_table);
03100                             break;
03101                      }
03102               case ZEND_VERIFY_ABSTRACT_CLASS:
03103               case ZEND_ADD_INTERFACE:
03104                      /* We currently don't early-bind classes that implement interfaces */
03105                      return;
03106               default:
03107                      zend_error(E_COMPILE_ERROR, "Invalid binding type");
03108                      return;
03109        }
03110 
03111        zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
03112        zval_dtor(&opline->op1.u.constant);
03113        zval_dtor(&opline->op2.u.constant);
03114        MAKE_NOP(opline);
03115 }
03116 /* }}} */
03117 
03118 ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
03119 {
03120        if (op_array->early_binding != -1) {
03121               zend_bool orig_in_compilation = CG(in_compilation);
03122               zend_uint opline_num = op_array->early_binding;
03123               zend_class_entry **pce;
03124 
03125               CG(in_compilation) = 1;
03126               while (opline_num != -1) {
03127                      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) {
03128                             do_bind_inherited_class(&op_array->opcodes[opline_num], EG(class_table), *pce, 1 TSRMLS_CC);
03129                      }
03130                      opline_num = op_array->opcodes[opline_num].result.u.opline_num;
03131               }
03132               CG(in_compilation) = orig_in_compilation;
03133        }
03134 }
03135 /* }}} */
03136 
03137 void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
03138 {
03139        int next_op_number = get_next_op_number(CG(active_op_array));
03140        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03141 
03142        opline->opcode = ZEND_JMPNZ_EX;
03143        if (expr1->op_type == IS_TMP_VAR) {
03144               opline->result = *expr1;
03145        } else {
03146               opline->result.u.var = get_temporary_variable(CG(active_op_array));
03147               opline->result.op_type = IS_TMP_VAR;
03148        }
03149        opline->op1 = *expr1;
03150        SET_UNUSED(opline->op2);
03151 
03152        op_token->u.opline_num = next_op_number;
03153 
03154        *expr1 = opline->result;
03155 }
03156 /* }}} */
03157 
03158 void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
03159 {
03160        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03161 
03162        *result = *expr1; /* we saved the original result in expr1 */
03163        opline->opcode = ZEND_BOOL;
03164        opline->result = *result;
03165        opline->op1 = *expr2;
03166        SET_UNUSED(opline->op2);
03167 
03168        CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
03169 }
03170 /* }}} */
03171 
03172 void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
03173 {
03174        int next_op_number = get_next_op_number(CG(active_op_array));
03175        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03176 
03177        opline->opcode = ZEND_JMPZ_EX;
03178        if (expr1->op_type == IS_TMP_VAR) {
03179               opline->result = *expr1;
03180        } else {
03181               opline->result.u.var = get_temporary_variable(CG(active_op_array));
03182               opline->result.op_type = IS_TMP_VAR;
03183        }
03184        opline->op1 = *expr1;
03185        SET_UNUSED(opline->op2);
03186 
03187        op_token->u.opline_num = next_op_number;
03188 
03189        *expr1 = opline->result;
03190 }
03191 /* }}} */
03192 
03193 void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
03194 {
03195        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03196 
03197        *result = *expr1; /* we saved the original result in expr1 */
03198        opline->opcode = ZEND_BOOL;
03199        opline->result = *result;
03200        opline->op1 = *expr2;
03201        SET_UNUSED(opline->op2);
03202 
03203        CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
03204 }
03205 /* }}} */
03206 
03207 void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
03208 {
03209        do_begin_loop(TSRMLS_C);
03210        INC_BPC(CG(active_op_array));
03211 }
03212 /* }}} */
03213 
03214 void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC) /* {{{ */
03215 {
03216        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03217 
03218        opline->opcode = ZEND_JMPNZ;
03219        opline->op1 = *expr;
03220        opline->op2.u.opline_num = do_token->u.opline_num;
03221        SET_UNUSED(opline->op2);
03222 
03223        do_end_loop(expr_open_bracket->u.opline_num, 0 TSRMLS_CC);
03224 
03225        DEC_BPC(CG(active_op_array));
03226 }
03227 /* }}} */
03228 
03229 void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
03230 {
03231        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03232 
03233        opline->opcode = op;
03234        opline->op1.u.opline_num = CG(active_op_array)->current_brk_cont;
03235        SET_UNUSED(opline->op1);
03236        if (expr) {
03237               opline->op2 = *expr;
03238        } else {
03239               Z_TYPE(opline->op2.u.constant) = IS_LONG;
03240               Z_LVAL(opline->op2.u.constant) = 1;
03241               INIT_PZVAL(&opline->op2.u.constant);
03242               opline->op2.op_type = IS_CONST;
03243        }
03244 }
03245 /* }}} */
03246 
03247 void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
03248 {
03249        zend_switch_entry switch_entry;
03250 
03251        switch_entry.cond = *cond;
03252        switch_entry.default_case = -1;
03253        switch_entry.control_var = -1;
03254        zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
03255 
03256        do_begin_loop(TSRMLS_C);
03257 
03258        INC_BPC(CG(active_op_array));
03259 }
03260 /* }}} */
03261 
03262 void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
03263 {
03264        zend_op *opline;
03265        zend_switch_entry *switch_entry_ptr;
03266 
03267        zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
03268 
03269        /* add code to jmp to default case */
03270        if (switch_entry_ptr->default_case != -1) {
03271               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03272               opline->opcode = ZEND_JMP;
03273               SET_UNUSED(opline->op1);
03274               SET_UNUSED(opline->op2);
03275               opline->op1.u.opline_num = switch_entry_ptr->default_case;
03276        }
03277 
03278        if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
03279               int next_op_number = get_next_op_number(CG(active_op_array));
03280 
03281               CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
03282        }
03283 
03284        /* remember break/continue loop information */
03285        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));
03286        CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
03287 
03288        if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
03289               /* emit free for the switch condition*/
03290               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03291               opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
03292               opline->op1 = switch_entry_ptr->cond;
03293               SET_UNUSED(opline->op2);
03294        }
03295        if (switch_entry_ptr->cond.op_type == IS_CONST) {
03296               zval_dtor(&switch_entry_ptr->cond.u.constant);
03297        }
03298 
03299        zend_stack_del_top(&CG(switch_cond_stack));
03300 
03301        DEC_BPC(CG(active_op_array));
03302 }
03303 /* }}} */
03304 
03305 void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC) /* {{{ */
03306 {
03307        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03308        int next_op_number;
03309        zend_switch_entry *switch_entry_ptr;
03310        znode result;
03311 
03312        zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
03313 
03314        if (switch_entry_ptr->control_var == -1) {
03315               switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
03316        }
03317        opline->opcode = ZEND_CASE;
03318        opline->result.u.var = switch_entry_ptr->control_var;
03319        opline->result.op_type = IS_TMP_VAR;
03320        opline->op1 = switch_entry_ptr->cond;
03321        opline->op2 = *case_expr;
03322        if (opline->op1.op_type == IS_CONST) {
03323               zval_copy_ctor(&opline->op1.u.constant);
03324        }
03325        result = opline->result;
03326 
03327        next_op_number = get_next_op_number(CG(active_op_array));
03328        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03329        opline->opcode = ZEND_JMPZ;
03330        opline->op1 = result;
03331        SET_UNUSED(opline->op2);
03332        case_token->u.opline_num = next_op_number;
03333 
03334        if (case_list->op_type==IS_UNUSED) {
03335               return;
03336        }
03337        next_op_number = get_next_op_number(CG(active_op_array));
03338        CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
03339 }
03340 /* }}} */
03341 
03342 void zend_do_case_after_statement(znode *result, const znode *case_token TSRMLS_DC) /* {{{ */
03343 {
03344        int next_op_number = get_next_op_number(CG(active_op_array));
03345        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03346 
03347        opline->opcode = ZEND_JMP;
03348        SET_UNUSED(opline->op1);
03349        SET_UNUSED(opline->op2);
03350        result->u.opline_num = next_op_number;
03351 
03352        switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) {
03353               case ZEND_JMP:
03354                      CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
03355                      break;
03356               case ZEND_JMPZ:
03357                      CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
03358                      break;
03359        }
03360 }
03361 /* }}} */
03362 
03363 void zend_do_default_before_statement(const znode *case_list, znode *default_token TSRMLS_DC) /* {{{ */
03364 {
03365        int next_op_number = get_next_op_number(CG(active_op_array));
03366        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03367        zend_switch_entry *switch_entry_ptr;
03368 
03369        zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
03370 
03371        opline->opcode = ZEND_JMP;
03372        SET_UNUSED(opline->op1);
03373        SET_UNUSED(opline->op2);
03374        default_token->u.opline_num = next_op_number;
03375 
03376        next_op_number = get_next_op_number(CG(active_op_array));
03377        switch_entry_ptr->default_case = next_op_number;
03378 
03379        if (case_list->op_type==IS_UNUSED) {
03380               return;
03381        }
03382        CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
03383 }
03384 /* }}} */
03385 
03386 void zend_do_begin_class_declaration(const znode *class_token, znode *class_name, const znode *parent_class_name TSRMLS_DC) /* {{{ */
03387 {
03388        zend_op *opline;
03389        int doing_inheritance = 0;
03390        zend_class_entry *new_class_entry;
03391        char *lcname;
03392        int error = 0;
03393        zval **ns_name;
03394 
03395        if (CG(active_class_entry)) {
03396               zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
03397               return;
03398        }
03399 
03400        lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
03401 
03402        if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
03403               efree(lcname);
03404               zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
03405        }
03406 
03407        /* Class name must not conflict with import names */
03408        if (CG(current_import) &&
03409                      zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
03410               error = 1;
03411        }
03412 
03413        if (CG(current_namespace)) {
03414               /* Prefix class name with name of current namespace */
03415               znode tmp;
03416 
03417               tmp.u.constant = *CG(current_namespace);
03418               zval_copy_ctor(&tmp.u.constant);
03419               zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
03420               class_name = &tmp;
03421               efree(lcname);
03422               lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
03423        }
03424 
03425        if (error) {
03426               char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
03427 
03428               if (Z_STRLEN_PP(ns_name) != Z_STRLEN(class_name->u.constant) ||
03429                      memcmp(tmp, lcname, Z_STRLEN(class_name->u.constant))) {
03430                      zend_error(E_COMPILE_ERROR, "Cannot declare class %s because the name is already in use", Z_STRVAL(class_name->u.constant));
03431               }
03432               efree(tmp);
03433        }
03434 
03435        new_class_entry = emalloc(sizeof(zend_class_entry));
03436        new_class_entry->type = ZEND_USER_CLASS;
03437        new_class_entry->name = class_name->u.constant.value.str.val;
03438        new_class_entry->name_length = class_name->u.constant.value.str.len;
03439 
03440        zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
03441        new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
03442        new_class_entry->line_start = class_token->u.opline_num;
03443        new_class_entry->ce_flags |= class_token->u.EA.type;
03444 
03445        if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
03446               switch (parent_class_name->u.EA.type) {
03447                      case ZEND_FETCH_CLASS_SELF:
03448                             zend_error(E_COMPILE_ERROR, "Cannot use 'self' as class name as it is reserved");
03449                             break;
03450                      case ZEND_FETCH_CLASS_PARENT:
03451                             zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved");
03452                             break;
03453                      case ZEND_FETCH_CLASS_STATIC:
03454                             zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved");
03455                             break;
03456                      default:
03457                             break;
03458               }
03459               doing_inheritance = 1;
03460        }
03461 
03462        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03463        opline->op1.op_type = IS_CONST;
03464        build_runtime_defined_function_key(&opline->op1.u.constant, lcname, new_class_entry->name_length TSRMLS_CC);
03465        
03466        opline->op2.op_type = IS_CONST;
03467        opline->op2.u.constant.type = IS_STRING;
03468        Z_SET_REFCOUNT(opline->op2.u.constant, 1);
03469 
03470        if (doing_inheritance) {
03471               opline->extended_value = parent_class_name->u.var;
03472               opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
03473        } else {
03474               opline->opcode = ZEND_DECLARE_CLASS;
03475        }
03476 
03477        opline->op2.u.constant.value.str.val = lcname;
03478        opline->op2.u.constant.value.str.len = new_class_entry->name_length;
03479        
03480        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);
03481        CG(active_class_entry) = new_class_entry;
03482 
03483        opline->result.u.var = get_temporary_variable(CG(active_op_array));
03484        opline->result.op_type = IS_VAR;
03485        CG(implementing_class) = opline->result;
03486 
03487        if (CG(doc_comment)) {
03488               CG(active_class_entry)->doc_comment = CG(doc_comment);
03489               CG(active_class_entry)->doc_comment_len = CG(doc_comment_len);
03490               CG(doc_comment) = NULL;
03491               CG(doc_comment_len) = 0;
03492        }
03493 }
03494 /* }}} */
03495 
03496 static void do_verify_abstract_class(TSRMLS_D) /* {{{ */
03497 {
03498        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03499 
03500        opline->opcode = ZEND_VERIFY_ABSTRACT_CLASS;
03501        opline->op1 = CG(implementing_class);
03502        SET_UNUSED(opline->op2);
03503 }
03504 /* }}} */
03505 
03506 void zend_do_end_class_declaration(const znode *class_token, const znode *parent_token TSRMLS_DC) /* {{{ */
03507 {
03508        zend_class_entry *ce = CG(active_class_entry);
03509 
03510        if (ce->constructor) {
03511               ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
03512               if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
03513                      zend_error(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
03514               }
03515        }
03516        if (ce->destructor) {
03517               ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
03518               if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
03519                      zend_error(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
03520               }
03521        }
03522        if (ce->clone) {
03523               ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
03524               if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
03525                      zend_error(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
03526               }
03527        }
03528 
03529        ce->line_end = zend_get_compiled_lineno(TSRMLS_C);
03530 
03531        if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
03532               && ((parent_token->op_type != IS_UNUSED) || (ce->num_interfaces > 0))) {
03533               zend_verify_abstract_class(ce TSRMLS_CC);
03534               if (ce->num_interfaces) {
03535                      do_verify_abstract_class(TSRMLS_C);
03536               }
03537        }
03538        /* Inherit interfaces; reset number to zero, we need it for above check and
03539         * will restore it during actual implementation. 
03540         * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
03541         * zend_verify_abstract_class() */
03542        if (ce->num_interfaces > 0) {
03543               ce->interfaces = NULL;
03544               ce->num_interfaces = 0;
03545               ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
03546        }
03547        CG(active_class_entry) = NULL;
03548 }
03549 /* }}} */
03550 
03551 void zend_do_implements_interface(znode *interface_name TSRMLS_DC) /* {{{ */
03552 {
03553        zend_op *opline;
03554 
03555        switch (zend_get_class_fetch_type(Z_STRVAL(interface_name->u.constant), Z_STRLEN(interface_name->u.constant))) {
03556               case ZEND_FETCH_CLASS_SELF:
03557               case ZEND_FETCH_CLASS_PARENT:
03558               case ZEND_FETCH_CLASS_STATIC:
03559                      zend_error(E_COMPILE_ERROR, "Cannot use '%s' as interface name as it is reserved", Z_STRVAL(interface_name->u.constant));
03560                      break;
03561               default:
03562                      break;
03563        }
03564 
03565        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03566        opline->opcode = ZEND_ADD_INTERFACE;
03567        opline->op1 = CG(implementing_class);
03568        zend_resolve_class_name(interface_name, &opline->extended_value, 0 TSRMLS_CC);
03569        opline->extended_value = (opline->extended_value & ~ZEND_FETCH_CLASS_MASK) | ZEND_FETCH_CLASS_INTERFACE;
03570        opline->op2 = *interface_name;
03571        CG(active_class_entry)->num_interfaces++;
03572 }
03573 /* }}} */
03574 
03575 ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, const char *src1, int src1_length, const char *src2, int src2_length, int internal) /* {{{ */
03576 {
03577        char *prop_name;
03578        int prop_name_length;
03579 
03580        prop_name_length = 1 + src1_length + 1 + src2_length;
03581        prop_name = pemalloc(prop_name_length + 1, internal);
03582        prop_name[0] = '\0';
03583        memcpy(prop_name + 1, src1, src1_length+1);
03584        memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
03585 
03586        *dest = prop_name;
03587        *dest_length = prop_name_length;
03588 }
03589 /* }}} */
03590 
03591 static int zend_strnlen(const char* s, int maxlen) /* {{{ */
03592 {
03593        int len = 0;
03594        while (*s++ && maxlen--) len++;
03595        return len;
03596 }
03597 /* }}} */
03598 
03599 ZEND_API int zend_unmangle_property_name(char *mangled_property, int len, char **class_name, char **prop_name) /* {{{ */
03600 {
03601        int class_name_len;
03602 
03603        *class_name = NULL;
03604 
03605        if (mangled_property[0]!=0) {
03606               *prop_name = mangled_property;
03607               return SUCCESS;
03608        }
03609        if (len < 3 || mangled_property[1]==0) {
03610               zend_error(E_NOTICE, "Illegal member variable name");
03611               *prop_name = mangled_property;
03612               return FAILURE;
03613        }
03614 
03615        class_name_len = zend_strnlen(mangled_property+1, --len - 1) + 1;
03616        if (class_name_len >= len || mangled_property[class_name_len]!=0) {
03617               zend_error(E_NOTICE, "Corrupt member variable name");
03618               *prop_name = mangled_property;
03619               return FAILURE;
03620        }
03621        *class_name = mangled_property+1;
03622        *prop_name = (*class_name)+class_name_len;
03623        return SUCCESS;
03624 }
03625 /* }}} */
03626 
03627 void zend_do_declare_property(const znode *var_name, const znode *value, zend_uint access_type TSRMLS_DC) /* {{{ */
03628 {
03629        zval *property;
03630        zend_property_info *existing_property_info;
03631        char *comment = NULL;
03632        int comment_len = 0;
03633 
03634        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
03635               zend_error(E_COMPILE_ERROR, "Interfaces may not include member variables");
03636        }
03637 
03638        if (access_type & ZEND_ACC_ABSTRACT) {
03639               zend_error(E_COMPILE_ERROR, "Properties cannot be declared abstract");
03640        }
03641 
03642        if (access_type & ZEND_ACC_FINAL) {
03643               zend_error(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods and classes",
03644                                    CG(active_class_entry)->name, var_name->u.constant.value.str.val);
03645        }
03646 
03647        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) {
03648               if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
03649                      zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
03650               }
03651        }
03652        ALLOC_ZVAL(property);
03653 
03654        if (value) {
03655               *property = value->u.constant;
03656        } else {
03657               INIT_PZVAL(property);
03658               Z_TYPE_P(property) = IS_NULL;
03659        }
03660 
03661        if (CG(doc_comment)) {
03662               comment = CG(doc_comment);
03663               comment_len = CG(doc_comment_len);
03664               CG(doc_comment) = NULL;
03665               CG(doc_comment_len) = 0;
03666        }
03667 
03668        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);
03669        efree(var_name->u.constant.value.str.val);
03670 }
03671 /* }}} */
03672 
03673 void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_DC) /* {{{ */
03674 {
03675        zval *property;
03676 
03677        if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
03678               zend_error(E_COMPILE_ERROR, "Arrays are not allowed in class constants");
03679        }
03680 
03681        ALLOC_ZVAL(property);
03682        *property = value->u.constant;
03683 
03684        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) {
03685               FREE_ZVAL(property);
03686               zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
03687        }
03688        FREE_PNODE(var_name);
03689        
03690        if (CG(doc_comment)) {
03691               efree(CG(doc_comment));
03692               CG(doc_comment) = NULL;
03693               CG(doc_comment_len) = 0;
03694        }
03695 }
03696 /* }}} */
03697 
03698 void zend_do_fetch_property(znode *result, znode *object, const znode *property TSRMLS_DC) /* {{{ */
03699 {
03700        zend_op opline;
03701        zend_llist *fetch_list_ptr;
03702 
03703        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
03704 
03705        if (object->op_type == IS_CV) {
03706               if (object->u.var == CG(active_op_array)->this_var) {
03707                      SET_UNUSED(*object); /* this means $this for objects */
03708               }
03709        } else if (fetch_list_ptr->count == 1) {
03710               zend_llist_element *le = fetch_list_ptr->head;
03711               zend_op *opline_ptr = (zend_op *) le->data;
03712 
03713               if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
03714                      efree(Z_STRVAL(opline_ptr->op1.u.constant));
03715                      SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
03716                      opline_ptr->op2 = *property;
03717                      /* if it was usual fetch, we change it to object fetch */
03718                      switch (opline_ptr->opcode) {
03719                             case ZEND_FETCH_W:
03720                                    opline_ptr->opcode = ZEND_FETCH_OBJ_W;
03721                                    break;
03722                             case ZEND_FETCH_R:
03723                                    opline_ptr->opcode = ZEND_FETCH_OBJ_R;
03724                                    break;
03725                             case ZEND_FETCH_RW:
03726                                    opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
03727                                    break;
03728                             case ZEND_FETCH_IS:
03729                                    opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
03730                                    break;
03731                             case ZEND_FETCH_UNSET:
03732                                    opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
03733                                    break;
03734                             case ZEND_FETCH_FUNC_ARG:
03735                                    opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
03736                                    break;
03737                      }
03738                      *result = opline_ptr->result;
03739                      return;
03740               }
03741        }
03742 
03743        init_op(&opline TSRMLS_CC);
03744        opline.opcode = ZEND_FETCH_OBJ_W;  /* the backpatching routine assumes W */
03745        opline.result.op_type = IS_VAR;
03746        opline.result.u.EA.type = 0;
03747        opline.result.u.var = get_temporary_variable(CG(active_op_array));
03748        opline.op1 = *object;
03749        opline.op2 = *property;
03750        *result = opline.result;
03751 
03752        zend_llist_add_element(fetch_list_ptr, &opline);
03753 }
03754 /* }}} */
03755 
03756 void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */
03757 {
03758        char *name, *cfilename;
03759        char haltoff[] = "__COMPILER_HALT_OFFSET__";
03760        int len, clen;
03761        
03762        if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
03763               zend_error(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope");
03764        }
03765        
03766        cfilename = zend_get_compiled_filename(TSRMLS_C);
03767        clen = strlen(cfilename);
03768        zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, cfilename, clen, 0);
03769        zend_register_long_constant(name, len+1, zend_get_scanned_file_offset(TSRMLS_C), CONST_CS, 0 TSRMLS_CC);
03770        pefree(name, 0);
03771        
03772        if (CG(in_namespace)) {
03773               zend_do_end_namespace(TSRMLS_C);
03774        }
03775 }
03776 /* }}} */
03777 
03778 void zend_do_declare_implicit_property(TSRMLS_D) /* {{{ */
03779 {
03780 /* Fixes bug #26182. Not sure why we needed to do this in the first place.
03781    Has to be checked with Zeev.
03782 */
03783 #if ANDI_0
03784        zend_op *opline_ptr;
03785        zend_llist_element *le;
03786        zend_llist *fetch_list_ptr;
03787 
03788 
03789        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
03790 
03791        if (fetch_list_ptr->count != 1) {
03792               return;
03793        }
03794 
03795        le = fetch_list_ptr->head;
03796        opline_ptr = (zend_op *) le->data;
03797 
03798        if (opline_ptr->op1.op_type == IS_UNUSED
03799               && CG(active_class_entry)
03800               && opline_ptr->op2.op_type == IS_CONST
03801               && !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)) {
03802               znode property;
03803 
03804               property = opline_ptr->op2;
03805               property.u.constant.value.str.val = estrndup(opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
03806               zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);
03807        }
03808 #endif
03809 }
03810 /* }}} */
03811 
03812 void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */
03813 {
03814        zend_stack_push(&CG(object_stack), object, sizeof(znode));
03815 }
03816 /* }}} */
03817 
03818 void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */
03819 {
03820        if (object) {
03821               znode *tmp;
03822 
03823               zend_stack_top(&CG(object_stack), (void **) &tmp);
03824               *object = *tmp;
03825        }
03826        zend_stack_del_top(&CG(object_stack));
03827 }
03828 /* }}} */
03829 
03830 void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */
03831 {
03832        zend_op *opline;
03833        unsigned char *ptr = NULL;
03834 
03835        new_token->u.opline_num = get_next_op_number(CG(active_op_array));
03836        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03837        opline->opcode = ZEND_NEW;
03838        opline->result.op_type = IS_VAR;
03839        opline->result.u.var = get_temporary_variable(CG(active_op_array));
03840        opline->op1 = *class_type;
03841        SET_UNUSED(opline->op2);
03842 
03843        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
03844 }
03845 /* }}} */
03846 
03847 void zend_do_end_new_object(znode *result, const znode *new_token, const znode *argument_list TSRMLS_DC) /* {{{ */
03848 {
03849        znode ctor_result;
03850 
03851        zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
03852        zend_do_free(&ctor_result TSRMLS_CC);
03853 
03854        CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
03855        *result = CG(active_op_array)->opcodes[new_token->u.opline_num].result;
03856 }
03857 /* }}} */
03858 
03859 static zend_constant* zend_get_ct_const(const zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
03860 {
03861        zend_constant *c = NULL;
03862 
03863        if (Z_STRVAL_P(const_name)[0] == '\\') {
03864               if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name), (void **) &c) == FAILURE) {
03865                      char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name)+1, Z_STRLEN_P(const_name)-1);
03866 
03867                      if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name), (void **) &c)==SUCCESS) {
03868                             if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
03869                                    efree(lookup_name);
03870                                    return c;
03871                             }
03872                      }
03873                      efree(lookup_name);
03874                      return NULL;
03875               }
03876        } else if (zend_hash_find(EG(zend_constants), Z_STRVAL_P(const_name), Z_STRLEN_P(const_name)+1, (void **) &c) == FAILURE) {
03877               char *lookup_name = zend_str_tolower_dup(Z_STRVAL_P(const_name), Z_STRLEN_P(const_name));
03878                
03879               if (zend_hash_find(EG(zend_constants), lookup_name, Z_STRLEN_P(const_name)+1, (void **) &c)==SUCCESS) {
03880                      if ((c->flags & CONST_CT_SUBST) && !(c->flags & CONST_CS)) {
03881                             efree(lookup_name);
03882                             return c;
03883                      }
03884               }
03885               efree(lookup_name);
03886               return NULL;
03887        }
03888        if (c->flags & CONST_CT_SUBST) {
03889               return c;
03890        }
03891        if (all_internal_constants_substitution &&
03892                      (c->flags & CONST_PERSISTENT) &&
03893                      !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION) &&
03894                      Z_TYPE(c->value) != IS_CONSTANT &&
03895                      Z_TYPE(c->value) != IS_CONSTANT_ARRAY) {
03896               return c;
03897        }
03898        return NULL;
03899 }
03900 /* }}} */
03901 
03902 static int zend_constant_ct_subst(znode *result, zval *const_name, int all_internal_constants_substitution TSRMLS_DC) /* {{{ */
03903 {
03904        zend_constant *c = zend_get_ct_const(const_name, all_internal_constants_substitution TSRMLS_CC);
03905 
03906        if (c) {
03907               zval_dtor(const_name);
03908               result->op_type = IS_CONST;
03909               result->u.constant = c->value;
03910               zval_copy_ctor(&result->u.constant);
03911               INIT_PZVAL(&result->u.constant);
03912               return 1;
03913        }
03914        return 0;
03915 }
03916 /* }}} */
03917 
03918 void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode, zend_bool check_namespace TSRMLS_DC) /* {{{ */
03919 {
03920        znode tmp;
03921        zend_op *opline;
03922        int type;
03923        char *compound;
03924        ulong fetch_type = 0;
03925 
03926        if (constant_container) {
03927               switch (mode) {
03928                      case ZEND_CT:
03929                             /* this is a class constant */
03930                             type = zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant));
03931        
03932                             if (ZEND_FETCH_CLASS_STATIC == type) {
03933                                    zend_error(E_ERROR, "\"static::\" is not allowed in compile-time constants");
03934                             } else if (ZEND_FETCH_CLASS_DEFAULT == type) {
03935                                    zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
03936                             }
03937                             zend_do_build_full_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
03938                             *result = *constant_container;
03939                             result->u.constant.type = IS_CONSTANT | fetch_type;
03940                             break;
03941                      case ZEND_RT:
03942                             if (constant_container->op_type == IS_CONST &&
03943                             ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(constant_container->u.constant), Z_STRLEN(constant_container->u.constant))) {
03944                                    zend_resolve_class_name(constant_container, &fetch_type, 1 TSRMLS_CC);
03945                             } else {
03946                                    zend_do_fetch_class(&tmp, constant_container TSRMLS_CC);
03947                                    constant_container = &tmp;
03948                             }
03949                             opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03950                             opline->opcode = ZEND_FETCH_CONSTANT;
03951                             opline->result.op_type = IS_TMP_VAR;
03952                             opline->result.u.var = get_temporary_variable(CG(active_op_array));
03953                             opline->op1 = *constant_container;
03954                             opline->op2 = *constant_name;
03955                             *result = opline->result;
03956                             break;
03957               }
03958               return;
03959        }
03960        /* namespace constant */
03961        /* only one that did not contain \ from the start can be converted to string if unknown */
03962        switch (mode) {
03963               case ZEND_CT:
03964                      compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
03965                      /* this is a namespace constant, or an unprefixed constant */
03966 
03967                      if (zend_constant_ct_subst(result, &constant_name->u.constant, 0 TSRMLS_CC)) {
03968                             break;
03969                      }
03970 
03971                      zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
03972 
03973                      if(!compound) {
03974                             fetch_type |= IS_CONSTANT_UNQUALIFIED;
03975                      }
03976 
03977                      *result = *constant_name;
03978                      result->u.constant.type = IS_CONSTANT | fetch_type;
03979                      break;
03980               case ZEND_RT:
03981                      compound = memchr(Z_STRVAL(constant_name->u.constant), '\\', Z_STRLEN(constant_name->u.constant));
03982 
03983                      zend_resolve_non_class_name(constant_name, check_namespace TSRMLS_CC);
03984                      
03985                      if(zend_constant_ct_subst(result, &constant_name->u.constant, 1 TSRMLS_CC)) {
03986                             break;
03987                      }
03988 
03989                      opline = get_next_op(CG(active_op_array) TSRMLS_CC);
03990                      opline->opcode = ZEND_FETCH_CONSTANT;
03991                      opline->result.op_type = IS_TMP_VAR;
03992                      opline->result.u.var = get_temporary_variable(CG(active_op_array));
03993                      *result = opline->result;
03994                      SET_UNUSED(opline->op1);
03995                      if(compound) {
03996                             /* the name is unambiguous */
03997                             opline->extended_value = 0;
03998                      } else {
03999                             opline->extended_value = IS_CONSTANT_UNQUALIFIED;
04000                      }
04001                      opline->op2 = *constant_name;
04002                      break;
04003        }
04004 }
04005 /* }}} */
04006 
04007 void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */
04008 {
04009        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04010 
04011        switch (cmd->op_type) {
04012               case IS_CONST:
04013               case IS_TMP_VAR:
04014                      opline->opcode = ZEND_SEND_VAL;
04015                      break;
04016               default:
04017                      opline->opcode = ZEND_SEND_VAR;
04018                      break;
04019        }
04020        opline->op1 = *cmd;
04021        opline->op2.u.opline_num = 0;
04022        opline->extended_value = ZEND_DO_FCALL;
04023        SET_UNUSED(opline->op2);
04024 
04025        /* FIXME: exception support not added to this op2 */
04026        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04027        opline->opcode = ZEND_DO_FCALL;
04028        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04029        opline->result.op_type = IS_VAR;
04030        Z_STRVAL(opline->op1.u.constant) = estrndup("shell_exec", sizeof("shell_exec")-1);
04031        Z_STRLEN(opline->op1.u.constant) = sizeof("shell_exec")-1;
04032        INIT_PZVAL(&opline->op1.u.constant);
04033        Z_TYPE(opline->op1.u.constant) = IS_STRING;
04034        opline->op1.op_type = IS_CONST;
04035        opline->extended_value = 1;
04036        SET_UNUSED(opline->op2);
04037        ZVAL_LONG(&opline->op2.u.constant, zend_hash_func("shell_exec", sizeof("shell_exec")));
04038        *result = opline->result;
04039 }
04040 /* }}} */
04041 
04042 void zend_do_init_array(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
04043 {
04044        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04045 
04046        opline->opcode = ZEND_INIT_ARRAY;
04047        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04048        opline->result.op_type = IS_TMP_VAR;
04049        *result = opline->result;
04050        if (expr) {
04051               opline->op1 = *expr;
04052               if (offset) {
04053                      opline->op2 = *offset;
04054               } else {
04055                      SET_UNUSED(opline->op2);
04056               }
04057        } else {
04058               SET_UNUSED(opline->op1);
04059               SET_UNUSED(opline->op2);
04060        }
04061        opline->extended_value = is_ref;
04062 }
04063 /* }}} */
04064 
04065 void zend_do_add_array_element(znode *result, const znode *expr, const znode *offset, zend_bool is_ref TSRMLS_DC) /* {{{ */
04066 {
04067        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04068 
04069        opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
04070        opline->result = *result;
04071        opline->op1 = *expr;
04072        if (offset) {
04073               opline->op2 = *offset;
04074        } else {
04075               SET_UNUSED(opline->op2);
04076        }
04077        opline->extended_value = is_ref;
04078 }
04079 /* }}} */
04080 
04081 void zend_do_add_static_array_element(znode *result, znode *offset, const znode *expr) /* {{{ */
04082 {
04083        zval *element;
04084 
04085        ALLOC_ZVAL(element);
04086        *element = expr->u.constant;
04087        if (offset) {
04088               switch (offset->u.constant.type & IS_CONSTANT_TYPE_MASK) {
04089                      case IS_CONSTANT:
04090                             /* Ugly hack to denote that this value has a constant index */
04091                             Z_TYPE_P(element) |= IS_CONSTANT_INDEX;
04092                             Z_STRVAL(offset->u.constant) = erealloc(Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3);
04093                             Z_STRVAL(offset->u.constant)[Z_STRLEN(offset->u.constant)+1] = Z_TYPE(offset->u.constant);
04094                             Z_STRVAL(offset->u.constant)[Z_STRLEN(offset->u.constant)+2] = 0;
04095                             zend_symtable_update(result->u.constant.value.ht, Z_STRVAL(offset->u.constant), Z_STRLEN(offset->u.constant)+3, &element, sizeof(zval *), NULL);
04096                             zval_dtor(&offset->u.constant);
04097                             break;
04098                      case IS_STRING:
04099                             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);
04100                             zval_dtor(&offset->u.constant);
04101                             break;
04102                      case IS_NULL:
04103                             zend_symtable_update(Z_ARRVAL(result->u.constant), "", 1, &element, sizeof(zval *), NULL);
04104                             break;
04105                      case IS_LONG:
04106                      case IS_BOOL:
04107                             zend_hash_index_update(Z_ARRVAL(result->u.constant), Z_LVAL(offset->u.constant), &element, sizeof(zval *), NULL);
04108                             break;
04109                      case IS_DOUBLE:
04110                             zend_hash_index_update(Z_ARRVAL(result->u.constant), zend_dval_to_lval(Z_DVAL(offset->u.constant)), &element, sizeof(zval *), NULL);
04111                             break;
04112                      case IS_CONSTANT_ARRAY:
04113                             zend_error(E_ERROR, "Illegal offset type");
04114                             break;
04115               }
04116        } else {
04117               zend_hash_next_index_insert(Z_ARRVAL(result->u.constant), &element, sizeof(zval *), NULL);
04118        }
04119 }
04120 /* }}} */
04121 
04122 void zend_do_add_list_element(const znode *element TSRMLS_DC) /* {{{ */
04123 {
04124        list_llist_element lle;
04125 
04126        if (element) {
04127               zend_check_writable_variable(element);
04128 
04129               lle.var = *element;
04130               zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
04131               zend_llist_prepend_element(&CG(list_llist), &lle);
04132        }
04133        (*((int *)CG(dimension_llist).tail->data))++;
04134 }
04135 /* }}} */
04136 
04137 void zend_do_new_list_begin(TSRMLS_D) /* {{{ */
04138 {
04139        int current_dimension = 0;
04140        zend_llist_add_element(&CG(dimension_llist), &current_dimension);
04141 }
04142 /* }}} */
04143 
04144 void zend_do_new_list_end(TSRMLS_D) /* {{{ */
04145 {
04146        zend_llist_remove_tail(&CG(dimension_llist));
04147        (*((int *)CG(dimension_llist).tail->data))++;
04148 }
04149 /* }}} */
04150 
04151 void zend_do_list_init(TSRMLS_D) /* {{{ */
04152 {
04153        zend_stack_push(&CG(list_stack), &CG(list_llist), sizeof(zend_llist));
04154        zend_stack_push(&CG(list_stack), &CG(dimension_llist), sizeof(zend_llist));
04155        zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
04156        zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
04157        zend_do_new_list_begin(TSRMLS_C);
04158 }
04159 /* }}} */
04160 
04161 void zend_do_list_end(znode *result, znode *expr TSRMLS_DC) /* {{{ */
04162 {
04163        zend_llist_element *le;
04164        zend_llist_element *dimension;
04165        zend_op *opline;
04166        znode last_container;
04167 
04168        le = CG(list_llist).head;
04169        while (le) {
04170               zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
04171               dimension = tmp_dimension_llist->head;
04172               while (dimension) {
04173                      opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04174                      if (dimension == tmp_dimension_llist->head) { /* first */
04175                             last_container = *expr;
04176                             switch (expr->op_type) {
04177                                    case IS_VAR:
04178                                    case IS_CV:
04179                                           opline->opcode = ZEND_FETCH_DIM_R;
04180                                           break;
04181                                    case IS_TMP_VAR:
04182                                           opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
04183                                           break;
04184                                    case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */
04185                                           zval_copy_ctor(&expr->u.constant);
04186                                           opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
04187                                           break;
04188                             }
04189                             opline->extended_value = ZEND_FETCH_ADD_LOCK;
04190                      } else {
04191                             opline->opcode = ZEND_FETCH_DIM_R;
04192                      }
04193                      opline->result.op_type = IS_VAR;
04194                      opline->result.u.EA.type = 0;
04195                      opline->result.u.var = get_temporary_variable(CG(active_op_array));
04196                      opline->op1 = last_container;
04197                      opline->op2.op_type = IS_CONST;
04198                      Z_TYPE(opline->op2.u.constant) = IS_LONG;
04199                      Z_LVAL(opline->op2.u.constant) = *((int *) dimension->data);
04200                      INIT_PZVAL(&opline->op2.u.constant);
04201                      last_container = opline->result;
04202                      dimension = dimension->next;
04203               }
04204               ((list_llist_element *) le->data)->value = last_container;
04205               zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
04206               zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
04207               zend_do_free(result TSRMLS_CC);
04208               le = le->next;
04209        }
04210        zend_llist_destroy(&CG(dimension_llist));
04211        zend_llist_destroy(&CG(list_llist));
04212        *result = *expr;
04213        {
04214               zend_llist *p;
04215 
04216               /* restore previous lists */
04217               zend_stack_top(&CG(list_stack), (void **) &p);
04218               CG(dimension_llist) = *p;
04219               zend_stack_del_top(&CG(list_stack));
04220               zend_stack_top(&CG(list_stack), (void **) &p);
04221               CG(list_llist) = *p;
04222               zend_stack_del_top(&CG(list_stack));
04223        }
04224 }
04225 /* }}} */
04226 
04227 void zend_do_fetch_static_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
04228 {
04229        zval *tmp;
04230        zend_op *opline;
04231        znode lval;
04232        znode result;
04233 
04234        ALLOC_ZVAL(tmp);
04235 
04236        if (static_assignment) {
04237               *tmp = static_assignment->u.constant;
04238        } else {
04239               INIT_ZVAL(*tmp);
04240        }
04241        if (!CG(active_op_array)->static_variables) {
04242               ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
04243               zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
04244        }
04245        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);
04246 
04247        if (varname->op_type == IS_CONST) {
04248               if (Z_TYPE(varname->u.constant) != IS_STRING) {
04249                      convert_to_string(&varname->u.constant);
04250               }
04251        }
04252 
04253        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04254        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 */
04255        opline->result.op_type = IS_VAR;
04256        opline->result.u.EA.type = 0;
04257        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04258        opline->op1 = *varname;
04259        SET_UNUSED(opline->op2);
04260        opline->op2.u.EA.type = ZEND_FETCH_STATIC;
04261        result = opline->result;
04262 
04263        if (varname->op_type == IS_CONST) {
04264               zval_copy_ctor(&varname->u.constant);
04265        }
04266        fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
04267 
04268        if (fetch_type == ZEND_FETCH_LEXICAL) {
04269               znode dummy;
04270 
04271               zend_do_begin_variable_parse(TSRMLS_C);
04272               zend_do_assign(&dummy, &lval, &result TSRMLS_CC);
04273               zend_do_free(&dummy TSRMLS_CC);
04274        } else {
04275               zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
04276        }
04277        CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
04278 
04279 /*     zval_dtor(&varname->u.constant); */
04280 }
04281 /* }}} */
04282 
04283 void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC) /* {{{ */
04284 {
04285        znode value;
04286 
04287        if (Z_STRLEN(varname->u.constant) == sizeof("this") - 1 &&
04288                      memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1) == 0) {
04289               zend_error(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
04290               return;
04291        }
04292 
04293        value.op_type = IS_CONST;
04294        ZVAL_NULL(&value.u.constant);
04295        Z_TYPE(value.u.constant) |= is_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
04296        Z_SET_REFCOUNT_P(&value.u.constant, 1);
04297        Z_UNSET_ISREF_P(&value.u.constant);
04298        
04299        zend_do_fetch_static_variable(varname, &value, is_ref ? ZEND_FETCH_STATIC : ZEND_FETCH_LEXICAL TSRMLS_CC);
04300 }
04301 /* }}} */
04302 
04303 void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) /* {{{ */
04304 {
04305        zend_op *opline;
04306        znode lval;
04307        znode result;
04308 
04309        if (varname->op_type == IS_CONST) {
04310               if (Z_TYPE(varname->u.constant) != IS_STRING) {
04311                      convert_to_string(&varname->u.constant);
04312               }
04313        }
04314 
04315        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04316        opline->opcode = ZEND_FETCH_W;            /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
04317        opline->result.op_type = IS_VAR;
04318        opline->result.u.EA.type = 0;
04319        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04320        opline->op1 = *varname;
04321        SET_UNUSED(opline->op2);
04322        opline->op2.u.EA.type = fetch_type;
04323        result = opline->result;
04324 
04325        if (varname->op_type == IS_CONST) {
04326               zval_copy_ctor(&varname->u.constant);
04327        }
04328        fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
04329 
04330        zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
04331        CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
04332 }
04333 /* }}} */
04334 
04335 void zend_do_cast(znode *result, const znode *expr, int type TSRMLS_DC) /* {{{ */
04336 {
04337        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04338 
04339        opline->opcode = ZEND_CAST;
04340        opline->result.op_type = IS_TMP_VAR;
04341        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04342        opline->op1 = *expr;
04343        SET_UNUSED(opline->op2);
04344        opline->extended_value = type;
04345        *result = opline->result;
04346 }
04347 /* }}} */
04348 
04349 void zend_do_include_or_eval(int type, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
04350 {
04351        zend_do_extended_fcall_begin(TSRMLS_C);
04352        {
04353               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04354 
04355               opline->opcode = ZEND_INCLUDE_OR_EVAL;
04356               opline->result.op_type = IS_VAR;
04357               opline->result.u.var = get_temporary_variable(CG(active_op_array));
04358               opline->op1 = *op1;
04359               SET_UNUSED(opline->op2);
04360               Z_LVAL(opline->op2.u.constant) = type;
04361               *result = opline->result;
04362        }
04363        zend_do_extended_fcall_end(TSRMLS_C);
04364 }
04365 /* }}} */
04366 
04367 void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC) /* {{{ */
04368 {
04369        int i;
04370 
04371        zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
04372        for (i=1; i<num_references->u.constant.value.lval; i++) {
04373               fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
04374               *variable = *result;
04375        }
04376        zend_do_begin_variable_parse(TSRMLS_C);
04377        fetch_simple_variable(result, variable, 1 TSRMLS_CC);
04378        /* there is a chance someone is accessing $this */
04379        if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) {
04380               CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
04381        }
04382 }
04383 /* }}} */
04384 
04385 void zend_do_unset(const znode *variable TSRMLS_DC) /* {{{ */
04386 {
04387        zend_op *last_op;
04388 
04389        zend_check_writable_variable(variable);
04390 
04391        if (variable->op_type == IS_CV) {
04392               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04393               opline->opcode = ZEND_UNSET_VAR;
04394               opline->op1 = *variable;
04395               SET_UNUSED(opline->op2);
04396               opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
04397               SET_UNUSED(opline->result);
04398               opline->extended_value = ZEND_QUICK_SET;
04399        } else {
04400               last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
04401 
04402               switch (last_op->opcode) {
04403                      case ZEND_FETCH_UNSET:
04404                             last_op->opcode = ZEND_UNSET_VAR;
04405                             break;
04406                      case ZEND_FETCH_DIM_UNSET:
04407                             last_op->opcode = ZEND_UNSET_DIM;
04408                             break;
04409                      case ZEND_FETCH_OBJ_UNSET:
04410                             last_op->opcode = ZEND_UNSET_OBJ;
04411                             break;
04412 
04413               }
04414        }
04415 }
04416 /* }}} */
04417 
04418 void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC) /* {{{ */
04419 {
04420        zend_op *last_op;
04421 
04422        zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
04423 
04424        zend_check_writable_variable(variable);
04425 
04426        if (variable->op_type == IS_CV) {
04427               last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
04428               last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
04429               last_op->op1 = *variable;
04430               SET_UNUSED(last_op->op2);
04431               last_op->op2.u.EA.type = ZEND_FETCH_LOCAL;
04432               last_op->result.u.var = get_temporary_variable(CG(active_op_array));
04433               last_op->extended_value = ZEND_QUICK_SET;
04434        } else {
04435               last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
04436 
04437               switch (last_op->opcode) {
04438                      case ZEND_FETCH_IS:
04439                             last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
04440                             break;
04441                      case ZEND_FETCH_DIM_IS:
04442                             last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
04443                             break;
04444                      case ZEND_FETCH_OBJ_IS:
04445                             last_op->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
04446                             break;
04447               }
04448               last_op->extended_value = 0;
04449        }
04450        last_op->result.op_type = IS_TMP_VAR;
04451        last_op->extended_value |= type;
04452 
04453        *result = last_op->result;
04454 }
04455 /* }}} */
04456 
04457 void zend_do_instanceof(znode *result, const znode *expr, const znode *class_znode, int type TSRMLS_DC) /* {{{ */
04458 {
04459        int last_op_number = get_next_op_number(CG(active_op_array));
04460        zend_op *opline;
04461 
04462        if (last_op_number > 0) {
04463               opline = &CG(active_op_array)->opcodes[last_op_number-1];
04464               if (opline->opcode == ZEND_FETCH_CLASS) {
04465                      opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
04466               }
04467        }
04468 
04469        if (expr->op_type == IS_CONST) {
04470               zend_error(E_COMPILE_ERROR, "instanceof expects an object instance, constant given");
04471        }
04472 
04473        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04474        opline->opcode = ZEND_INSTANCEOF;
04475        opline->result.op_type = IS_TMP_VAR;
04476        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04477        opline->op1 = *expr;
04478 
04479        opline->op2 = *class_znode;
04480 
04481        *result = opline->result;
04482 }
04483 /* }}} */
04484 
04485 void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, znode *array, znode *as_token, int variable TSRMLS_DC) /* {{{ */
04486 {
04487        zend_op *opline;
04488        zend_bool is_variable;
04489        zend_bool push_container = 0;
04490        zend_op dummy_opline;
04491 
04492        if (variable) {
04493               if (zend_is_function_or_method_call(array)) {
04494                      is_variable = 0;
04495               } else {
04496                      is_variable = 1;
04497               }
04498               /* save the location of FETCH_W instruction(s) */
04499               open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
04500               zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
04501               if (CG(active_op_array)->last > 0 &&
04502                             CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
04503                      /* Only lock the container if we are fetching from a real container and not $this */
04504                      if (CG(active_op_array)->opcodes[CG(active_op_array)->last-1].op1.op_type == IS_VAR) {
04505                             CG(active_op_array)->opcodes[CG(active_op_array)->last-1].extended_value |= ZEND_FETCH_ADD_LOCK;
04506                             push_container = 1;
04507                      }
04508               }
04509        } else {
04510               is_variable = 0;
04511               open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
04512        }
04513 
04514        /* save the location of FE_RESET */
04515        foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
04516 
04517        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04518 
04519        /* Preform array reset */
04520        opline->opcode = ZEND_FE_RESET;
04521        opline->result.op_type = IS_VAR;
04522        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04523        opline->op1 = *array;
04524        SET_UNUSED(opline->op2);
04525        opline->extended_value = is_variable ? ZEND_FE_RESET_VARIABLE : 0;
04526 
04527        dummy_opline.result = opline->result;
04528        if (push_container) {
04529               dummy_opline.op1 = CG(active_op_array)->opcodes[CG(active_op_array)->last-2].op1;
04530        } else {
04531               znode tmp;
04532 
04533               tmp.op_type = IS_UNUSED;
04534               dummy_opline.op1 = tmp;
04535        }
04536        zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
04537 
04538        /* save the location of FE_FETCH */
04539        as_token->u.opline_num = get_next_op_number(CG(active_op_array));
04540 
04541        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04542        opline->opcode = ZEND_FE_FETCH;
04543        opline->result.op_type = IS_VAR;
04544        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04545        opline->op1 = dummy_opline.result;
04546        opline->extended_value = 0;
04547        SET_UNUSED(opline->op2);
04548 
04549        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04550        opline->opcode = ZEND_OP_DATA;
04551        SET_UNUSED(opline->op1);
04552        SET_UNUSED(opline->op2);
04553        SET_UNUSED(opline->result);
04554 }
04555 /* }}} */
04556 
04557 void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token, const znode *as_token, znode *value, znode *key TSRMLS_DC) /* {{{ */
04558 {
04559        zend_op *opline;
04560        znode dummy, value_node;
04561        zend_bool assign_by_ref=0;
04562 
04563        opline = &CG(active_op_array)->opcodes[as_token->u.opline_num];
04564        if (key->op_type != IS_UNUSED) {
04565               znode *tmp;
04566 
04567               /* switch between the key and value... */
04568               tmp = key;
04569               key = value;
04570               value = tmp;
04571 
04572               /* Mark extended_value in case both key and value are being used */
04573               opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
04574        }
04575 
04576        if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) {
04577               zend_error(E_COMPILE_ERROR, "Key element cannot be a reference");
04578        }
04579 
04580        if (value->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE) {
04581               assign_by_ref = 1;
04582               if (!(opline-1)->extended_value) {
04583                      zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
04584               }
04585               /* Mark extended_value for assign-by-reference */
04586               opline->extended_value |= ZEND_FE_FETCH_BYREF;
04587               CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE;
04588        } else {
04589               zend_op *foreach_copy;
04590               zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.opline_num];
04591               zend_op       *end = &CG(active_op_array)->opcodes[open_brackets_token->u.opline_num];
04592 
04593               /* Change "write context" into "read context" */
04594               fetch->extended_value = 0;  /* reset ZEND_FE_RESET_VARIABLE */
04595               while (fetch != end) {
04596                      --fetch;
04597                      if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2.op_type == IS_UNUSED) {
04598                             zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
04599                      }
04600                      fetch->opcode -= 3; /* FETCH_W -> FETCH_R */
04601               }
04602               /* prevent double SWITCH_FREE */
04603               zend_stack_top(&CG(foreach_copy_stack), (void **) &foreach_copy);
04604               foreach_copy->op1.op_type = IS_UNUSED;
04605        }
04606 
04607        value_node = opline->result;
04608 
04609        if (assign_by_ref) {
04610               zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
04611               /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
04612               zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
04613        } else {
04614               zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
04615               zend_do_free(&dummy TSRMLS_CC);
04616        }
04617 
04618        if (key->op_type != IS_UNUSED) {
04619               znode key_node;
04620 
04621               opline = &CG(active_op_array)->opcodes[as_token->u.opline_num+1];
04622               opline->result.op_type = IS_TMP_VAR;
04623               opline->result.u.EA.type = 0;
04624               opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
04625               key_node = opline->result;
04626 
04627               zend_do_assign(&dummy, key, &key_node TSRMLS_CC);
04628               zend_do_free(&dummy TSRMLS_CC);
04629        }
04630 
04631        do_begin_loop(TSRMLS_C);
04632        INC_BPC(CG(active_op_array));
04633 }
04634 /* }}} */
04635 
04636 void zend_do_foreach_end(const znode *foreach_token, const znode *as_token TSRMLS_DC) /* {{{ */
04637 {
04638        zend_op *container_ptr;
04639        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04640 
04641        opline->opcode = ZEND_JMP;
04642        opline->op1.u.opline_num = as_token->u.opline_num;
04643        SET_UNUSED(opline->op1);
04644        SET_UNUSED(opline->op2);
04645 
04646        CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
04647        CG(active_op_array)->opcodes[as_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
04648 
04649        do_end_loop(as_token->u.opline_num, 1 TSRMLS_CC);
04650 
04651        zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
04652        generate_free_foreach_copy(container_ptr TSRMLS_CC);
04653        zend_stack_del_top(&CG(foreach_copy_stack));
04654 
04655        DEC_BPC(CG(active_op_array));
04656 }
04657 /* }}} */
04658 
04659 void zend_do_declare_begin(TSRMLS_D) /* {{{ */
04660 {
04661        zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables));
04662 }
04663 /* }}} */
04664 
04665 void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC) /* {{{ */
04666 {
04667        if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
04668               convert_to_long(&val->u.constant);
04669               CG(declarables).ticks = val->u.constant;
04670 #ifdef ZEND_MULTIBYTE
04671        } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
04672               zend_encoding *new_encoding, *old_encoding;
04673               zend_encoding_filter old_input_filter;
04674 
04675               if ((Z_TYPE(val->u.constant) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT) {
04676                      zend_error(E_COMPILE_ERROR, "Cannot use constants as encoding");
04677               }
04678 
04679               /*
04680                * Check that the pragma comes before any opcodes. If the compilation
04681                * got as far as this, the previous portion of the script must have been
04682                * parseable according to the .ini script_encoding setting. We still
04683                * want to tell them to put declare() at the top.
04684                */
04685               {
04686                      int num = CG(active_op_array)->last;
04687                      /* ignore ZEND_EXT_STMT and ZEND_TICKS */
04688                      while (num > 0 &&
04689                                            (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
04690                                                  CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
04691                             --num;
04692                      }
04693 
04694                      if (num > 0) {
04695                             zend_error(E_COMPILE_ERROR, "Encoding declaration pragma must be the very first statement in the script");
04696                      }
04697               }
04698               CG(encoding_declared) = 1;
04699 
04700               convert_to_string(&val->u.constant);
04701               new_encoding = zend_multibyte_fetch_encoding(val->u.constant.value.str.val);
04702               if (!new_encoding) {
04703                      zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", val->u.constant.value.str.val);
04704               } else {
04705                      old_input_filter = LANG_SCNG(input_filter);
04706                      old_encoding = LANG_SCNG(script_encoding);
04707                      zend_multibyte_set_filter(new_encoding TSRMLS_CC);
04708 
04709                      /* need to re-scan if input filter changed */
04710                      if (old_input_filter != LANG_SCNG(input_filter) ||
04711                             ((old_input_filter == zend_multibyte_script_encoding_filter) &&
04712                              (new_encoding != old_encoding))) {
04713                             zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
04714                      }
04715               }
04716               efree(val->u.constant.value.str.val);
04717 #else  /* !ZEND_MULTIBYTE */
04718        } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
04719               /* Do not generate any kind of warning for encoding declares */
04720               /* zend_error(E_COMPILE_WARNING, "Declare encoding [%s] not supported", val->u.constant.value.str.val); */
04721               zval_dtor(&val->u.constant);
04722 #endif /* ZEND_MULTIBYTE */
04723        } else {
04724               zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", var->u.constant.value.str.val);
04725               zval_dtor(&val->u.constant);
04726        }
04727        zval_dtor(&var->u.constant);
04728 }
04729 /* }}} */
04730 
04731 void zend_do_declare_end(const znode *declare_token TSRMLS_DC) /* {{{ */
04732 {
04733        zend_declarables *declarables;
04734 
04735        zend_stack_top(&CG(declare_stack), (void **) &declarables);
04736        /* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
04737        if ((get_next_op_number(CG(active_op_array)) - declare_token->u.opline_num) - ((Z_LVAL(CG(declarables).ticks))?1:0)) {
04738               CG(declarables) = *declarables;
04739        }
04740 }
04741 /* }}} */
04742 
04743 void zend_do_exit(znode *result, const znode *message TSRMLS_DC) /* {{{ */
04744 {
04745        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04746 
04747        opline->opcode = ZEND_EXIT;
04748        opline->op1 = *message;
04749        SET_UNUSED(opline->op2);
04750 
04751        result->op_type = IS_CONST;
04752        Z_TYPE(result->u.constant) = IS_BOOL;
04753        Z_LVAL(result->u.constant) = 1;
04754 }
04755 /* }}} */
04756 
04757 void zend_do_begin_silence(znode *strudel_token TSRMLS_DC) /* {{{ */
04758 {
04759        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04760 
04761        opline->opcode = ZEND_BEGIN_SILENCE;
04762        opline->result.op_type = IS_TMP_VAR;
04763        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04764        SET_UNUSED(opline->op1);
04765        SET_UNUSED(opline->op2);
04766        *strudel_token = opline->result;
04767 }
04768 /* }}} */
04769 
04770 void zend_do_end_silence(const znode *strudel_token TSRMLS_DC) /* {{{ */
04771 {
04772        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04773 
04774        opline->opcode = ZEND_END_SILENCE;
04775        opline->op1 = *strudel_token;
04776        SET_UNUSED(opline->op2);
04777 }
04778 /* }}} */
04779 
04780 void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC) /* {{{ */
04781 {
04782        int op_number = get_next_op_number(CG(active_op_array));
04783        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04784 
04785        opline->opcode = ZEND_JMP_SET;
04786        opline->result.op_type = IS_TMP_VAR;
04787        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04788        opline->op1 = *value;
04789        SET_UNUSED(opline->op2);
04790        
04791        *colon_token = opline->result;
04792 
04793        jmp_token->u.opline_num = op_number;
04794 
04795        INC_BPC(CG(active_op_array));
04796 }
04797 /* }}} */
04798 
04799 void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *jmp_token, const znode *colon_token TSRMLS_DC) /* {{{ */
04800 {
04801        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04802 
04803        opline->opcode = ZEND_QM_ASSIGN;
04804        opline->extended_value = 0;
04805        opline->result = *colon_token;
04806        opline->op1 = *false_value;
04807        SET_UNUSED(opline->op2);
04808        
04809        *result = opline->result;
04810 
04811        CG(active_op_array)->opcodes[jmp_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
04812        
04813        DEC_BPC(CG(active_op_array));
04814 }
04815 /* }}} */
04816 
04817 void zend_do_begin_qm_op(const znode *cond, znode *qm_token TSRMLS_DC) /* {{{ */
04818 {
04819        int jmpz_op_number = get_next_op_number(CG(active_op_array));
04820        zend_op *opline;
04821 
04822        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04823 
04824        opline->opcode = ZEND_JMPZ;
04825        opline->op1 = *cond;
04826        SET_UNUSED(opline->op2);
04827        opline->op2.u.opline_num = jmpz_op_number;
04828        *qm_token = opline->op2;
04829 
04830        INC_BPC(CG(active_op_array));
04831 }
04832 /* }}} */
04833 
04834 void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC) /* {{{ */
04835 {
04836        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04837 
04838        CG(active_op_array)->opcodes[qm_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
04839 
04840        opline->opcode = ZEND_QM_ASSIGN;
04841        opline->result.op_type = IS_TMP_VAR;
04842        opline->result.u.var = get_temporary_variable(CG(active_op_array));
04843        opline->op1 = *true_value;
04844        SET_UNUSED(opline->op2);
04845 
04846        *qm_token = opline->result;
04847        colon_token->u.opline_num = get_next_op_number(CG(active_op_array));
04848 
04849        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04850        opline->opcode = ZEND_JMP;
04851        SET_UNUSED(opline->op1);
04852        SET_UNUSED(opline->op2);
04853 }
04854 /* }}} */
04855 
04856 void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_token, const znode *colon_token TSRMLS_DC) /* {{{ */
04857 {
04858        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04859 
04860        opline->opcode = ZEND_QM_ASSIGN;
04861        opline->result = *qm_token;
04862        opline->op1 = *false_value;
04863        SET_UNUSED(opline->op2);
04864 
04865        CG(active_op_array)->opcodes[colon_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
04866 
04867        *result = opline->result;
04868 
04869        DEC_BPC(CG(active_op_array));
04870 }
04871 /* }}} */
04872 
04873 void zend_do_extended_info(TSRMLS_D) /* {{{ */
04874 {
04875        zend_op *opline;
04876 
04877        if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
04878               return;
04879        }
04880 
04881        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04882 
04883        opline->opcode = ZEND_EXT_STMT;
04884        SET_UNUSED(opline->op1);
04885        SET_UNUSED(opline->op2);
04886 }
04887 /* }}} */
04888 
04889 void zend_do_extended_fcall_begin(TSRMLS_D) /* {{{ */
04890 {
04891        zend_op *opline;
04892 
04893        if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
04894               return;
04895        }
04896 
04897        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04898 
04899        opline->opcode = ZEND_EXT_FCALL_BEGIN;
04900        SET_UNUSED(opline->op1);
04901        SET_UNUSED(opline->op2);
04902 }
04903 /* }}} */
04904 
04905 void zend_do_extended_fcall_end(TSRMLS_D) /* {{{ */
04906 {
04907        zend_op *opline;
04908 
04909        if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
04910               return;
04911        }
04912 
04913        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04914 
04915        opline->opcode = ZEND_EXT_FCALL_END;
04916        SET_UNUSED(opline->op1);
04917        SET_UNUSED(opline->op2);
04918 }
04919 /* }}} */
04920 
04921 void zend_do_ticks(TSRMLS_D) /* {{{ */
04922 {
04923        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
04924 
04925        opline->opcode = ZEND_TICKS;
04926        opline->op1.u.constant = CG(declarables).ticks;
04927        opline->op1.op_type = IS_CONST;
04928        SET_UNUSED(opline->op2);
04929 }
04930 /* }}} */
04931 
04932 void zend_auto_global_dtor(zend_auto_global *auto_global) /* {{{ */
04933 {
04934        free(auto_global->name);
04935 }
04936 /* }}} */
04937 
04938 zend_bool zend_is_auto_global(const char *name, uint name_len TSRMLS_DC) /* {{{ */
04939 {
04940        zend_auto_global *auto_global;
04941 
04942        if (zend_hash_find(CG(auto_globals), name, name_len+1, (void **) &auto_global)==SUCCESS) {
04943               if (auto_global->armed) {
04944                      auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
04945               }
04946               return 1;
04947        }
04948        return 0;
04949 }
04950 /* }}} */
04951 
04952 int zend_register_auto_global(const char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC) /* {{{ */
04953 {
04954        zend_auto_global auto_global;
04955 
04956        auto_global.name = zend_strndup(name, name_len);
04957        auto_global.name_len = name_len;
04958        auto_global.auto_global_callback = auto_global_callback;
04959 
04960        return zend_hash_add(CG(auto_globals), name, name_len+1, &auto_global, sizeof(zend_auto_global), NULL);
04961 }
04962 /* }}} */
04963 
04964 int zendlex(znode *zendlval TSRMLS_DC) /* {{{ */
04965 {
04966        int retval;
04967 
04968        if (CG(increment_lineno)) {
04969               CG(zend_lineno)++;
04970               CG(increment_lineno) = 0;
04971        }
04972 
04973 again:
04974        Z_TYPE(zendlval->u.constant) = IS_LONG;
04975        retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
04976        switch (retval) {
04977               case T_COMMENT:
04978               case T_DOC_COMMENT:
04979               case T_OPEN_TAG:
04980               case T_WHITESPACE:
04981                      goto again;
04982 
04983               case T_CLOSE_TAG:
04984                      if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
04985                             CG(increment_lineno) = 1;
04986                      }
04987                      if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
04988                             goto again;                        
04989                      }
04990                      retval = ';'; /* implicit ; */
04991                      break;
04992               case T_OPEN_TAG_WITH_ECHO:
04993                      retval = T_ECHO;
04994                      break;
04995               case T_END_HEREDOC:
04996                      efree(Z_STRVAL(zendlval->u.constant));
04997                      break;
04998        }
04999 
05000        INIT_PZVAL(&zendlval->u.constant);
05001        zendlval->op_type = IS_CONST;
05002        return retval;
05003 }
05004 /* }}} */
05005 
05006 ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC) /* {{{ */
05007 {
05008        zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
05009        dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
05010 
05011        ce->refcount = 1;
05012        ce->constants_updated = 0;
05013        ce->ce_flags = 0;
05014 
05015        ce->doc_comment = NULL;
05016        ce->doc_comment_len = 0;
05017 
05018        zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
05019        zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
05020        zend_hash_init_ex(&ce->default_static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
05021        zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
05022        zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
05023 
05024        if (ce->type == ZEND_INTERNAL_CLASS) {
05025 #ifdef ZTS
05026               int n = zend_hash_num_elements(CG(class_table));
05027 
05028               if (CG(static_members) && n >= CG(last_static_member)) {
05029                      /* Support for run-time declaration: dl() */
05030                      CG(last_static_member) = n+1;
05031                      CG(static_members) = realloc(CG(static_members), (n+1)*sizeof(HashTable*));
05032                      CG(static_members)[n] = NULL;
05033               }
05034               ce->static_members = (HashTable*)(zend_intptr_t)n;
05035 #else
05036               ce->static_members = NULL;
05037 #endif
05038        } else {
05039               ce->static_members = &ce->default_static_members;
05040        }
05041 
05042        if (nullify_handlers) {
05043               ce->constructor = NULL;
05044               ce->destructor = NULL;
05045               ce->clone = NULL;
05046               ce->__get = NULL;
05047               ce->__set = NULL;
05048               ce->__unset = NULL;
05049               ce->__isset = NULL;
05050               ce->__call = NULL;
05051               ce->__callstatic = NULL;
05052               ce->__tostring = NULL;
05053               ce->create_object = NULL;
05054               ce->get_iterator = NULL;
05055               ce->iterator_funcs.funcs = NULL;
05056               ce->interface_gets_implemented = NULL;
05057               ce->get_static_method = NULL;
05058               ce->parent = NULL;
05059               ce->num_interfaces = 0;
05060               ce->interfaces = NULL;
05061               ce->module = NULL;
05062               ce->serialize = NULL;
05063               ce->unserialize = NULL;
05064               ce->serialize_func = NULL;
05065               ce->unserialize_func = NULL;
05066               ce->builtin_functions = NULL;
05067        }
05068 }
05069 /* }}} */
05070 
05071 int zend_get_class_fetch_type(const char *class_name, uint class_name_len) /* {{{ */
05072 {
05073        if ((class_name_len == sizeof("self")-1) &&
05074               !memcmp(class_name, "self", sizeof("self")-1)) {
05075               return ZEND_FETCH_CLASS_SELF;             
05076        } else if ((class_name_len == sizeof("parent")-1) &&
05077               !memcmp(class_name, "parent", sizeof("parent")-1)) {
05078               return ZEND_FETCH_CLASS_PARENT;
05079        } else if ((class_name_len == sizeof("static")-1) &&
05080               !memcmp(class_name, "static", sizeof("static")-1)) {
05081               return ZEND_FETCH_CLASS_STATIC;
05082        } else {
05083               return ZEND_FETCH_CLASS_DEFAULT;
05084        }
05085 }
05086 /* }}} */
05087 
05088 ZEND_API char* zend_get_compiled_variable_name(const zend_op_array *op_array, zend_uint var, int* name_len) /* {{{ */
05089 {
05090        if (name_len) {
05091               *name_len = op_array->vars[var].name_len;
05092        }
05093        return op_array->vars[var].name;
05094 }
05095 /* }}} */
05096 
05097 void zend_do_build_namespace_name(znode *result, znode *prefix, znode *name TSRMLS_DC) /* {{{ */
05098 {
05099        if (prefix) {
05100               *result = *prefix;
05101               if (Z_TYPE(result->u.constant) == IS_STRING &&
05102               Z_STRLEN(result->u.constant) == 0) {
05103                      /* namespace\ */
05104                      if (CG(current_namespace)) {
05105                             znode tmp;
05106 
05107                             zval_dtor(&result->u.constant);
05108                             tmp.op_type = IS_CONST;
05109                             tmp.u.constant = *CG(current_namespace);
05110                             zval_copy_ctor(&tmp.u.constant);
05111                             zend_do_build_namespace_name(result, NULL, &tmp TSRMLS_CC);
05112                      }
05113               }
05114        } else {
05115               result->op_type = IS_CONST;
05116               Z_TYPE(result->u.constant) = IS_STRING;
05117               Z_STRVAL(result->u.constant) = NULL;
05118               Z_STRLEN(result->u.constant) = 0;
05119        }
05120        /* prefix = result */
05121        zend_do_build_full_name(NULL, result, name, 0 TSRMLS_CC);
05122 }
05123 /* }}} */
05124 
05125 void zend_do_begin_namespace(const znode *name, zend_bool with_bracket TSRMLS_DC) /* {{{ */
05126 {
05127        char *lcname;
05128 
05129        /* handle mixed syntax declaration or nested namespaces */
05130        if (!CG(has_bracketed_namespaces)) {
05131               if (CG(current_namespace)) {
05132                      /* previous namespace declarations were unbracketed */
05133                      if (with_bracket) {
05134                             zend_error(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
05135                      }
05136               }
05137        } else {
05138               /* previous namespace declarations were bracketed */
05139               if (!with_bracket) {
05140                      zend_error(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations with unbracketed namespace declarations");
05141               } else if (CG(current_namespace) || CG(in_namespace)) {
05142                      zend_error(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
05143               }
05144        }
05145 
05146        if (((!with_bracket && !CG(current_namespace)) || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0) {
05147               /* ignore ZEND_EXT_STMT and ZEND_TICKS */
05148               int num = CG(active_op_array)->last;
05149               while (num > 0 &&
05150                                     (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
05151                                           CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
05152                      --num;
05153               }
05154               if (num > 0) {
05155                      zend_error(E_COMPILE_ERROR, "Namespace declaration statement has to be the very first statement in the script");
05156               }
05157        }
05158 
05159        CG(in_namespace) = 1;
05160        if (with_bracket) {
05161               CG(has_bracketed_namespaces) = 1;
05162        }
05163 
05164        if (name) {
05165               lcname = zend_str_tolower_dup(Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant));
05166               if (((Z_STRLEN(name->u.constant) == sizeof("self")-1) &&
05167                                    !memcmp(lcname, "self", sizeof("self")-1)) ||
05168                             ((Z_STRLEN(name->u.constant) == sizeof("parent")-1) &&
05169                                           !memcmp(lcname, "parent", sizeof("parent")-1))) {
05170                      zend_error(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", Z_STRVAL(name->u.constant));
05171               }
05172               efree(lcname);
05173 
05174               if (CG(current_namespace)) {
05175                      zval_dtor(CG(current_namespace));
05176               } else {
05177                      ALLOC_ZVAL(CG(current_namespace));
05178               }
05179               *CG(current_namespace) = name->u.constant;
05180        } else {
05181               if (CG(current_namespace)) {
05182                      zval_dtor(CG(current_namespace));
05183                      FREE_ZVAL(CG(current_namespace));
05184                      CG(current_namespace) = NULL;
05185               }
05186        }
05187 
05188        if (CG(current_import)) {
05189               zend_hash_destroy(CG(current_import));
05190               efree(CG(current_import));
05191               CG(current_import) = NULL;
05192        }
05193 
05194        if (CG(doc_comment)) {
05195               efree(CG(doc_comment));
05196               CG(doc_comment) = NULL;
05197               CG(doc_comment_len) = 0;
05198        }
05199 }
05200 /* }}} */
05201 
05202 void zend_do_use(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
05203 {
05204        char *lcname;
05205        zval *name, *ns, tmp;
05206        zend_bool warn = 0;
05207        zend_class_entry **pce;
05208 
05209        if (!CG(current_import)) {
05210               CG(current_import) = emalloc(sizeof(HashTable));
05211               zend_hash_init(CG(current_import), 0, NULL, ZVAL_PTR_DTOR, 0);
05212        }
05213 
05214        ALLOC_ZVAL(ns);
05215        *ns = ns_name->u.constant;
05216        if (new_name) {
05217               name = &new_name->u.constant;
05218        } else {
05219               char *p;
05220 
05221               /* The form "use A\B" is eqivalent to "use A\B as B".
05222                  So we extract the last part of compound name to use as a new_name */
05223               name = &tmp;
05224               p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
05225               if (p) {
05226                      ZVAL_STRING(name, p+1, 1);
05227               } else {
05228                      *name = *ns;
05229                      zval_copy_ctor(name);
05230                      warn = !is_global && !CG(current_namespace);
05231               }
05232        }
05233 
05234        lcname = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
05235 
05236        if (((Z_STRLEN_P(name) == sizeof("self")-1) &&
05237                             !memcmp(lcname, "self", sizeof("self")-1)) ||
05238                      ((Z_STRLEN_P(name) == sizeof("parent")-1) &&
05239                             !memcmp(lcname, "parent", sizeof("parent")-1))) {
05240               zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' is a special class name", Z_STRVAL_P(ns), Z_STRVAL_P(name), Z_STRVAL_P(name));
05241        }
05242 
05243        if (CG(current_namespace)) {
05244               /* Prefix import name with current namespace name to avoid conflicts with classes */
05245               char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
05246 
05247               zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
05248               c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
05249               memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lcname, Z_STRLEN_P(name)+1);
05250               if (zend_hash_exists(CG(class_table), c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
05251                      char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
05252 
05253                      if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
05254                             memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
05255                             zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
05256                      }
05257                      efree(tmp2);
05258               }
05259               efree(c_ns_name);
05260        } else if (zend_hash_find(CG(class_table), lcname, Z_STRLEN_P(name)+1, (void**)&pce) == SUCCESS &&
05261                   (*pce)->type == ZEND_USER_CLASS &&
05262                   (*pce)->filename == CG(compiled_filename)) {
05263               char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
05264 
05265               if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
05266                      memcmp(c_tmp, lcname, Z_STRLEN_P(ns))) {
05267                      zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
05268               }
05269               efree(c_tmp);
05270        }
05271 
05272        if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
05273               zend_error(E_COMPILE_ERROR, "Cannot use %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
05274        }
05275        if (warn) {
05276               zend_error(E_WARNING, "The use statement with non-compound name '%s' has no effect", Z_STRVAL_P(name));
05277        }
05278        efree(lcname);
05279        zval_dtor(name);
05280 }
05281 /* }}} */
05282 
05283 void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
05284 {
05285        zend_op *opline;
05286 
05287        if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
05288               zend_error(E_COMPILE_ERROR, "Arrays are not allowed as constants");
05289        }
05290 
05291        if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
05292               zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
05293        }
05294 
05295        if (CG(current_namespace)) {
05296               /* Prefix constant name with name of current namespace, lowercased */
05297               znode tmp;
05298 
05299               tmp.op_type = IS_CONST;
05300               tmp.u.constant = *CG(current_namespace);
05301               Z_STRVAL(tmp.u.constant) = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), Z_STRLEN(tmp.u.constant));
05302               zend_do_build_namespace_name(&tmp, &tmp, name TSRMLS_CC);
05303               *name = tmp;
05304        }
05305 
05306        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
05307        opline->opcode = ZEND_DECLARE_CONST;
05308        SET_UNUSED(opline->result);
05309        opline->op1 = *name;
05310        opline->op2 = *value;
05311 }
05312 /* }}} */
05313 
05314 void zend_verify_namespace(TSRMLS_D) /* {{{ */
05315 {
05316        if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
05317               zend_error(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
05318        }
05319 }
05320 /* }}} */
05321 
05322 void zend_do_end_namespace(TSRMLS_D) /* {{{ */
05323 {
05324        CG(in_namespace) = 0;
05325        if (CG(current_namespace)) {
05326               zval_dtor(CG(current_namespace));
05327               FREE_ZVAL(CG(current_namespace));
05328               CG(current_namespace) = NULL;
05329        }
05330        if (CG(current_import)) {
05331               zend_hash_destroy(CG(current_import));
05332               efree(CG(current_import));
05333               CG(current_import) = NULL;
05334        }
05335        
05336        if (CG(doc_comment)) {
05337               efree(CG(doc_comment));
05338               CG(doc_comment) = NULL;
05339               CG(doc_comment_len) = 0;
05340        }
05341 }
05342 /* }}} */
05343 
05344 void zend_do_end_compilation(TSRMLS_D) /* {{{ */
05345 {
05346        CG(has_bracketed_namespaces) = 0;
05347        zend_do_end_namespace(TSRMLS_C);
05348 }
05349 /* }}} */
05350 
05351 /* {{{ zend_dirname
05352    Returns directory name component of path */
05353 ZEND_API size_t zend_dirname(char *path, size_t len)
05354 {
05355        register char *end = path + len - 1;
05356        unsigned int len_adjust = 0;
05357 
05358 #ifdef PHP_WIN32
05359        /* Note that on Win32 CWD is per drive (heritage from CP/M).
05360         * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
05361         */
05362        if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
05363               /* Skip over the drive spec (if any) so as not to change */
05364               path += 2;
05365               len_adjust += 2;
05366               if (2 == len) {
05367                      /* Return "c:" on Win32 for dirname("c:").
05368                       * It would be more consistent to return "c:." 
05369                       * but that would require making the string *longer*.
05370                       */
05371                      return len;
05372               }
05373        }
05374 #elif defined(NETWARE)
05375        /*
05376         * Find the first occurence of : from the left 
05377         * move the path pointer to the position just after :
05378         * increment the len_adjust to the length of path till colon character(inclusive)
05379         * If there is no character beyond : simple return len
05380         */
05381        char *colonpos = NULL;
05382        colonpos = strchr(path, ':');
05383        if (colonpos != NULL) {
05384               len_adjust = ((colonpos - path) + 1);
05385               path += len_adjust;
05386               if (len_adjust == len) {
05387                      return len;
05388               }
05389        }
05390 #endif
05391 
05392        if (len == 0) {
05393               /* Illegal use of this function */
05394               return 0;
05395        }
05396 
05397        /* Strip trailing slashes */
05398        while (end >= path && IS_SLASH_P(end)) {
05399               end--;
05400        }
05401        if (end < path) {
05402               /* The path only contained slashes */
05403               path[0] = DEFAULT_SLASH;
05404               path[1] = '\0';
05405               return 1 + len_adjust;
05406        }
05407 
05408        /* Strip filename */
05409        while (end >= path && !IS_SLASH_P(end)) {
05410               end--;
05411        }
05412        if (end < path) {
05413               /* No slash found, therefore return '.' */
05414 #ifdef NETWARE
05415               if (len_adjust == 0) {
05416                      path[0] = '.';
05417                      path[1] = '\0';
05418                      return 1; /* only one character */
05419               } else {
05420                      path[0] = '\0';
05421                      return len_adjust;
05422               }
05423 #else
05424               path[0] = '.';
05425               path[1] = '\0';
05426               return 1 + len_adjust;
05427 #endif
05428        }
05429 
05430        /* Strip slashes which came before the file name */
05431        while (end >= path && IS_SLASH_P(end)) {
05432               end--;
05433        }
05434        if (end < path) {
05435               path[0] = DEFAULT_SLASH;
05436               path[1] = '\0';
05437               return 1 + len_adjust;
05438        }
05439        *(end+1) = '\0';
05440 
05441        return (size_t)(end + 1 - path) + len_adjust;
05442 }
05443 /* }}} */
05444 
05445 /*
05446  * Local variables:
05447  * tab-width: 4
05448  * c-basic-offset: 4
05449  * indent-tabs-mode: t
05450  * End:
05451  */