root/Zend/zend_compile.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_push_function_call_entry
  2. zend_duplicate_property_info
  3. zend_duplicate_property_info_internal
  4. zend_destroy_property_info
  5. zend_destroy_property_info_internal
  6. build_runtime_defined_function_key
  7. init_compiler_declarables
  8. zend_init_compiler_context
  9. zend_init_compiler_data_structures
  10. file_handle_dtor
  11. init_compiler
  12. shutdown_compiler
  13. zend_set_compiled_filename
  14. zend_restore_compiled_filename
  15. zend_get_compiled_filename
  16. zend_get_compiled_lineno
  17. zend_is_compiling
  18. get_temporary_variable
  19. lookup_cv
  20. zend_del_literal
  21. zend_insert_literal
  22. zend_add_literal
  23. zend_append_individual_literal
  24. zend_add_func_name_literal
  25. zend_add_ns_func_name_literal
  26. zend_add_class_name_literal
  27. zend_add_const_name_literal
  28. zend_is_function_or_method_call
  29. zend_do_binary_op
  30. zend_do_unary_op
  31. zend_do_op_data
  32. zend_do_binary_assign_op
  33. fetch_simple_variable_ex
  34. fetch_simple_variable
  35. zend_do_fetch_static_member
  36. fetch_array_begin
  37. fetch_array_dim
  38. fetch_string_offset
  39. zend_do_print
  40. zend_do_echo
  41. zend_do_abstract_method
  42. opline_is_fetch_this
  43. zend_do_assign
  44. zend_do_assign_ref
  45. do_begin_loop
  46. do_end_loop
  47. zend_do_while_cond
  48. zend_do_while_end
  49. zend_do_for_cond
  50. zend_do_for_before_statement
  51. zend_do_for_end
  52. zend_do_pre_incdec
  53. zend_do_post_incdec
  54. zend_do_if_cond
  55. zend_do_if_after_statement
  56. zend_do_if_end
  57. zend_check_writable_variable
  58. zend_do_begin_variable_parse
  59. zend_do_end_variable_parse
  60. zend_do_add_string
  61. zend_do_add_variable
  62. zend_do_free
  63. zend_do_verify_access_types
  64. zend_do_begin_function_declaration
  65. zend_do_begin_lambda_function_declaration
  66. zend_do_handle_exception
  67. zend_do_end_function_declaration
  68. zend_do_receive_param
  69. zend_do_begin_function_call
  70. zend_do_begin_method_call
  71. zend_do_clone
  72. zend_do_begin_dynamic_function_call
  73. zend_resolve_non_class_name
  74. zend_resolve_function_name
  75. zend_resolve_const_name
  76. zend_do_resolve_class_name
  77. zend_resolve_class_name
  78. zend_do_fetch_class
  79. zend_do_label
  80. zend_resolve_goto_label
  81. zend_do_goto
  82. zend_release_labels
  83. zend_do_build_full_name
  84. zend_do_begin_class_member_function_call
  85. zend_do_end_function_call
  86. zend_do_pass_param
  87. zend_do_unpack_params
  88. generate_free_switch_expr
  89. generate_free_foreach_copy
  90. zend_do_return
  91. zend_do_yield
  92. zend_add_try_element
  93. zend_add_catch_element
  94. zend_do_first_catch
  95. zend_initialize_try_catch_element
  96. zend_do_mark_last_catch
  97. zend_do_try
  98. zend_do_finally
  99. zend_do_begin_catch
  100. zend_do_end_catch
  101. zend_do_bind_catch
  102. zend_do_end_finally
  103. zend_do_throw
  104. function_add_ref
  105. do_inherit_parent_constructor
  106. zend_visibility_string
  107. do_inherit_method
  108. zend_do_perform_implementation_check
  109. zend_get_function_declaration
  110. do_inheritance_check_on_method
  111. do_inherit_method_check
  112. do_inherit_property_access_check
  113. do_implement_interface
  114. zend_do_inherit_interfaces
  115. zval_internal_ctor
  116. zend_do_inheritance
  117. do_inherit_constant_check
  118. do_interface_constant_check
  119. zend_do_implement_interface
  120. zend_do_implement_trait
  121. zend_traits_method_compatibility_check
  122. zend_add_magic_methods
  123. zend_add_trait_method
  124. zend_fixup_trait_method
  125. zend_traits_copy_functions
  126. zend_check_trait_usage
  127. zend_traits_init_trait_structures
  128. zend_traits_compile_exclude_table
  129. zend_do_traits_method_binding
  130. find_first_definition
  131. zend_do_traits_property_binding
  132. zend_do_check_for_inconsistent_traits_aliasing
  133. zend_do_bind_traits
  134. do_bind_function
  135. zend_prepare_reference
  136. zend_add_trait_alias
  137. zend_add_trait_precedence
  138. do_bind_class
  139. do_bind_inherited_class
  140. zend_do_early_binding
  141. zend_do_delayed_early_binding
  142. zend_do_boolean_or_begin
  143. zend_do_boolean_or_end
  144. zend_do_boolean_and_begin
  145. zend_do_boolean_and_end
  146. zend_do_do_while_begin
  147. zend_do_do_while_end
  148. zend_do_brk_cont
  149. zend_do_switch_cond
  150. zend_do_switch_end
  151. zend_do_case_before_statement
  152. zend_do_case_after_statement
  153. zend_do_default_before_statement
  154. zend_do_begin_class_declaration
  155. do_verify_abstract_class
  156. zend_do_end_class_declaration
  157. zend_do_implements_interface
  158. zend_do_use_trait
  159. zend_mangle_property_name
  160. zend_strnlen
  161. zend_unmangle_property_name_ex
  162. zend_do_declare_property
  163. zend_do_declare_class_constant
  164. zend_do_fetch_property
  165. zend_do_halt_compiler_register
  166. zend_do_push_object
  167. zend_do_pop_object
  168. zend_do_begin_new_object
  169. zend_do_end_new_object
  170. zend_get_ct_const
  171. zend_constant_ct_subst
  172. zend_do_fetch_constant
  173. zend_do_shell_exec
  174. zend_do_init_array
  175. zend_do_add_array_element
  176. zend_do_add_static_array_element
  177. zend_do_add_list_element
  178. zend_do_new_list_begin
  179. zend_do_new_list_end
  180. zend_do_list_init
  181. zend_do_list_end
  182. zend_init_list
  183. zend_add_to_list
  184. zend_do_fetch_static_variable
  185. zend_do_fetch_lexical_variable
  186. zend_do_fetch_global_variable
  187. zend_do_cast
  188. zend_do_include_or_eval
  189. zend_do_indirect_references
  190. zend_do_unset
  191. zend_do_isset_or_isempty
  192. zend_do_instanceof
  193. zend_do_foreach_begin
  194. zend_do_foreach_cont
  195. zend_do_foreach_end
  196. zend_do_declare_begin
  197. zend_do_declare_stmt
  198. zend_do_declare_end
  199. zend_do_exit
  200. zend_do_begin_silence
  201. zend_do_end_silence
  202. zend_do_jmp_set
  203. zend_do_jmp_set_else
  204. zend_do_begin_qm_op
  205. zend_do_qm_true
  206. zend_do_qm_false
  207. zend_do_extended_info
  208. zend_do_extended_fcall_begin
  209. zend_do_extended_fcall_end
  210. zend_do_ticks
  211. zend_is_auto_global_quick
  212. zend_is_auto_global
  213. zend_register_auto_global
  214. zend_auto_global_init
  215. zend_activate_auto_globals
  216. zendlex
  217. zend_initialize_class_data
  218. zend_get_class_fetch_type
  219. zend_get_compiled_variable_name
  220. zend_do_build_namespace_name
  221. zend_do_begin_namespace
  222. zend_do_use
  223. zend_do_use_non_class
  224. zend_do_use_function
  225. zend_do_use_const
  226. zend_do_declare_constant
  227. zend_verify_namespace
  228. zend_do_end_namespace
  229. zend_do_end_compilation
  230. zend_do_constant_expression
  231. zend_dirname

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

/* [<][>][^][v][top][bottom][index][help] */