You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3201 lines
99 KiB

27 years ago
24 years ago
27 years ago
24 years ago
27 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
23 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
26 years ago
27 years ago
26 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
26 years ago
27 years ago
27 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
25 years ago
25 years ago
25 years ago
25 years ago
27 years ago
27 years ago
27 years ago
26 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
24 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
26 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
25 years ago
25 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
23 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
27 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2002 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 at through the world-wide-web at |
  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. #include "zend_language_parser.h"
  20. #include "zend.h"
  21. #include "zend_compile.h"
  22. #include "zend_llist.h"
  23. #include "zend_API.h"
  24. #include "zend_fast_cache.h"
  25. ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
  26. #ifndef ZTS
  27. ZEND_API zend_compiler_globals compiler_globals;
  28. ZEND_API zend_executor_globals executor_globals;
  29. #endif
  30. static void build_runtime_defined_function_key(zval *result, char *name, int name_length, zend_op *opline TSRMLS_DC)
  31. {
  32. char lineno_buf[32];
  33. uint lineno_len;
  34. char *filename;
  35. lineno_len = zend_sprintf(lineno_buf, "%d", opline->lineno);
  36. if (CG(active_op_array)->filename) {
  37. filename = CG(active_op_array)->filename;
  38. } else {
  39. filename = "-";
  40. }
  41. /* NULL, name length, filename length, line number length */
  42. result->value.str.len = 1+name_length+strlen(filename)+lineno_len;
  43. result->value.str.val = (char *) emalloc(result->value.str.len+1);
  44. sprintf(result->value.str.val, "%c%s%s%s", '\0', name, filename, lineno_buf);
  45. result->type = IS_STRING;
  46. result->refcount = 1;
  47. }
  48. static void init_compiler_declarables(TSRMLS_D)
  49. {
  50. CG(declarables).ticks.type = IS_LONG;
  51. CG(declarables).ticks.value.lval = 0;
  52. }
  53. void zend_init_compiler_data_structures(TSRMLS_D)
  54. {
  55. zend_stack_init(&CG(bp_stack));
  56. zend_stack_init(&CG(function_call_stack));
  57. zend_stack_init(&CG(switch_cond_stack));
  58. zend_stack_init(&CG(foreach_copy_stack));
  59. zend_stack_init(&CG(object_stack));
  60. zend_stack_init(&CG(declare_stack));
  61. CG(active_class_entry) = NULL;
  62. CG(active_ce_parent_class_name).value.str.val = NULL;
  63. zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
  64. zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
  65. zend_stack_init(&CG(list_stack));
  66. CG(handle_op_arrays) = 1;
  67. CG(in_compilation) = 0;
  68. init_compiler_declarables(TSRMLS_C);
  69. CG(throw_list) = NULL;
  70. zend_register_auto_global("GLOBALS", sizeof("GLOBALS")-1 TSRMLS_CC);
  71. CG(in_clone_method) = 0;
  72. }
  73. void init_compiler(TSRMLS_D)
  74. {
  75. zend_init_compiler_data_structures(TSRMLS_C);
  76. zend_init_rsrc_list(TSRMLS_C);
  77. zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
  78. zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) zend_file_handle_dtor, 0);
  79. CG(unclean_shutdown) = 0;
  80. }
  81. void shutdown_compiler(TSRMLS_D)
  82. {
  83. zend_stack_destroy(&CG(bp_stack));
  84. zend_stack_destroy(&CG(function_call_stack));
  85. zend_stack_destroy(&CG(switch_cond_stack));
  86. zend_stack_destroy(&CG(foreach_copy_stack));
  87. zend_stack_destroy(&CG(object_stack));
  88. zend_stack_destroy(&CG(declare_stack));
  89. zend_stack_destroy(&CG(list_stack));
  90. zend_hash_destroy(&CG(filenames_table));
  91. zend_llist_destroy(&CG(open_files));
  92. }
  93. ZEND_API char *zend_set_compiled_filename(char *new_compiled_filename TSRMLS_DC)
  94. {
  95. char **pp, *p;
  96. int length = strlen(new_compiled_filename);
  97. if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp)==SUCCESS) {
  98. CG(compiled_filename) = *pp;
  99. return *pp;
  100. }
  101. p = estrndup(new_compiled_filename, length);
  102. zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
  103. CG(compiled_filename) = p;
  104. return p;
  105. }
  106. ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC)
  107. {
  108. CG(compiled_filename) = original_compiled_filename;
  109. }
  110. ZEND_API char *zend_get_compiled_filename(TSRMLS_D)
  111. {
  112. return CG(compiled_filename);
  113. }
  114. ZEND_API int zend_get_compiled_lineno(TSRMLS_D)
  115. {
  116. return CG(zend_lineno);
  117. }
  118. ZEND_API zend_bool zend_is_compiling(TSRMLS_D)
  119. {
  120. return CG(in_compilation);
  121. }
  122. static zend_uint get_temporary_variable(zend_op_array *op_array)
  123. {
  124. return (op_array->T)++ * sizeof(temp_variable);
  125. }
  126. void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC)
  127. {
  128. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  129. opline->opcode = op;
  130. opline->result.op_type = IS_TMP_VAR;
  131. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  132. opline->op1 = *op1;
  133. opline->op2 = *op2;
  134. *result = opline->result;
  135. }
  136. void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC)
  137. {
  138. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  139. opline->opcode = op;
  140. opline->result.op_type = IS_TMP_VAR;
  141. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  142. opline->op1 = *op1;
  143. *result = opline->result;
  144. SET_UNUSED(opline->op2);
  145. }
  146. #define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; }
  147. static void zend_replace_object_fetch(zend_op *last_op, znode *value TSRMLS_DC)
  148. {
  149. if (value->op_type != IS_VAR) {
  150. last_op->opcode = ZEND_MAKE_VAR;
  151. last_op->result.op_type = IS_VAR;
  152. last_op->result.u.EA.type = 0;
  153. last_op->result.u.var = get_temporary_variable(CG(active_op_array));
  154. last_op->op1 = *value;
  155. SET_UNUSED(last_op->op2);
  156. value->op_type = IS_VAR;
  157. value->u.EA.type = 0;
  158. value->u.var = last_op->result.u.var;
  159. } else {
  160. MAKE_NOP(last_op);
  161. }
  162. }
  163. void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC)
  164. {
  165. int last_op_number = get_next_op_number(CG(active_op_array))-1;
  166. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
  167. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  168. if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
  169. switch (op) {
  170. case ZEND_ASSIGN_ADD:
  171. opline->opcode = ZEND_ASSIGN_ADD_OBJ;
  172. break;
  173. case ZEND_ASSIGN_SUB:
  174. opline->opcode = ZEND_ASSIGN_SUB_OBJ;
  175. break;
  176. case ZEND_ASSIGN_MUL:
  177. opline->opcode = ZEND_ASSIGN_MUL_OBJ;
  178. break;
  179. case ZEND_ASSIGN_DIV:
  180. opline->opcode = ZEND_ASSIGN_DIV_OBJ;
  181. break;
  182. case ZEND_ASSIGN_MOD:
  183. opline->opcode = ZEND_ASSIGN_MOD_OBJ;
  184. break;
  185. case ZEND_ASSIGN_SL:
  186. opline->opcode = ZEND_ASSIGN_SL_OBJ;
  187. break;
  188. case ZEND_ASSIGN_SR:
  189. opline->opcode = ZEND_ASSIGN_SR_OBJ;
  190. break;
  191. case ZEND_ASSIGN_CONCAT:
  192. opline->opcode = ZEND_ASSIGN_CONCAT_OBJ;
  193. break;
  194. case ZEND_ASSIGN_BW_OR:
  195. opline->opcode = ZEND_ASSIGN_BW_OR_OBJ;
  196. break;
  197. case ZEND_ASSIGN_BW_AND:
  198. opline->opcode = ZEND_ASSIGN_BW_AND_OBJ;
  199. break;
  200. case ZEND_ASSIGN_BW_XOR:
  201. opline->opcode = ZEND_ASSIGN_BW_XOR_OBJ;
  202. break;
  203. default:
  204. zend_error(E_COMPILE_ERROR, "Unknown binary op opcode %d", op);
  205. }
  206. opline->op2 = last_op->op2;
  207. opline->op1 = last_op->op1;
  208. zend_replace_object_fetch(last_op, op2 TSRMLS_CC);
  209. opline->extended_value = op2->u.var;
  210. } else {
  211. opline->opcode = op;
  212. opline->op1 = *op1;
  213. opline->op2 = *op2;
  214. }
  215. opline->result.op_type = IS_VAR;
  216. opline->result.u.EA.type = 0;
  217. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  218. *result = opline->result;
  219. }
  220. void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC)
  221. {
  222. zend_op opline;
  223. zend_op *opline_ptr;
  224. zend_llist *fetch_list_ptr;
  225. if (bp) {
  226. opline_ptr = &opline;
  227. init_op(opline_ptr TSRMLS_CC);
  228. } else {
  229. opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
  230. }
  231. opline_ptr->opcode = op;
  232. opline_ptr->result.op_type = IS_VAR;
  233. opline_ptr->result.u.EA.type = 0;
  234. opline_ptr->result.u.var = get_temporary_variable(CG(active_op_array));
  235. opline_ptr->op1 = *varname;
  236. *result = opline_ptr->result;
  237. SET_UNUSED(opline_ptr->op2);
  238. opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
  239. if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
  240. if (zend_hash_exists(CG(auto_globals), varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) {
  241. opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
  242. } else {
  243. if (CG(active_op_array)->static_variables && zend_hash_exists(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) {
  244. opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC;
  245. }
  246. }
  247. }
  248. if (bp) {
  249. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  250. zend_llist_add_element(fetch_list_ptr, opline_ptr);
  251. }
  252. }
  253. void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC)
  254. {
  255. /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
  256. fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
  257. }
  258. void zend_do_fetch_static_member(znode *class_znode TSRMLS_DC)
  259. {
  260. zend_llist *fetch_list_ptr;
  261. zend_llist_element *le;
  262. zend_op *opline_ptr;
  263. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  264. le = fetch_list_ptr->head;
  265. opline_ptr = (zend_op *)le->data;
  266. opline_ptr->op2 = *class_znode;
  267. opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
  268. }
  269. void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC)
  270. {
  271. fetch_simple_variable(result, varname, 1 TSRMLS_CC);
  272. fetch_array_dim(result, result, first_dim TSRMLS_CC);
  273. }
  274. void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC)
  275. {
  276. zend_op opline;
  277. zend_llist *fetch_list_ptr;
  278. init_op(&opline TSRMLS_CC);
  279. opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */
  280. opline.result.op_type = IS_VAR;
  281. opline.result.u.EA.type = 0;
  282. opline.result.u.var = get_temporary_variable(CG(active_op_array));
  283. opline.op1 = *parent;
  284. opline.op2 = *dim;
  285. opline.extended_value = ZEND_FETCH_STANDARD;
  286. *result = opline.result;
  287. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  288. zend_llist_add_element(fetch_list_ptr, &opline);
  289. }
  290. void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC)
  291. {
  292. fetch_array_dim(result, parent, offset TSRMLS_CC);
  293. }
  294. void zend_do_print(znode *result, znode *arg TSRMLS_DC)
  295. {
  296. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  297. opline->result.op_type = IS_TMP_VAR;
  298. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  299. opline->opcode = ZEND_PRINT;
  300. opline->op1 = *arg;
  301. SET_UNUSED(opline->op2);
  302. *result = opline->result;
  303. }
  304. void zend_do_echo(znode *arg TSRMLS_DC)
  305. {
  306. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  307. opline->opcode = ZEND_ECHO;
  308. opline->op1 = *arg;
  309. SET_UNUSED(opline->op2);
  310. }
  311. void zend_do_abstract_method(TSRMLS_D)
  312. {
  313. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  314. opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
  315. SET_UNUSED(opline->op1);
  316. SET_UNUSED(opline->op2);
  317. }
  318. void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC)
  319. {
  320. int last_op_number = get_next_op_number(CG(active_op_array))-1;
  321. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
  322. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  323. if (last_op->opcode == ZEND_FETCH_OBJ_W) {
  324. opline->opcode = ZEND_ASSIGN_OBJ;
  325. opline->op1 = last_op->op1;
  326. opline->op2 = last_op->op2;
  327. zend_replace_object_fetch(last_op, value TSRMLS_CC);
  328. opline->extended_value = value->u.var;
  329. } else {
  330. opline->opcode = ZEND_ASSIGN;
  331. opline->op1 = *variable;
  332. opline->op2 = *value;
  333. }
  334. opline->result.op_type = IS_VAR;
  335. opline->result.u.EA.type = 0;
  336. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  337. *result = opline->result;
  338. }
  339. void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC)
  340. {
  341. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  342. opline->opcode = ZEND_ASSIGN_REF;
  343. if (result) {
  344. opline->result.op_type = IS_VAR;
  345. opline->result.u.EA.type = 0;
  346. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  347. *result = opline->result;
  348. } else {
  349. /* SET_UNUSED(opline->result); */
  350. opline->result.u.EA.type |= EXT_TYPE_UNUSED;
  351. }
  352. opline->op1 = *lvar;
  353. opline->op2 = *rvar;
  354. }
  355. static inline void do_begin_loop(TSRMLS_D)
  356. {
  357. zend_brk_cont_element *brk_cont_element;
  358. int parent;
  359. parent = CG(active_op_array)->current_brk_cont;
  360. CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
  361. brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
  362. brk_cont_element->parent = parent;
  363. }
  364. static inline void do_end_loop(int cont_addr TSRMLS_DC)
  365. {
  366. CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
  367. CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
  368. CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
  369. }
  370. void zend_do_while_cond(znode *expr, znode *close_bracket_token TSRMLS_DC)
  371. {
  372. int while_cond_op_number = get_next_op_number(CG(active_op_array));
  373. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  374. opline->opcode = ZEND_JMPZ;
  375. opline->op1 = *expr;
  376. close_bracket_token->u.opline_num = while_cond_op_number;
  377. SET_UNUSED(opline->op2);
  378. do_begin_loop(TSRMLS_C);
  379. INC_BPC(CG(active_op_array));
  380. }
  381. void zend_do_while_end(znode *while_token, znode *close_bracket_token TSRMLS_DC)
  382. {
  383. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  384. /* add unconditional jump */
  385. opline->opcode = ZEND_JMP;
  386. opline->op1.u.opline_num = while_token->u.opline_num;
  387. SET_UNUSED(opline->op1);
  388. SET_UNUSED(opline->op2);
  389. /* update while's conditional jmp */
  390. CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  391. do_end_loop(while_token->u.opline_num TSRMLS_CC);
  392. DEC_BPC(CG(active_op_array));
  393. }
  394. void zend_do_for_cond(znode *expr, znode *second_semicolon_token TSRMLS_DC)
  395. {
  396. int for_cond_op_number = get_next_op_number(CG(active_op_array));
  397. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  398. opline->opcode = ZEND_JMPZNZ;
  399. opline->op1 = *expr; /* the conditional expression */
  400. second_semicolon_token->u.opline_num = for_cond_op_number;
  401. SET_UNUSED(opline->op2);
  402. }
  403. void zend_do_for_before_statement(znode *cond_start, znode *second_semicolon_token TSRMLS_DC)
  404. {
  405. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  406. opline->opcode = ZEND_JMP;
  407. opline->op1.u.opline_num = cond_start->u.opline_num;
  408. CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
  409. SET_UNUSED(opline->op1);
  410. SET_UNUSED(opline->op2);
  411. do_begin_loop(TSRMLS_C);
  412. INC_BPC(CG(active_op_array));
  413. }
  414. void zend_do_for_end(znode *second_semicolon_token TSRMLS_DC)
  415. {
  416. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  417. opline->opcode = ZEND_JMP;
  418. opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1;
  419. CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  420. SET_UNUSED(opline->op1);
  421. SET_UNUSED(opline->op2);
  422. do_end_loop(second_semicolon_token->u.opline_num+1 TSRMLS_CC);
  423. DEC_BPC(CG(active_op_array));
  424. }
  425. void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC)
  426. {
  427. int last_op_number = get_next_op_number(CG(active_op_array))-1;
  428. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
  429. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  430. if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
  431. opline->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
  432. opline->op1 = last_op->op1;
  433. opline->op2 = last_op->op2;
  434. MAKE_NOP(last_op);
  435. } else {
  436. opline->opcode = op;
  437. opline->op1 = *op1;
  438. SET_UNUSED(opline->op2);
  439. }
  440. opline->result.op_type = IS_VAR;
  441. opline->result.u.EA.type = 0;
  442. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  443. *result = opline->result;
  444. }
  445. void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC)
  446. {
  447. int last_op_number = get_next_op_number(CG(active_op_array))-1;
  448. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number];
  449. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  450. if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
  451. opline->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
  452. opline->op1 = last_op->op1;
  453. opline->op2 = last_op->op2;
  454. MAKE_NOP(last_op);
  455. } else {
  456. opline->opcode = op;
  457. opline->op1 = *op1;
  458. SET_UNUSED(opline->op2);
  459. }
  460. opline->result.op_type = IS_TMP_VAR;
  461. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  462. *result = opline->result;
  463. }
  464. void zend_do_if_cond(znode *cond, znode *closing_bracket_token TSRMLS_DC)
  465. {
  466. int if_cond_op_number = get_next_op_number(CG(active_op_array));
  467. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  468. opline->opcode = ZEND_JMPZ;
  469. opline->op1 = *cond;
  470. closing_bracket_token->u.opline_num = if_cond_op_number;
  471. SET_UNUSED(opline->op2);
  472. INC_BPC(CG(active_op_array));
  473. }
  474. void zend_do_if_after_statement(znode *closing_bracket_token, unsigned char initialize TSRMLS_DC)
  475. {
  476. int if_end_op_number = get_next_op_number(CG(active_op_array));
  477. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  478. zend_llist *jmp_list_ptr;
  479. opline->opcode = ZEND_JMP;
  480. /* save for backpatching */
  481. if (initialize) {
  482. zend_llist jmp_list;
  483. zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
  484. zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
  485. }
  486. zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
  487. zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
  488. CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1;
  489. SET_UNUSED(opline->op1);
  490. SET_UNUSED(opline->op2);
  491. }
  492. void zend_do_if_end(TSRMLS_D)
  493. {
  494. int next_op_number = get_next_op_number(CG(active_op_array));
  495. zend_llist *jmp_list_ptr;
  496. zend_llist_element *le;
  497. zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
  498. for (le=jmp_list_ptr->head; le; le = le->next) {
  499. CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number;
  500. }
  501. zend_llist_destroy(jmp_list_ptr);
  502. zend_stack_del_top(&CG(bp_stack));
  503. DEC_BPC(CG(active_op_array));
  504. }
  505. #if 0
  506. /* variable parsing type (compile-time) */
  507. #define ZEND_PARSED_MEMBER (1<<0)
  508. #define ZEND_PARSED_METHOD_CALL (1<<1)
  509. #define ZEND_PARSED_STATIC_MEMBER (1<<2)
  510. #define ZEND_PARSED_FUNCTION_CALL (1<<3)
  511. #define ZEND_PARSED_VARIABLE (1<<4)
  512. #endif
  513. void zend_check_writable_variable(znode *variable)
  514. {
  515. zend_uint type = variable->u.EA.type;
  516. if (type & ZEND_PARSED_METHOD_CALL) {
  517. zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
  518. }
  519. if (type == ZEND_PARSED_FUNCTION_CALL) {
  520. zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
  521. }
  522. }
  523. zend_bool zend_is_function_or_method_call(znode *variable)
  524. {
  525. zend_uint type = variable->u.EA.type;
  526. return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
  527. }
  528. void zend_do_begin_import(TSRMLS_D)
  529. {
  530. zend_llist_init(&CG(import_commands), sizeof(zend_op), NULL, 0);
  531. }
  532. void zend_do_import(int type, znode *what TSRMLS_DC)
  533. {
  534. zend_op opline;
  535. init_op(&opline TSRMLS_CC);
  536. switch (type) {
  537. case T_FUNCTION:
  538. opline.opcode = ZEND_IMPORT_FUNCTION;
  539. break;
  540. case T_CLASS:
  541. opline.opcode = ZEND_IMPORT_CLASS;
  542. break;
  543. case T_CONST:
  544. opline.opcode = ZEND_IMPORT_CONST;
  545. break;
  546. }
  547. if (what) {
  548. if (type == T_FUNCTION || type == T_CLASS) {
  549. zend_str_tolower(what->u.constant.value.str.val, what->u.constant.value.str.len);
  550. }
  551. opline.op2 = *what;
  552. } else {
  553. SET_UNUSED(opline.op2);
  554. }
  555. zend_llist_add_element(&CG(import_commands), &opline);
  556. }
  557. void zend_do_end_import(znode *import_from TSRMLS_DC)
  558. {
  559. zend_llist_element *le;
  560. zend_op *opline, *opline_ptr;
  561. le = CG(import_commands).head;
  562. while (le) {
  563. opline_ptr = (zend_op *)le->data;
  564. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  565. memcpy(opline, opline_ptr, sizeof(zend_op));
  566. opline->op1 = *import_from;
  567. le = le->next;
  568. }
  569. zend_llist_destroy(&CG(import_commands));
  570. }
  571. void zend_do_begin_variable_parse(TSRMLS_D)
  572. {
  573. zend_llist fetch_list;
  574. zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
  575. zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
  576. }
  577. void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
  578. {
  579. zend_llist *fetch_list_ptr;
  580. zend_llist_element *le;
  581. zend_op *opline, *opline_ptr=NULL;
  582. int num_of_created_opcodes = 0;
  583. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  584. le = fetch_list_ptr->head;
  585. while (le) {
  586. opline_ptr = (zend_op *)le->data;
  587. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  588. memcpy(opline, opline_ptr, sizeof(zend_op));
  589. switch (type) {
  590. case BP_VAR_R:
  591. if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
  592. zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
  593. }
  594. opline->opcode -= 3;
  595. break;
  596. case BP_VAR_W:
  597. break;
  598. case BP_VAR_RW:
  599. opline->opcode += 3;
  600. break;
  601. case BP_VAR_IS:
  602. opline->opcode += 6; /* 3+3 */
  603. break;
  604. case BP_VAR_FUNC_ARG:
  605. opline->opcode += 9; /* 3+3+3 */
  606. opline->extended_value = arg_offset;
  607. break;
  608. case BP_VAR_UNSET:
  609. if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
  610. zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
  611. }
  612. opline->opcode += 12; /* 3+3+3+3 */
  613. break;
  614. }
  615. le = le->next;
  616. num_of_created_opcodes++;
  617. }
  618. if (num_of_created_opcodes == 1) {
  619. if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) &&
  620. (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) &&
  621. !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) {
  622. CG(active_op_array)->uses_this = 1;
  623. }
  624. }
  625. zend_llist_destroy(fetch_list_ptr);
  626. zend_stack_del_top(&CG(bp_stack));
  627. }
  628. void zend_do_init_string(znode *result TSRMLS_DC)
  629. {
  630. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  631. opline->opcode = ZEND_INIT_STRING;
  632. opline->result.op_type = IS_TMP_VAR;
  633. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  634. *result = opline->result;
  635. SET_UNUSED(opline->op1);
  636. SET_UNUSED(opline->op2);
  637. }
  638. void zend_do_add_char(znode *result, znode *op1, znode *op2 TSRMLS_DC)
  639. {
  640. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  641. opline->opcode = ZEND_ADD_CHAR;
  642. opline->op1 = *op1;
  643. opline->op2 = *op2;
  644. opline->op2.op_type = IS_CONST;
  645. opline->result = opline->op1;
  646. *result = opline->result;
  647. }
  648. void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC)
  649. {
  650. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  651. opline->opcode = ZEND_ADD_STRING;
  652. opline->op1 = *op1;
  653. opline->op2 = *op2;
  654. opline->op2.op_type = IS_CONST;
  655. opline->result = opline->op1;
  656. *result = opline->result;
  657. }
  658. void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC)
  659. {
  660. zend_op *opline;
  661. if (op1->op_type == IS_CONST) {
  662. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  663. opline->opcode = ZEND_INIT_STRING;
  664. opline->result.op_type = IS_TMP_VAR;
  665. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  666. *result = opline->result;
  667. SET_UNUSED(opline->op1);
  668. SET_UNUSED(opline->op2);
  669. if (op1->u.constant.value.str.len>0) {
  670. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  671. opline->opcode = ZEND_ADD_STRING;
  672. opline->result = *result;
  673. opline->op1 = *result;
  674. opline->op2 = *op1;
  675. opline->result = opline->op1;
  676. } else {
  677. zval_dtor(&op1->u.constant);
  678. }
  679. } else {
  680. *result = *op1;
  681. }
  682. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  683. opline->opcode = ZEND_ADD_VAR;
  684. opline->result = *result;
  685. opline->op1 = *result;
  686. opline->op2 = *op2;
  687. *result = opline->result;
  688. }
  689. static void zend_lowercase_znode_if_const(znode *z)
  690. {
  691. if (z->op_type == IS_CONST) {
  692. zend_str_tolower(z->u.constant.value.str.val, z->u.constant.value.str.len);
  693. }
  694. }
  695. void zend_do_free(znode *op1 TSRMLS_DC)
  696. {
  697. if (op1->op_type==IS_TMP_VAR) {
  698. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  699. opline->opcode = ZEND_FREE;
  700. opline->op1 = *op1;
  701. SET_UNUSED(opline->op2);
  702. } else if (op1->op_type==IS_VAR) {
  703. zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
  704. while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END) {
  705. opline--;
  706. }
  707. if (opline->result.op_type == op1->op_type
  708. && opline->result.u.var == op1->u.var) {
  709. opline->result.u.EA.type |= EXT_TYPE_UNUSED;
  710. } else {
  711. while (opline>CG(active_op_array)->opcodes) {
  712. /* This should be an object instantiation
  713. * Find JMP_NO_CTOR, mark the preceding ASSIGN and the
  714. * proceeding INIT_FCALL_BY_NAME as unused
  715. */
  716. if (opline->opcode == ZEND_JMP_NO_CTOR) {
  717. (opline-1)->result.u.EA.type |= EXT_TYPE_UNUSED;
  718. (opline+1)->op1.u.EA.type |= EXT_TYPE_UNUSED;
  719. break;
  720. } else if (opline->opcode == ZEND_FETCH_DIM_R
  721. && opline->op1.op_type == IS_VAR
  722. && opline->op1.u.var == op1->u.var) {
  723. /* This should the end of a list() construct
  724. * Mark its result as unused
  725. */
  726. opline->extended_value = ZEND_FETCH_STANDARD;
  727. break;
  728. } else if (opline->result.op_type==IS_VAR
  729. && opline->result.u.var == op1->u.var) {
  730. break;
  731. }
  732. opline--;
  733. }
  734. }
  735. } else if (op1->op_type == IS_CONST) {
  736. zval_dtor(&op1->u.constant);
  737. }
  738. }
  739. int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier)
  740. {
  741. if (current_access_type->u.constant.value.lval & ZEND_FN_PPP_MASK) {
  742. zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
  743. }
  744. return (current_access_type->u.constant.value.lval | new_modifier->u.constant.value.lval);
  745. }
  746. void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, zend_uint fn_flags TSRMLS_DC)
  747. {
  748. zend_op_array op_array;
  749. char *name = function_name->u.constant.value.str.val;
  750. int name_len = function_name->u.constant.value.str.len;
  751. int function_begin_line = function_token->u.opline_num;
  752. function_token->u.op_array = CG(active_op_array);
  753. zend_str_tolower(name, name_len);
  754. init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
  755. op_array.function_name = name;
  756. op_array.arg_types = NULL;
  757. op_array.return_reference = return_reference;
  758. op_array.fn_flags = fn_flags;
  759. op_array.scope = CG(active_class_entry);
  760. if (is_method) {
  761. char *short_class_name = CG(active_class_entry)->name;
  762. zend_uint short_class_name_length = CG(active_class_entry)->name_length;
  763. zend_uint i;
  764. for (i=0; i < CG(active_class_entry)->name_length; i++) {
  765. if (CG(active_class_entry)->name[i] == ':') {
  766. short_class_name = &CG(active_class_entry)->name[i+1];
  767. short_class_name_length = strlen(short_class_name);
  768. }
  769. }
  770. if (zend_hash_add(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
  771. zend_op_array *child_op_array, *parent_op_array;
  772. if (CG(active_class_entry)->parent
  773. && (zend_hash_find(&CG(active_class_entry)->function_table, name, name_len+1, (void **) &child_op_array) == SUCCESS)
  774. && (zend_hash_find(&CG(active_class_entry)->parent->function_table, name, name_len+1, (void **) &parent_op_array) == SUCCESS)
  775. && (child_op_array == parent_op_array)) {
  776. zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
  777. } else {
  778. zend_error(E_COMPILE_ERROR, "Cannot redeclare %s()", name);
  779. }
  780. }
  781. if (fn_flags & ZEND_ACC_ABSTRACT) {
  782. CG(active_class_entry)->ce_flags |= ZEND_ACC_ABSTRACT;
  783. }
  784. if ((short_class_name_length == name_len) && (!memcmp(short_class_name, name, name_len))) {
  785. CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
  786. } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
  787. CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
  788. } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) {
  789. CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
  790. } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
  791. CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
  792. CG(in_clone_method) = 1;
  793. } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
  794. CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
  795. } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
  796. CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
  797. } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
  798. CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
  799. }
  800. } else {
  801. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  802. opline->opcode = ZEND_DECLARE_FUNCTION;
  803. opline->op1.op_type = IS_CONST;
  804. build_runtime_defined_function_key(&opline->op1.u.constant, function_name->u.constant.value.str.val, function_name->u.constant.value.str.len, opline TSRMLS_CC);
  805. opline->op2.op_type = IS_CONST;
  806. opline->op2.u.constant.type = IS_STRING;
  807. opline->op2.u.constant.value.str.val = estrndup(name, name_len);
  808. opline->op2.u.constant.value.str.len = name_len;
  809. opline->op2.u.constant.refcount = 1;
  810. opline->extended_value = ZEND_DECLARE_FUNCTION;
  811. zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
  812. }
  813. if (CG(extended_info)) {
  814. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  815. opline->opcode = ZEND_EXT_NOP;
  816. opline->lineno = function_begin_line;
  817. SET_UNUSED(opline->op1);
  818. SET_UNUSED(opline->op2);
  819. }
  820. {
  821. /* Push a seperator to the switch and foreach stacks */
  822. zend_switch_entry switch_entry;
  823. switch_entry.cond.op_type = IS_UNUSED;
  824. switch_entry.default_case = 0;
  825. switch_entry.control_var = 0;
  826. zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
  827. zend_stack_push(&CG(foreach_copy_stack), (void *) &switch_entry.cond, sizeof(znode));
  828. }
  829. function_token->throw_list = CG(throw_list);
  830. CG(throw_list) = NULL;
  831. }
  832. void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
  833. {
  834. zend_do_extended_info(TSRMLS_C);
  835. zend_do_return(NULL, 0 TSRMLS_CC);
  836. pass_two(CG(active_op_array) TSRMLS_CC);
  837. CG(active_op_array) = function_token->u.op_array;
  838. /* Pop the switch and foreach seperators */
  839. zend_stack_del_top(&CG(switch_cond_stack));
  840. zend_stack_del_top(&CG(foreach_copy_stack));
  841. CG(throw_list) = function_token->throw_list;
  842. CG(in_clone_method) = 0;
  843. }
  844. void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC)
  845. {
  846. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  847. opline->opcode = op;
  848. opline->result = *var;
  849. opline->op1 = *offset;
  850. if ((op == ZEND_RECV_INIT)) {
  851. opline->op2 = *initialization;
  852. } else {
  853. SET_UNUSED(opline->op2);
  854. }
  855. if (!CG(active_op_array)->arg_types) {
  856. if (pass_type==BYREF_FORCE) {
  857. int i;
  858. CG(active_op_array)->arg_types = (unsigned char *) emalloc(sizeof(unsigned char)*(offset->u.constant.value.lval+1));
  859. for (i=1; i<offset->u.constant.value.lval; i++) {
  860. CG(active_op_array)->arg_types[i] = BYREF_NONE;
  861. }
  862. CG(active_op_array)->arg_types[0]=(unsigned char) offset->u.constant.value.lval;
  863. CG(active_op_array)->arg_types[offset->u.constant.value.lval] = pass_type;
  864. }
  865. } else {
  866. CG(active_op_array)->arg_types = (unsigned char *) erealloc(CG(active_op_array)->arg_types, sizeof(unsigned char)*(offset->u.constant.value.lval+1));
  867. CG(active_op_array)->arg_types[0]=(unsigned char) offset->u.constant.value.lval;
  868. CG(active_op_array)->arg_types[offset->u.constant.value.lval] = pass_type;
  869. }
  870. }
  871. int zend_do_begin_function_call(znode *function_name TSRMLS_DC)
  872. {
  873. zend_function *function;
  874. zend_str_tolower(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
  875. if (zend_hash_find(CG(function_table), function_name->u.constant.value.str.val, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
  876. zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
  877. return 1; /* Dynamic */
  878. }
  879. switch (function->type) {
  880. case ZEND_USER_FUNCTION: {
  881. zend_op_array *op_array = (zend_op_array *) function;
  882. zend_stack_push(&CG(function_call_stack), (void *) &op_array, sizeof(zend_function *));
  883. }
  884. break;
  885. case ZEND_INTERNAL_FUNCTION: {
  886. zend_internal_function *internal_function = (zend_internal_function *) function;
  887. zend_stack_push(&CG(function_call_stack), (void *) &internal_function, sizeof(zend_function *));
  888. }
  889. break;
  890. }
  891. zend_do_extended_fcall_begin(TSRMLS_C);
  892. return 0;
  893. }
  894. void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
  895. {
  896. zend_op *last_op;
  897. int last_op_number;
  898. unsigned char *ptr = NULL;
  899. zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
  900. zend_do_begin_variable_parse(TSRMLS_C);
  901. last_op_number = get_next_op_number(CG(active_op_array))-1;
  902. last_op = &CG(active_op_array)->opcodes[last_op_number];
  903. if ((last_op->op2.op_type == IS_CONST) && (last_op->op2.u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1)
  904. && !memcmp(last_op->op2.u.constant.value.str.val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME))) {
  905. last_op->opcode = ZEND_CLONE;
  906. left_bracket->u.constant.value.lval = ZEND_CLONE;
  907. zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
  908. zend_do_extended_fcall_begin(TSRMLS_C);
  909. return;
  910. }
  911. last_op->opcode = ZEND_INIT_METHOD_CALL;
  912. left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME;
  913. zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
  914. zend_do_extended_fcall_begin(TSRMLS_C);
  915. }
  916. void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC)
  917. {
  918. unsigned char *ptr = NULL;
  919. zend_op *opline;
  920. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  921. opline->opcode = ZEND_INIT_FCALL_BY_NAME;
  922. opline->op2 = *function_name;
  923. opline->extended_value = 0;
  924. SET_UNUSED(opline->op1);
  925. zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
  926. zend_do_extended_fcall_begin(TSRMLS_C);
  927. }
  928. void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC)
  929. {
  930. long fetch_class_op_number;
  931. zend_op *opline;
  932. fetch_class_op_number = get_next_op_number(CG(active_op_array));
  933. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  934. opline->opcode = ZEND_FETCH_CLASS;
  935. if (class_entry) {
  936. opline->op1 = *class_entry;
  937. } else {
  938. SET_UNUSED(opline->op1);
  939. CG(catch_begin) = fetch_class_op_number;
  940. }
  941. zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
  942. if ((class_name->u.constant.value.str.len == (sizeof("self") - 1)) &&
  943. !memcmp(class_name->u.constant.value.str.val, "self", sizeof("self"))) {
  944. SET_UNUSED(opline->op2);
  945. opline->extended_value = ZEND_FETCH_CLASS_SELF;
  946. zval_dtor(&class_name->u.constant);
  947. } else if ((class_name->u.constant.value.str.len == (sizeof("parent") - 1)) &&
  948. !memcmp(class_name->u.constant.value.str.val, "parent", sizeof("parent"))) {
  949. SET_UNUSED(opline->op2);
  950. opline->extended_value = ZEND_FETCH_CLASS_PARENT;
  951. zval_dtor(&class_name->u.constant);
  952. } else if ((class_name->u.constant.value.str.len == (sizeof("main") - 1)) &&
  953. !memcmp(class_name->u.constant.value.str.val, "main", sizeof("main"))) {
  954. SET_UNUSED(opline->op2);
  955. opline->extended_value = ZEND_FETCH_CLASS_MAIN;
  956. zval_dtor(&class_name->u.constant);
  957. } else {
  958. opline->op2 = *class_name;
  959. }
  960. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  961. opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
  962. *result = opline->result;
  963. }
  964. void do_fetch_class_name(znode *result, znode *class_name_entry, znode *class_name, zend_bool case_sensitive TSRMLS_DC)
  965. {
  966. zend_uint length;
  967. if (!result) {
  968. result = class_name_entry;
  969. } else {
  970. *result = *class_name_entry;
  971. }
  972. if (!case_sensitive) {
  973. zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
  974. }
  975. length = sizeof("::")-1 + result->u.constant.value.str.len + class_name->u.constant.value.str.len;
  976. result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
  977. memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
  978. memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1);
  979. STR_FREE(class_name->u.constant.value.str.val);
  980. result->u.constant.value.str.len = length;
  981. }
  982. void zend_do_begin_class_member_function_call(znode *class_name, znode *function_name TSRMLS_DC)
  983. {
  984. unsigned char *ptr = NULL;
  985. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  986. opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
  987. opline->op1 = *class_name;
  988. zend_lowercase_znode_if_const(function_name);
  989. opline->op2 = *function_name;
  990. zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
  991. }
  992. void zend_do_end_function_call(znode *function_name, znode *result, znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC)
  993. {
  994. zend_op *opline;
  995. if (is_method && function_name && function_name->u.constant.value.lval == ZEND_CLONE) {
  996. if (argument_list->u.constant.value.lval > 0) {
  997. zend_error(E_COMPILE_ERROR, "Can't pass arguments to __clone()");
  998. }
  999. /* FIXME: throw_list */
  1000. zend_stack_del_top(&CG(function_call_stack));
  1001. *result = CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1].result;
  1002. return;
  1003. }
  1004. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1005. if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
  1006. opline->opcode = ZEND_DO_FCALL;
  1007. opline->op1 = *function_name;
  1008. } else {
  1009. opline->opcode = ZEND_DO_FCALL_BY_NAME;
  1010. SET_UNUSED(opline->op1);
  1011. }
  1012. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  1013. opline->result.op_type = IS_VAR;
  1014. *result = opline->result;
  1015. SET_UNUSED(opline->op2);
  1016. /* Check how much this is really needed
  1017. opline->op2.u.constant.value.lval = is_method;
  1018. */
  1019. if (CG(throw_list) != NULL) {
  1020. long op_number = get_next_op_number(CG(active_op_array))-1;
  1021. zend_llist_add_element(CG(throw_list), &op_number);
  1022. } else {
  1023. opline->op2.u.opline_num = -1;
  1024. }
  1025. zend_stack_del_top(&CG(function_call_stack));
  1026. opline->extended_value = argument_list->u.constant.value.lval;
  1027. }
  1028. void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC)
  1029. {
  1030. zend_op *opline;
  1031. unsigned char *arg_types;
  1032. int original_op=op;
  1033. zend_function **function_ptr_ptr, *function_ptr;
  1034. int send_by_reference;
  1035. zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
  1036. function_ptr = *function_ptr_ptr;
  1037. if (original_op==ZEND_SEND_REF
  1038. && !CG(allow_call_time_pass_reference)) {
  1039. zend_error(E_COMPILE_WARNING,
  1040. "Call-time pass-by-reference has been deprecated - argument passed by value; "
  1041. "If you would like to pass it by reference, modify the declaration of %s(). "
  1042. "If you would like to enable call-time pass-by-reference, you can set "
  1043. "allow_call_time_pass_reference to true in your INI file. "
  1044. "However, future versions may not support this any longer. ",
  1045. (function_ptr?function_ptr->common.function_name:"[runtime function name]"),
  1046. offset+1);
  1047. }
  1048. if (function_ptr) {
  1049. arg_types = function_ptr->common.arg_types;
  1050. } else {
  1051. arg_types = NULL;
  1052. }
  1053. send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)?ZEND_ARG_SEND_BY_REF:0;
  1054. if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
  1055. /* Method call */
  1056. op = ZEND_SEND_VAR_NO_REF;
  1057. } else if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) {
  1058. op = ZEND_SEND_VAR_NO_REF;
  1059. }
  1060. if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference == ZEND_ARG_SEND_BY_REF) {
  1061. /* change to passing by reference */
  1062. switch (param->op_type) {
  1063. case IS_VAR:
  1064. op = ZEND_SEND_REF;
  1065. break;
  1066. default:
  1067. zend_error(E_COMPILE_ERROR, "Only variables can be passed by reference");
  1068. break;
  1069. }
  1070. }
  1071. if (original_op == ZEND_SEND_VAR) {
  1072. switch (op) {
  1073. case ZEND_SEND_VAR_NO_REF:
  1074. zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
  1075. break;
  1076. case ZEND_SEND_VAR:
  1077. if (function_ptr) {
  1078. zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
  1079. } else {
  1080. zend_do_end_variable_parse(BP_VAR_FUNC_ARG, offset TSRMLS_CC);
  1081. }
  1082. break;
  1083. case ZEND_SEND_REF:
  1084. zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
  1085. break;
  1086. }
  1087. }
  1088. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1089. if (op == ZEND_SEND_VAR_NO_REF) {
  1090. if (function_ptr) {
  1091. opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference;
  1092. } else {
  1093. opline->extended_value = 0;
  1094. }
  1095. } else {
  1096. if (function_ptr) {
  1097. opline->extended_value = ZEND_DO_FCALL;
  1098. } else {
  1099. opline->extended_value = ZEND_DO_FCALL_BY_NAME;
  1100. }
  1101. }
  1102. opline->opcode = op;
  1103. opline->op1 = *param;
  1104. opline->op2.u.opline_num = offset;
  1105. SET_UNUSED(opline->op2);
  1106. }
  1107. static int generate_free_switch_expr(zend_switch_entry *switch_entry TSRMLS_DC)
  1108. {
  1109. zend_op *opline;
  1110. if (switch_entry->cond.op_type!=IS_VAR && switch_entry->cond.op_type!=IS_TMP_VAR) {
  1111. return 1;
  1112. }
  1113. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1114. opline->opcode = ZEND_SWITCH_FREE;
  1115. opline->op1 = switch_entry->cond;
  1116. SET_UNUSED(opline->op2);
  1117. opline->extended_value = 0;
  1118. return 0;
  1119. }
  1120. static int generate_free_foreach_copy(znode *foreach_copy TSRMLS_DC)
  1121. {
  1122. zend_op *opline;
  1123. if (foreach_copy->op_type!=IS_VAR && foreach_copy->op_type!=IS_TMP_VAR) {
  1124. return 1;
  1125. }
  1126. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1127. opline->opcode = ZEND_SWITCH_FREE;
  1128. opline->op1 = *foreach_copy;
  1129. SET_UNUSED(opline->op2);
  1130. opline->extended_value = 1;
  1131. return 0;
  1132. }
  1133. void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC)
  1134. {
  1135. zend_op *opline;
  1136. if (do_end_vparse) {
  1137. if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
  1138. zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
  1139. } else {
  1140. zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
  1141. }
  1142. #if 0
  1143. } else if (expr && CG(active_op_array)->return_reference) {
  1144. zend_error(E_COMPILE_ERROR, "Only variables may be returned by reference");
  1145. #endif
  1146. }
  1147. #ifdef ZTS
  1148. zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
  1149. zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
  1150. #else
  1151. zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
  1152. zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
  1153. #endif
  1154. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1155. opline->opcode = ZEND_RETURN;
  1156. if (expr) {
  1157. opline->op1 = *expr;
  1158. } else {
  1159. opline->op1.op_type = IS_CONST;
  1160. INIT_ZVAL(opline->op1.u.constant);
  1161. }
  1162. SET_UNUSED(opline->op2);
  1163. }
  1164. void zend_do_try(znode *try_token TSRMLS_DC)
  1165. {
  1166. try_token->throw_list = (void *) CG(throw_list);
  1167. CG(throw_list) = (zend_llist *) emalloc(sizeof(zend_llist));
  1168. zend_llist_init(CG(throw_list), sizeof(long), NULL, 0);
  1169. /* Initialize try backpatch list used to backpatch throw, do_fcall */
  1170. }
  1171. static void throw_list_applier(long *opline_num, long *catch_opline)
  1172. {
  1173. zend_op *opline;
  1174. TSRMLS_FETCH(); /* Pass this by argument */
  1175. opline = &CG(active_op_array)->opcodes[*opline_num];
  1176. /* Backpatch the opline of the catch statement */
  1177. switch (opline->opcode) {
  1178. case ZEND_DO_FCALL:
  1179. case ZEND_DO_FCALL_BY_NAME:
  1180. case ZEND_THROW:
  1181. opline->op2.u.opline_num = *catch_opline;
  1182. break;
  1183. default:
  1184. zend_error(E_COMPILE_ERROR, "Bad opcode in throw list");
  1185. break;
  1186. }
  1187. }
  1188. void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC)
  1189. {
  1190. long catch_op_number = get_next_op_number(CG(active_op_array));
  1191. zend_op *opline;
  1192. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1193. opline->opcode = ZEND_CATCH;
  1194. opline->op1 = *catch_class;
  1195. SET_UNUSED(opline->op1); /* FIXME: Define IS_CLASS or something like that */
  1196. opline->op2 = *catch_var;
  1197. if (first_catch) {
  1198. zend_llist_apply_with_argument(CG(throw_list), (llist_apply_with_arg_func_t) throw_list_applier, &CG(catch_begin) TSRMLS_CC);
  1199. zend_llist_destroy(CG(throw_list));
  1200. efree(CG(throw_list));
  1201. CG(throw_list) = (void *) try_token->throw_list;
  1202. }
  1203. try_token->u.opline_num = catch_op_number;
  1204. }
  1205. void zend_do_end_catch(znode *try_token TSRMLS_DC)
  1206. {
  1207. CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
  1208. }
  1209. void zend_do_throw(znode *expr TSRMLS_DC)
  1210. {
  1211. zend_op *opline;
  1212. long throw_op_number = get_next_op_number(CG(active_op_array));
  1213. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1214. opline->opcode = ZEND_THROW;
  1215. opline->op1 = *expr;
  1216. SET_UNUSED(opline->op2);
  1217. if (CG(throw_list) != NULL) {
  1218. zend_llist_add_element(CG(throw_list), &throw_op_number);
  1219. } else {
  1220. opline->op2.u.opline_num = -1;
  1221. }
  1222. }
  1223. ZEND_API void function_add_ref(zend_function *function)
  1224. {
  1225. if (function->type == ZEND_USER_FUNCTION) {
  1226. zend_op_array *op_array = &function->op_array;
  1227. (*op_array->refcount)++;
  1228. if (op_array->static_variables) {
  1229. HashTable *static_variables = op_array->static_variables;
  1230. zval *tmp_zval;
  1231. ALLOC_HASHTABLE(op_array->static_variables);
  1232. zend_hash_init(op_array->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
  1233. zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
  1234. }
  1235. }
  1236. }
  1237. static void do_inherit_parent_constructor(zend_class_entry *ce)
  1238. {
  1239. zend_function *function;
  1240. if (!ce->parent || ce->constructor) {
  1241. return;
  1242. }
  1243. if (!zend_hash_exists(&ce->function_table, ce->name, ce->name_length+1)) {
  1244. if (zend_hash_find(&ce->parent->function_table, ce->parent->name, ce->parent->name_length+1, (void **) &function)==SUCCESS) {
  1245. /* inherit parent's constructor */
  1246. zend_hash_update(&ce->function_table, ce->name, ce->name_length+1, function, sizeof(zend_function), NULL);
  1247. function_add_ref(function);
  1248. }
  1249. }
  1250. if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **) &function)==SUCCESS) {
  1251. /* inherit parent's constructor */
  1252. zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL);
  1253. function_add_ref(function);
  1254. }
  1255. ce->constructor = ce->parent->constructor;
  1256. ce->__get = ce->parent->__get;
  1257. ce->__set = ce->parent->__set;
  1258. ce->__call = ce->parent->__call;
  1259. }
  1260. char *zend_visibility_string(zend_uint fn_flags)
  1261. {
  1262. if (fn_flags & ZEND_ACC_PRIVATE) {
  1263. return "private";
  1264. }
  1265. if (fn_flags & ZEND_ACC_PROTECTED) {
  1266. return "protected";
  1267. }
  1268. if (fn_flags & ZEND_ACC_PUBLIC) {
  1269. return "public";
  1270. }
  1271. return "";
  1272. }
  1273. static void do_inherit_method(zend_function *function)
  1274. {
  1275. /* The class entry of the derived function intentionally remains the same
  1276. * as that of the parent class. That allows us to know in which context
  1277. * we're running, and handle private method calls properly.
  1278. */
  1279. if (function->common.fn_flags & ZEND_ACC_ABSTRACT) {
  1280. function->op_array.scope->ce_flags |= ZEND_ACC_ABSTRACT;
  1281. }
  1282. function_add_ref(function);
  1283. }
  1284. static zend_bool do_inherit_method_check(zend_function *child, zend_function *parent)
  1285. {
  1286. zend_uint child_flags = child->common.fn_flags;
  1287. zend_uint parent_flags = parent->common.fn_flags;
  1288. /* we do not inherit private methods */
  1289. /* assert(!(parent_flags & ZEND_ACC_PRIVATE)); */
  1290. /* You cannot change from static to non static and vice versa.
  1291. */
  1292. if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
  1293. if (child->common.fn_flags & ZEND_ACC_STATIC) {
  1294. zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
  1295. } else {
  1296. zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
  1297. }
  1298. }
  1299. /* Disallow making an inherited method abstract.
  1300. * Also check the visibility and copy it if needed. This must be done last
  1301. * since we may change the child flags here.
  1302. * Again first detect more than one error to make normal operation faster.
  1303. */
  1304. if ((child_flags & (ZEND_FN_PPP_MASK|ZEND_ACC_ABSTRACT)) != (parent_flags & ZEND_FN_PPP_MASK)) {
  1305. if (child_flags & ZEND_ACC_ABSTRACT) {
  1306. zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
  1307. }
  1308. if (!(child_flags & ZEND_FN_PPP_MASK) || (((child_flags|parent_flags) & ZEND_FN_PPP_MASK) == ZEND_ACC_PUBLIC)) {
  1309. /* this is no error since we copy visibility here */
  1310. /* child->common.fn_flags &= ~ZEND_FN_PPP_MASK; do not clear added public */
  1311. child->common.fn_flags |= parent_flags & ZEND_FN_PPP_MASK;
  1312. } else {
  1313. zend_error(E_COMPILE_ERROR, "Cannot redeclare %s %s::%s() as %s %s::%s()",
  1314. zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), parent->common.function_name,
  1315. zend_visibility_string(child_flags), ZEND_FN_SCOPE_NAME(child), child->common.function_name);
  1316. }
  1317. }
  1318. return SUCCESS;
  1319. }
  1320. void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce)
  1321. {
  1322. zval *tmp;
  1323. /* Perform inheritance */
  1324. zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
  1325. /* STATIC_MEMBERS_FIXME */
  1326. /* zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */
  1327. zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0);
  1328. zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (zend_bool (*)(void *, void *)) do_inherit_method_check);
  1329. ce->parent = parent_ce;
  1330. if (!ce->handle_property_get) {
  1331. ce->handle_property_get = parent_ce->handle_property_get;
  1332. }
  1333. if (!ce->handle_property_set) {
  1334. ce->handle_property_set = parent_ce->handle_property_set;
  1335. }
  1336. if (!ce->handle_function_call) {
  1337. ce->handle_function_call = parent_ce->handle_function_call;
  1338. }
  1339. do_inherit_parent_constructor(ce);
  1340. }
  1341. static void create_class(HashTable *class_table, char *name, int name_length, zend_class_entry **ce)
  1342. {
  1343. zend_class_entry *new_class_entry;
  1344. new_class_entry = emalloc(sizeof(zend_class_entry));
  1345. *ce = new_class_entry;
  1346. new_class_entry->type = ZEND_USER_CLASS;
  1347. new_class_entry->name = estrndup(name, name_length);
  1348. new_class_entry->name_length = name_length;
  1349. new_class_entry->refcount = 1;
  1350. new_class_entry->constants_updated = 0;
  1351. new_class_entry->ce_flags = 0;
  1352. zend_str_tolower(new_class_entry->name, new_class_entry->name_length);
  1353. zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
  1354. zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
  1355. zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
  1356. zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
  1357. zend_hash_init(&new_class_entry->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
  1358. ALLOC_HASHTABLE(new_class_entry->static_members);
  1359. zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
  1360. zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
  1361. new_class_entry->constructor = NULL;
  1362. new_class_entry->destructor = NULL;
  1363. new_class_entry->clone = NULL;
  1364. new_class_entry->__get = NULL;
  1365. new_class_entry->__set = NULL;
  1366. new_class_entry->__call = NULL;
  1367. new_class_entry->create_object = NULL;
  1368. new_class_entry->handle_function_call = NULL;
  1369. new_class_entry->handle_property_set = NULL;
  1370. new_class_entry->handle_property_get = NULL;
  1371. new_class_entry->parent = NULL;
  1372. if (zend_hash_update(class_table, new_class_entry->name, name_length+1, &new_class_entry, sizeof(zend_class_entry *), NULL) == FAILURE) {
  1373. zend_error(E_COMPILE_ERROR, "Can't create class. Fatal error, please report!");
  1374. }
  1375. }
  1376. #include "../TSRM/tsrm_strtok_r.h"
  1377. static int create_nested_class(HashTable *class_table, char *path, zend_class_entry *new_ce)
  1378. {
  1379. char *cur, *temp;
  1380. char *last;
  1381. zend_class_entry *ce, **pce;
  1382. cur = tsrm_strtok_r(path, ":", &temp);
  1383. if (zend_hash_find(class_table, cur, strlen(cur)+1, (void **)&pce) == FAILURE) {
  1384. create_class(class_table, cur, strlen(cur), &ce);
  1385. } else {
  1386. ce = *pce;
  1387. }
  1388. last = tsrm_strtok_r(NULL, ":", &temp);
  1389. for(;;) {
  1390. cur = tsrm_strtok_r(NULL, ":", &temp);
  1391. if (!cur) {
  1392. break;
  1393. }
  1394. if (zend_hash_find(&ce->class_table, last, strlen(last)+1, (void **)&pce) == FAILURE) {
  1395. create_class(&ce->class_table, last, strlen(last), &ce);
  1396. } else {
  1397. ce = *pce;
  1398. }
  1399. last = cur;
  1400. }
  1401. new_ce->refcount++;
  1402. if (zend_hash_add(&ce->class_table, last, strlen(last)+1, &new_ce, sizeof(zend_class_entry *), NULL) == FAILURE) {
  1403. new_ce->refcount--;
  1404. zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", last);
  1405. return FAILURE;
  1406. }
  1407. return SUCCESS;
  1408. }
  1409. ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time)
  1410. {
  1411. zend_function *function;
  1412. zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
  1413. if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) {
  1414. int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
  1415. zend_function *function;
  1416. if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &function)==SUCCESS
  1417. && function->type==ZEND_USER_FUNCTION
  1418. && ((zend_op_array *) function)->last>0) {
  1419. zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
  1420. opline->op2.u.constant.value.str.val,
  1421. ((zend_op_array *) function)->filename,
  1422. ((zend_op_array *) function)->opcodes[0].lineno);
  1423. } else {
  1424. zend_error(error_level, "Cannot redeclare %s()", opline->op2.u.constant.value.str.val);
  1425. }
  1426. return FAILURE;
  1427. } else {
  1428. (*function->op_array.refcount)++;
  1429. function->op_array.static_variables = NULL; /* NULL out the unbound function */
  1430. return SUCCESS;
  1431. }
  1432. }
  1433. ZEND_API int do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table)
  1434. {
  1435. zend_class_entry *ce, **pce;
  1436. if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
  1437. zend_error(E_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
  1438. return FAILURE;
  1439. } else {
  1440. ce = *pce;
  1441. }
  1442. if (strchr(opline->op2.u.constant.value.str.val, ':')) {
  1443. return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce);
  1444. }
  1445. ce->refcount++;
  1446. if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
  1447. ce->refcount--;
  1448. zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
  1449. return FAILURE;
  1450. } else {
  1451. return SUCCESS;
  1452. }
  1453. }
  1454. ZEND_API int do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce)
  1455. {
  1456. zend_class_entry *ce, **pce;
  1457. int found_ce;
  1458. found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
  1459. if (found_ce == FAILURE) {
  1460. zend_error(E_ERROR, "Cannot redeclare class %s", (*pce)->name);
  1461. return FAILURE;
  1462. } else {
  1463. ce = *pce;
  1464. }
  1465. zend_do_inheritance(ce, parent_ce);
  1466. if (strchr(opline->op2.u.constant.value.str.val, ':')) {
  1467. return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce);
  1468. }
  1469. ce->refcount++;
  1470. /* Register the derived class */
  1471. if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
  1472. zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
  1473. ce->refcount--;
  1474. zend_hash_destroy(&ce->function_table);
  1475. zend_hash_destroy(&ce->default_properties);
  1476. zend_hash_destroy(&ce->private_properties);
  1477. zend_hash_destroy(&ce->protected_properties);
  1478. zend_hash_destroy(ce->static_members);
  1479. zend_hash_destroy(&ce->constants_table);
  1480. return FAILURE;
  1481. }
  1482. return SUCCESS;
  1483. }
  1484. void zend_do_early_binding(TSRMLS_D)
  1485. {
  1486. zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
  1487. if (do_bind_function(opline, CG(function_table), CG(class_table), 1) == FAILURE) {
  1488. return;
  1489. }
  1490. zend_hash_del(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
  1491. zval_dtor(&opline->op1.u.constant);
  1492. zval_dtor(&opline->op2.u.constant);
  1493. opline->opcode = ZEND_NOP;
  1494. memset(&opline->op1, 0, sizeof(znode));
  1495. memset(&opline->op2, 0, sizeof(znode));
  1496. SET_UNUSED(opline->op1);
  1497. SET_UNUSED(opline->op2);
  1498. }
  1499. void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC)
  1500. {
  1501. int next_op_number = get_next_op_number(CG(active_op_array));
  1502. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1503. opline->opcode = ZEND_JMPNZ_EX;
  1504. if (expr1->op_type == IS_TMP_VAR) {
  1505. opline->result = *expr1;
  1506. } else {
  1507. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  1508. opline->result.op_type = IS_TMP_VAR;
  1509. }
  1510. opline->op1 = *expr1;
  1511. SET_UNUSED(opline->op2);
  1512. op_token->u.opline_num = next_op_number;
  1513. *expr1 = opline->result;
  1514. }
  1515. void zend_do_boolean_or_end(znode *result, znode *expr1, znode *expr2, znode *op_token TSRMLS_DC)
  1516. {
  1517. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1518. *result = *expr1; /* we saved the original result in expr1 */
  1519. opline->opcode = ZEND_BOOL;
  1520. opline->result = *result;
  1521. opline->op1 = *expr2;
  1522. SET_UNUSED(opline->op2);
  1523. CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  1524. }
  1525. void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC)
  1526. {
  1527. int next_op_number = get_next_op_number(CG(active_op_array));
  1528. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1529. opline->opcode = ZEND_JMPZ_EX;
  1530. if (expr1->op_type == IS_TMP_VAR) {
  1531. opline->result = *expr1;
  1532. } else {
  1533. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  1534. opline->result.op_type = IS_TMP_VAR;
  1535. }
  1536. opline->op1 = *expr1;
  1537. SET_UNUSED(opline->op2);
  1538. op_token->u.opline_num = next_op_number;
  1539. *expr1 = opline->result;
  1540. }
  1541. void zend_do_boolean_and_end(znode *result, znode *expr1, znode *expr2, znode *op_token TSRMLS_DC)
  1542. {
  1543. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1544. *result = *expr1; /* we saved the original result in expr1 */
  1545. opline->opcode = ZEND_BOOL;
  1546. opline->result = *result;
  1547. opline->op1 = *expr2;
  1548. SET_UNUSED(opline->op2);
  1549. CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  1550. }
  1551. void zend_do_do_while_begin(TSRMLS_D)
  1552. {
  1553. do_begin_loop(TSRMLS_C);
  1554. INC_BPC(CG(active_op_array));
  1555. }
  1556. void zend_do_do_while_end(znode *do_token, znode *expr_open_bracket, znode *expr TSRMLS_DC)
  1557. {
  1558. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1559. opline->opcode = ZEND_JMPNZ;
  1560. opline->op1 = *expr;
  1561. opline->op2.u.opline_num = do_token->u.opline_num;
  1562. SET_UNUSED(opline->op2);
  1563. do_end_loop(expr_open_bracket->u.opline_num TSRMLS_CC);
  1564. DEC_BPC(CG(active_op_array));
  1565. }
  1566. void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC)
  1567. {
  1568. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1569. opline->opcode = op;
  1570. opline->op1.u.opline_num = CG(active_op_array)->current_brk_cont;
  1571. SET_UNUSED(opline->op1);
  1572. if (expr) {
  1573. opline->op2 = *expr;
  1574. } else {
  1575. opline->op2.u.constant.type = IS_LONG;
  1576. opline->op2.u.constant.value.lval = 1;
  1577. INIT_PZVAL(&opline->op2.u.constant);
  1578. opline->op2.op_type = IS_CONST;
  1579. }
  1580. }
  1581. void zend_do_switch_cond(znode *cond TSRMLS_DC)
  1582. {
  1583. zend_switch_entry switch_entry;
  1584. zend_op *opline;
  1585. /* Initialize the conditional value */
  1586. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1587. opline->opcode = ZEND_BOOL;
  1588. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  1589. opline->result.op_type = IS_TMP_VAR;
  1590. opline->op1.op_type = IS_CONST;
  1591. opline->op1.u.constant.type = IS_BOOL;
  1592. opline->op1.u.constant.value.lval = 0;
  1593. INIT_PZVAL(&opline->op1.u.constant);
  1594. SET_UNUSED(opline->op2);
  1595. switch_entry.cond = *cond;
  1596. switch_entry.default_case = -1;
  1597. switch_entry.control_var = opline->result.u.var;
  1598. zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
  1599. do_begin_loop(TSRMLS_C);
  1600. INC_BPC(CG(active_op_array));
  1601. }
  1602. void zend_do_switch_end(znode *case_list TSRMLS_DC)
  1603. {
  1604. zend_op *opline;
  1605. zend_switch_entry *switch_entry_ptr;
  1606. zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
  1607. if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
  1608. int next_op_number = get_next_op_number(CG(active_op_array));
  1609. CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
  1610. }
  1611. /* add code to jmp to default case */
  1612. if (switch_entry_ptr->default_case != -1) {
  1613. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1614. opline->opcode = ZEND_JMPZ;
  1615. opline->op1.op_type = IS_TMP_VAR;
  1616. opline->op1.u.var = switch_entry_ptr->control_var;
  1617. opline->op2.u.opline_num = switch_entry_ptr->default_case;
  1618. SET_UNUSED(opline->op2);
  1619. }
  1620. /* remember break/continue loop information */
  1621. CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
  1622. CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
  1623. if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
  1624. /* emit free for the switch condition*/
  1625. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1626. opline->opcode = ZEND_SWITCH_FREE;
  1627. opline->op1 = switch_entry_ptr->cond;
  1628. SET_UNUSED(opline->op2);
  1629. }
  1630. if (switch_entry_ptr->cond.op_type == IS_CONST) {
  1631. zval_dtor(&switch_entry_ptr->cond.u.constant);
  1632. }
  1633. zend_stack_del_top(&CG(switch_cond_stack));
  1634. DEC_BPC(CG(active_op_array));
  1635. }
  1636. void zend_do_case_before_statement(znode *case_list, znode *case_token, znode *case_expr TSRMLS_DC)
  1637. {
  1638. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1639. int next_op_number;
  1640. zend_switch_entry *switch_entry_ptr;
  1641. znode result;
  1642. zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
  1643. opline->opcode = ZEND_CASE;
  1644. opline->result.u.var = switch_entry_ptr->control_var;
  1645. opline->result.op_type = IS_TMP_VAR;
  1646. opline->op1 = switch_entry_ptr->cond;
  1647. opline->op2 = *case_expr;
  1648. if (opline->op1.op_type == IS_CONST) {
  1649. zval_copy_ctor(&opline->op1.u.constant);
  1650. }
  1651. result = opline->result;
  1652. next_op_number = get_next_op_number(CG(active_op_array));
  1653. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1654. opline->opcode = ZEND_JMPZ;
  1655. opline->op1 = result;
  1656. SET_UNUSED(opline->op2);
  1657. case_token->u.opline_num = next_op_number;
  1658. if (case_list->op_type==IS_UNUSED) {
  1659. return;
  1660. }
  1661. next_op_number = get_next_op_number(CG(active_op_array));
  1662. CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
  1663. }
  1664. void zend_do_case_after_statement(znode *result, znode *case_token TSRMLS_DC)
  1665. {
  1666. int next_op_number = get_next_op_number(CG(active_op_array));
  1667. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1668. opline->opcode = ZEND_JMP;
  1669. SET_UNUSED(opline->op1);
  1670. SET_UNUSED(opline->op2);
  1671. result->u.opline_num = next_op_number;
  1672. switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) {
  1673. case ZEND_JMP:
  1674. CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
  1675. break;
  1676. case ZEND_JMPZ:
  1677. CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  1678. break;
  1679. }
  1680. }
  1681. void zend_do_default_before_statement(znode *case_list, znode *default_token TSRMLS_DC)
  1682. {
  1683. int next_op_number = get_next_op_number(CG(active_op_array));
  1684. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1685. zend_switch_entry *switch_entry_ptr;
  1686. zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
  1687. opline->opcode = ZEND_JMP;
  1688. SET_UNUSED(opline->op1);
  1689. SET_UNUSED(opline->op2);
  1690. default_token->u.opline_num = next_op_number;
  1691. next_op_number = get_next_op_number(CG(active_op_array));
  1692. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1693. opline->opcode = ZEND_BOOL;
  1694. opline->result.u.var = switch_entry_ptr->control_var;
  1695. opline->result.op_type = IS_TMP_VAR;
  1696. opline->op1.op_type = IS_CONST;
  1697. opline->op1.u.constant.type = IS_BOOL;
  1698. opline->op1.u.constant.value.lval = 1;
  1699. INIT_PZVAL(&opline->op1.u.constant);
  1700. SET_UNUSED(opline->op2);
  1701. switch_entry_ptr->default_case = next_op_number;
  1702. if (case_list->op_type==IS_UNUSED) {
  1703. return;
  1704. }
  1705. next_op_number = get_next_op_number(CG(active_op_array));
  1706. CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
  1707. }
  1708. void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC)
  1709. {
  1710. zend_op *opline;
  1711. int doing_inheritance = 0;
  1712. zend_class_entry *new_class_entry = emalloc(sizeof(zend_class_entry));
  1713. class_token->u.previously_active_class_entry = CG(active_class_entry);
  1714. new_class_entry->type = ZEND_USER_CLASS;
  1715. if (CG(active_class_entry)) {
  1716. new_class_entry->name_length = sizeof("::")-1 + class_name->u.constant.value.str.len + CG(active_class_entry)->name_length;
  1717. new_class_entry->name = emalloc(new_class_entry->name_length+1);
  1718. strcpy(new_class_entry->name, CG(active_class_entry)->name);
  1719. strcat(new_class_entry->name, "::");
  1720. strcat(new_class_entry->name, class_name->u.constant.value.str.val);
  1721. STR_FREE(class_name->u.constant.value.str.val);
  1722. } else {
  1723. new_class_entry->name = class_name->u.constant.value.str.val;
  1724. new_class_entry->name_length = class_name->u.constant.value.str.len;
  1725. }
  1726. new_class_entry->refcount = 1;
  1727. new_class_entry->constants_updated = 0;
  1728. new_class_entry->ce_flags = 0;
  1729. zend_str_tolower(new_class_entry->name, new_class_entry->name_length);
  1730. zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0);
  1731. zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0);
  1732. zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
  1733. zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
  1734. zend_hash_init(&new_class_entry->protected_properties, 10, NULL, ZVAL_PTR_DTOR, 0);
  1735. ALLOC_HASHTABLE(new_class_entry->static_members);
  1736. zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0);
  1737. zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0);
  1738. new_class_entry->constructor = NULL;
  1739. new_class_entry->destructor = NULL;
  1740. new_class_entry->clone = NULL;
  1741. new_class_entry->__get = NULL;
  1742. new_class_entry->__set = NULL;
  1743. new_class_entry->__call = NULL;
  1744. new_class_entry->create_object = NULL;
  1745. new_class_entry->handle_function_call = NULL;
  1746. new_class_entry->handle_property_set = NULL;
  1747. new_class_entry->handle_property_get = NULL;
  1748. new_class_entry->parent = NULL;
  1749. if (parent_class_name->op_type != IS_UNUSED) {
  1750. doing_inheritance = 1;
  1751. }
  1752. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1753. opline->op1.op_type = IS_CONST;
  1754. build_runtime_defined_function_key(&opline->op1.u.constant, new_class_entry->name, new_class_entry->name_length, opline TSRMLS_CC);
  1755. opline->op2.op_type = IS_CONST;
  1756. opline->op2.u.constant.type = IS_STRING;
  1757. opline->op2.u.constant.refcount = 1;
  1758. if (doing_inheritance) {
  1759. opline->extended_value = parent_class_name->u.var;
  1760. opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
  1761. } else {
  1762. opline->opcode = ZEND_DECLARE_CLASS;
  1763. }
  1764. opline->op2.u.constant.value.str.val = estrndup(new_class_entry->name, new_class_entry->name_length);
  1765. opline->op2.u.constant.value.str.len = new_class_entry->name_length;
  1766. zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL);
  1767. CG(active_class_entry) = new_class_entry;
  1768. }
  1769. void zend_do_end_class_declaration(znode *class_token TSRMLS_DC)
  1770. {
  1771. do_inherit_parent_constructor(CG(active_class_entry));
  1772. CG(active_class_entry) = class_token->u.previously_active_class_entry;
  1773. if (CG(active_ce_parent_class_name).value.str.val) {
  1774. efree(CG(active_ce_parent_class_name).value.str.val);
  1775. CG(active_ce_parent_class_name).value.str.val = NULL;
  1776. }
  1777. }
  1778. void mangle_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length)
  1779. {
  1780. char *prop_name;
  1781. int prop_name_length;
  1782. prop_name_length = 1 + src1_length + 1 + src2_length;
  1783. prop_name = emalloc(prop_name_length+1);
  1784. prop_name[0] = '\0';
  1785. memcpy(prop_name + 1, src1, src1_length+1);
  1786. memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1);
  1787. *dest = prop_name;
  1788. *dest_length = prop_name_length;
  1789. }
  1790. void zend_do_declare_property(znode *var_name, znode *value TSRMLS_DC)
  1791. {
  1792. zval *property;
  1793. ALLOC_ZVAL(property);
  1794. if (value) {
  1795. *property = value->u.constant;
  1796. } else {
  1797. INIT_PZVAL(property);
  1798. property->type = IS_NULL;
  1799. }
  1800. switch (CG(access_type)) {
  1801. case ZEND_ACC_PRIVATE:
  1802. {
  1803. char *priv_name;
  1804. int priv_name_length;
  1805. mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
  1806. zend_hash_update(&CG(active_class_entry)->default_properties, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
  1807. efree(priv_name);
  1808. property->refcount++;
  1809. zend_hash_update(&CG(active_class_entry)->private_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
  1810. break;
  1811. }
  1812. case ZEND_ACC_PROTECTED:
  1813. {
  1814. char *prot_name;
  1815. int prot_name_length;
  1816. zval **found = NULL;
  1817. if (CG(active_class_entry)->parent) {
  1818. zend_hash_find(&CG(active_class_entry)->parent->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &found);
  1819. }
  1820. mangle_property_name(&prot_name, &prot_name_length, "*", 1, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len);
  1821. /* If we don't have a value and it exists in our parent then use the parent's value */
  1822. if (!value && found) {
  1823. (*found)->refcount++;
  1824. zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, found, sizeof(zval *), NULL);
  1825. (*found)->refcount++;
  1826. zend_hash_update(&CG(active_class_entry)->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, found, sizeof(zval *), NULL);
  1827. zval_ptr_dtor(&property);
  1828. } else {
  1829. zend_hash_update(&CG(active_class_entry)->default_properties, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
  1830. property->refcount++;
  1831. zend_hash_update(&CG(active_class_entry)->protected_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
  1832. }
  1833. efree(prot_name);
  1834. break;
  1835. }
  1836. case ZEND_ACC_PUBLIC:
  1837. zend_hash_update(&CG(active_class_entry)->default_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
  1838. break;
  1839. case ZEND_ACC_STATIC:
  1840. zend_hash_update(CG(active_class_entry)->static_members, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
  1841. break;
  1842. }
  1843. FREE_PNODE(var_name);
  1844. }
  1845. void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC)
  1846. {
  1847. zval *property;
  1848. ALLOC_ZVAL(property);
  1849. if (value) {
  1850. *property = value->u.constant;
  1851. } else {
  1852. INIT_PZVAL(property);
  1853. property->type = IS_NULL;
  1854. }
  1855. zend_hash_update(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL);
  1856. FREE_PNODE(var_name);
  1857. }
  1858. void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC)
  1859. {
  1860. zend_op opline;
  1861. zend_llist *fetch_list_ptr;
  1862. zend_op *opline_ptr=NULL;
  1863. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  1864. if (fetch_list_ptr->count == 1) {
  1865. zend_llist_element *le;
  1866. le = fetch_list_ptr->head;
  1867. opline_ptr = (zend_op *) le->data;
  1868. if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) &&
  1869. (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) &&
  1870. !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) {
  1871. efree(opline_ptr->op1.u.constant.value.str.val);
  1872. SET_UNUSED(opline_ptr->op1); /* this means $this for objects */
  1873. opline_ptr->op2 = *property;
  1874. /* if it was usual fetch, we change it to object fetch */
  1875. switch (opline_ptr->opcode) {
  1876. case ZEND_FETCH_W:
  1877. opline_ptr->opcode = ZEND_FETCH_OBJ_W;
  1878. break;
  1879. case ZEND_FETCH_R:
  1880. opline_ptr->opcode = ZEND_FETCH_OBJ_R;
  1881. break;
  1882. case ZEND_FETCH_RW:
  1883. opline_ptr->opcode = ZEND_FETCH_OBJ_RW;
  1884. break;
  1885. case ZEND_FETCH_IS:
  1886. opline_ptr->opcode = ZEND_FETCH_OBJ_IS;
  1887. break;
  1888. case ZEND_FETCH_UNSET:
  1889. opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET;
  1890. break;
  1891. case ZEND_FETCH_FUNC_ARG:
  1892. opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG;
  1893. break;
  1894. }
  1895. if (CG(active_class_entry) && (opline_ptr->op2.op_type == IS_CONST)) {
  1896. if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
  1897. char *priv_name;
  1898. int priv_name_length;
  1899. mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
  1900. STR_FREE(opline_ptr->op2.u.constant.value.str.val);
  1901. opline_ptr->op2.u.constant.value.str.val = priv_name;
  1902. opline_ptr->op2.u.constant.value.str.len = priv_name_length;
  1903. } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
  1904. char *prot_name;
  1905. int prot_name_length;
  1906. mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
  1907. STR_FREE(opline_ptr->op2.u.constant.value.str.val);
  1908. opline_ptr->op2.u.constant.value.str.val = prot_name;
  1909. opline_ptr->op2.u.constant.value.str.len = prot_name_length;
  1910. }
  1911. }
  1912. *result = opline_ptr->result;
  1913. return;
  1914. }
  1915. }
  1916. init_op(&opline TSRMLS_CC);
  1917. opline.opcode = ZEND_FETCH_OBJ_W; /* the backpatching routine assumes W */
  1918. opline.result.op_type = IS_VAR;
  1919. opline.result.u.EA.type = 0;
  1920. opline.result.u.var = get_temporary_variable(CG(active_op_array));
  1921. opline.op1 = *object;
  1922. opline.op2 = *property;
  1923. *result = opline.result;
  1924. if (CG(in_clone_method)) {
  1925. if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) &&
  1926. (opline_ptr->op1.u.constant.value.str.len == (sizeof("that")-1)) &&
  1927. !memcmp(opline_ptr->op1.u.constant.value.str.val, "that", sizeof("that"))) {
  1928. if (CG(active_class_entry) && (opline.op2.op_type == IS_CONST)) {
  1929. if (zend_hash_exists(&CG(active_class_entry)->private_properties, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len+1)) {
  1930. char *priv_name;
  1931. int priv_name_length;
  1932. mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len);
  1933. STR_FREE(opline.op2.u.constant.value.str.val);
  1934. opline.op2.u.constant.value.str.val = priv_name;
  1935. opline.op2.u.constant.value.str.len = priv_name_length;
  1936. } else if (zend_hash_exists(&CG(active_class_entry)->protected_properties, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len+1)) {
  1937. char *prot_name;
  1938. int prot_name_length;
  1939. mangle_property_name(&prot_name, &prot_name_length, "*", 1, opline.op2.u.constant.value.str.val, opline.op2.u.constant.value.str.len);
  1940. STR_FREE(opline.op2.u.constant.value.str.val);
  1941. opline.op2.u.constant.value.str.val = prot_name;
  1942. opline.op2.u.constant.value.str.len = prot_name_length;
  1943. }
  1944. }
  1945. }
  1946. }
  1947. zend_llist_add_element(fetch_list_ptr, &opline);
  1948. }
  1949. void zend_do_push_object(znode *object TSRMLS_DC)
  1950. {
  1951. zend_stack_push(&CG(object_stack), object, sizeof(znode));
  1952. }
  1953. void zend_do_pop_object(znode *object TSRMLS_DC)
  1954. {
  1955. znode *tmp;
  1956. zend_stack_top(&CG(object_stack), (void **) &tmp);
  1957. *object = *tmp;
  1958. zend_stack_del_top(&CG(object_stack));
  1959. }
  1960. void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC)
  1961. {
  1962. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1963. unsigned char *ptr = NULL;
  1964. opline->opcode = ZEND_NEW;
  1965. opline->result.op_type = IS_VAR;
  1966. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  1967. opline->op1 = *class_type;
  1968. SET_UNUSED(opline->op2);
  1969. new_token->u.opline_num = get_next_op_number(CG(active_op_array));
  1970. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1971. opline->opcode = ZEND_JMP_NO_CTOR;
  1972. opline->op1 = (opline-1)->result;
  1973. SET_UNUSED(opline->op2);
  1974. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1975. opline->opcode = ZEND_INIT_CTOR_CALL;
  1976. opline->op1 = (opline-2)->result;
  1977. SET_UNUSED(opline->op2);
  1978. zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *));
  1979. }
  1980. void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC)
  1981. {
  1982. znode ctor_result;
  1983. zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
  1984. zend_do_free(&ctor_result TSRMLS_CC);
  1985. CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  1986. *result = CG(active_op_array)->opcodes[new_token->u.opline_num].op1;
  1987. }
  1988. void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC)
  1989. {
  1990. switch (mode) {
  1991. case ZEND_CT:
  1992. if (constant_container) {
  1993. do_fetch_class_name(NULL, constant_container, constant_name, 1 TSRMLS_CC);
  1994. *result = *constant_container;
  1995. } else {
  1996. *result = *constant_name;
  1997. }
  1998. result->u.constant.type = IS_CONSTANT;
  1999. break;
  2000. case ZEND_RT:
  2001. {
  2002. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2003. opline->opcode = ZEND_FETCH_CONSTANT;
  2004. opline->result.op_type = IS_TMP_VAR;
  2005. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2006. if (constant_container) {
  2007. opline->op1 = *constant_container;
  2008. } else {
  2009. SET_UNUSED(opline->op1);
  2010. }
  2011. opline->op2 = *constant_name;
  2012. *result = opline->result;
  2013. }
  2014. break;
  2015. }
  2016. }
  2017. void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC)
  2018. {
  2019. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2020. switch (cmd->op_type) {
  2021. case IS_TMP_VAR:
  2022. opline->opcode = ZEND_SEND_VAL;
  2023. break;
  2024. default:
  2025. opline->opcode = ZEND_SEND_VAR;
  2026. break;
  2027. }
  2028. opline->op1 = *cmd;
  2029. opline->op2.u.opline_num = 0;
  2030. opline->extended_value = ZEND_DO_FCALL;
  2031. SET_UNUSED(opline->op2);
  2032. /* FIXME: exception support not added to this op2 */
  2033. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2034. opline->opcode = ZEND_DO_FCALL;
  2035. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2036. opline->result.op_type = IS_VAR;
  2037. opline->op1.u.constant.value.str.val = estrndup("shell_exec", sizeof("shell_exec")-1);
  2038. opline->op1.u.constant.value.str.len = sizeof("shell_exec")-1;
  2039. INIT_PZVAL(&opline->op1.u.constant);
  2040. opline->op1.u.constant.type = IS_STRING;
  2041. opline->op1.op_type = IS_CONST;
  2042. opline->extended_value = 1;
  2043. SET_UNUSED(opline->op2);
  2044. *result = opline->result;
  2045. }
  2046. void zend_do_init_array(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC)
  2047. {
  2048. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2049. opline->opcode = ZEND_INIT_ARRAY;
  2050. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2051. opline->result.op_type = IS_TMP_VAR;
  2052. *result = opline->result;
  2053. if (expr) {
  2054. opline->op1 = *expr;
  2055. if (offset) {
  2056. opline->op2 = *offset;
  2057. } else {
  2058. SET_UNUSED(opline->op2);
  2059. }
  2060. } else {
  2061. SET_UNUSED(opline->op1);
  2062. SET_UNUSED(opline->op2);
  2063. }
  2064. opline->extended_value = is_ref;
  2065. }
  2066. void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_bool is_ref TSRMLS_DC)
  2067. {
  2068. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2069. opline->opcode = ZEND_ADD_ARRAY_ELEMENT;
  2070. opline->result = *result;
  2071. opline->op1 = *expr;
  2072. if (offset) {
  2073. opline->op2 = *offset;
  2074. } else {
  2075. SET_UNUSED(opline->op2);
  2076. }
  2077. opline->extended_value = is_ref;
  2078. }
  2079. void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr)
  2080. {
  2081. zval *element;
  2082. ALLOC_ZVAL(element);
  2083. *element = expr->u.constant;
  2084. if (offset) {
  2085. switch (offset->u.constant.type) {
  2086. case IS_CONSTANT:
  2087. /* Ugly hack to denote that this value has a constant index */
  2088. element->type |= IS_CONSTANT_INDEX;
  2089. /* break missing intentionally */
  2090. case IS_STRING:
  2091. zend_hash_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL);
  2092. zval_dtor(&offset->u.constant);
  2093. break;
  2094. case IS_LONG:
  2095. zend_hash_index_update(result->u.constant.value.ht, offset->u.constant.value.lval, &element, sizeof(zval *), NULL);
  2096. break;
  2097. }
  2098. } else {
  2099. zend_hash_next_index_insert(result->u.constant.value.ht, &element, sizeof(zval *), NULL);
  2100. }
  2101. }
  2102. void zend_do_add_list_element(znode *element TSRMLS_DC)
  2103. {
  2104. list_llist_element lle;
  2105. if (element) {
  2106. zend_check_writable_variable(element);
  2107. lle.var = *element;
  2108. zend_llist_copy(&lle.dimensions, &CG(dimension_llist));
  2109. zend_llist_prepend_element(&CG(list_llist), &lle);
  2110. }
  2111. (*((int *)CG(dimension_llist).tail->data))++;
  2112. }
  2113. void zend_do_new_list_begin(TSRMLS_D)
  2114. {
  2115. int current_dimension = 0;
  2116. zend_llist_add_element(&CG(dimension_llist), &current_dimension);
  2117. }
  2118. void zend_do_new_list_end(TSRMLS_D)
  2119. {
  2120. zend_llist_remove_tail(&CG(dimension_llist));
  2121. (*((int *)CG(dimension_llist).tail->data))++;
  2122. }
  2123. void zend_do_list_init(TSRMLS_D)
  2124. {
  2125. zend_stack_push(&CG(list_stack), &CG(list_llist), sizeof(zend_llist));
  2126. zend_stack_push(&CG(list_stack), &CG(dimension_llist), sizeof(zend_llist));
  2127. zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
  2128. zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
  2129. zend_do_new_list_begin(TSRMLS_C);
  2130. }
  2131. void zend_do_list_end(znode *result, znode *expr TSRMLS_DC)
  2132. {
  2133. zend_llist_element *le;
  2134. zend_llist_element *dimension;
  2135. zend_op *opline;
  2136. znode last_container;
  2137. le = CG(list_llist).head;
  2138. while (le) {
  2139. zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions;
  2140. dimension = tmp_dimension_llist->head;
  2141. while (dimension) {
  2142. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2143. if (dimension == tmp_dimension_llist->head) { /* first */
  2144. last_container = *expr;
  2145. switch (expr->op_type) {
  2146. case IS_VAR:
  2147. opline->opcode = ZEND_FETCH_DIM_R;
  2148. break;
  2149. case IS_TMP_VAR:
  2150. opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
  2151. break;
  2152. case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */
  2153. zval_copy_ctor(&expr->u.constant);
  2154. opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
  2155. break;
  2156. }
  2157. } else {
  2158. opline->opcode = ZEND_FETCH_DIM_R;
  2159. }
  2160. opline->result.op_type = IS_VAR;
  2161. opline->result.u.EA.type = 0;
  2162. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2163. opline->op1 = last_container;
  2164. opline->op2.op_type = IS_CONST;
  2165. opline->op2.u.constant.type = IS_LONG;
  2166. opline->op2.u.constant.value.lval = *((int *) dimension->data);
  2167. INIT_PZVAL(&opline->op2.u.constant);
  2168. opline->extended_value = ZEND_FETCH_ADD_LOCK;
  2169. last_container = opline->result;
  2170. dimension = dimension->next;
  2171. }
  2172. ((list_llist_element *) le->data)->value = last_container;
  2173. zend_llist_destroy(&((list_llist_element *) le->data)->dimensions);
  2174. zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
  2175. zend_do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value TSRMLS_CC);
  2176. CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
  2177. le = le->next;
  2178. }
  2179. zend_llist_destroy(&CG(dimension_llist));
  2180. zend_llist_destroy(&CG(list_llist));
  2181. *result = *expr;
  2182. {
  2183. zend_llist *p;
  2184. /* restore previous lists */
  2185. zend_stack_top(&CG(list_stack), (void **) &p);
  2186. CG(dimension_llist) = *p;
  2187. zend_stack_del_top(&CG(list_stack));
  2188. zend_stack_top(&CG(list_stack), (void **) &p);
  2189. CG(list_llist) = *p;
  2190. zend_stack_del_top(&CG(list_stack));
  2191. }
  2192. }
  2193. void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC)
  2194. {
  2195. zval *tmp;
  2196. ALLOC_ZVAL(tmp);
  2197. convert_to_string(&varname->u.constant);
  2198. if (static_assignment) {
  2199. *tmp = static_assignment->u.constant;
  2200. } else {
  2201. INIT_ZVAL(*tmp);
  2202. }
  2203. if (!CG(active_op_array)->static_variables) {
  2204. ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
  2205. zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
  2206. }
  2207. zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
  2208. zval_dtor(&varname->u.constant);
  2209. }
  2210. void zend_do_fetch_global_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC)
  2211. {
  2212. zend_op *opline;
  2213. znode lval;
  2214. znode result;
  2215. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2216. opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
  2217. opline->result.op_type = IS_VAR;
  2218. opline->result.u.EA.type = 0;
  2219. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2220. opline->op1 = *varname;
  2221. SET_UNUSED(opline->op2);
  2222. opline->op2.u.EA.type = fetch_type;
  2223. result = opline->result;
  2224. if (varname->op_type == IS_CONST) {
  2225. zval_copy_ctor(&varname->u.constant);
  2226. }
  2227. fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */
  2228. zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC);
  2229. CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
  2230. }
  2231. void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC)
  2232. {
  2233. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2234. opline->opcode = ZEND_CAST;
  2235. opline->result.op_type = IS_TMP_VAR;
  2236. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2237. opline->op1 = *expr;
  2238. SET_UNUSED(opline->op2);
  2239. opline->extended_value = type;
  2240. *result = opline->result;
  2241. }
  2242. void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC)
  2243. {
  2244. zend_do_extended_fcall_begin(TSRMLS_C);
  2245. {
  2246. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2247. opline->opcode = ZEND_INCLUDE_OR_EVAL;
  2248. opline->result.op_type = IS_VAR;
  2249. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2250. opline->op1 = *op1;
  2251. SET_UNUSED(opline->op2);
  2252. opline->op2.u.constant.value.lval = type;
  2253. *result = opline->result;
  2254. if (type==ZEND_REQUIRE) {
  2255. opline->result.u.EA.type |= EXT_TYPE_UNUSED;
  2256. }
  2257. }
  2258. zend_do_extended_fcall_end(TSRMLS_C);
  2259. }
  2260. void zend_do_indirect_references(znode *result, znode *num_references, znode *variable TSRMLS_DC)
  2261. {
  2262. int i;
  2263. zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
  2264. for (i=1; i<num_references->u.constant.value.lval; i++) {
  2265. fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
  2266. *variable = *result;
  2267. }
  2268. zend_do_begin_variable_parse(TSRMLS_C);
  2269. fetch_simple_variable(result, variable, 1 TSRMLS_CC);
  2270. }
  2271. void zend_do_unset(znode *variable TSRMLS_DC)
  2272. {
  2273. zend_op *last_op;
  2274. zend_check_writable_variable(variable);
  2275. last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
  2276. switch (last_op->opcode) {
  2277. case ZEND_FETCH_UNSET:
  2278. last_op->opcode = ZEND_UNSET_VAR;
  2279. break;
  2280. case ZEND_FETCH_DIM_UNSET:
  2281. case ZEND_FETCH_OBJ_UNSET:
  2282. last_op->opcode = ZEND_UNSET_DIM_OBJ;
  2283. break;
  2284. }
  2285. }
  2286. void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC)
  2287. {
  2288. zend_op *last_op;
  2289. zend_do_end_variable_parse(BP_VAR_IS, 0 TSRMLS_CC);
  2290. zend_check_writable_variable(variable);
  2291. last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1];
  2292. switch (last_op->opcode) {
  2293. case ZEND_FETCH_IS:
  2294. last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
  2295. break;
  2296. case ZEND_FETCH_DIM_IS:
  2297. case ZEND_FETCH_OBJ_IS:
  2298. last_op->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
  2299. break;
  2300. }
  2301. last_op->result.op_type = IS_TMP_VAR;
  2302. last_op->extended_value = type;
  2303. *result = last_op->result;
  2304. }
  2305. void zend_do_is_class(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC)
  2306. {
  2307. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2308. opline->opcode = ZEND_IS_CLASS;
  2309. opline->result.op_type = IS_TMP_VAR;
  2310. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2311. opline->op1 = *expr;
  2312. opline->op2 = *class_znode;
  2313. *result = opline->result;
  2314. }
  2315. void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC)
  2316. {
  2317. zend_op *opline;
  2318. zend_bool is_variable;
  2319. if (variable) {
  2320. if (zend_is_function_or_method_call(array)) {
  2321. is_variable = 0;
  2322. } else {
  2323. is_variable = 1;
  2324. }
  2325. zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
  2326. } else {
  2327. is_variable = 0;
  2328. }
  2329. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2330. /* Preform array reset */
  2331. opline->opcode = ZEND_FE_RESET;
  2332. opline->result.op_type = IS_VAR;
  2333. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2334. opline->op1 = *array;
  2335. SET_UNUSED(opline->op2);
  2336. opline->extended_value = is_variable;
  2337. *open_brackets_token = opline->result;
  2338. zend_stack_push(&CG(foreach_copy_stack), (void *) &opline->result, sizeof(znode));
  2339. /* save the location of the beginning of the loop (array fetching) */
  2340. foreach_token->u.opline_num = get_next_op_number(CG(active_op_array));
  2341. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2342. opline->opcode = ZEND_FE_FETCH;
  2343. opline->result.op_type = IS_TMP_VAR;
  2344. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2345. opline->op1 = *open_brackets_token;
  2346. SET_UNUSED(opline->op2);
  2347. *as_token = opline->result;
  2348. }
  2349. void zend_do_foreach_cont(znode *value, znode *key, znode *as_token TSRMLS_DC)
  2350. {
  2351. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2352. znode result_value, result_key, dummy;
  2353. if (key->op_type != IS_UNUSED) {
  2354. znode *tmp;
  2355. /* switch between the key and value... */
  2356. tmp = key;
  2357. key = value;
  2358. value = tmp;
  2359. }
  2360. opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
  2361. opline->result.op_type = IS_VAR;
  2362. opline->result.u.EA.type = 0;
  2363. opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
  2364. opline->op1 = *as_token;
  2365. opline->op2.op_type = IS_CONST;
  2366. opline->op2.u.constant.type = IS_LONG;
  2367. opline->op2.u.constant.value.lval = 0;
  2368. opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */
  2369. result_value = opline->result;
  2370. if (key->op_type != IS_UNUSED) {
  2371. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2372. opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
  2373. opline->result.op_type = IS_VAR;
  2374. opline->result.u.EA.type = 0;
  2375. opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
  2376. opline->op1 = *as_token;
  2377. opline->op2.op_type = IS_CONST;
  2378. opline->op2.u.constant.type = IS_LONG;
  2379. opline->op2.u.constant.value.lval = 1;
  2380. opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */
  2381. result_key = opline->result;
  2382. }
  2383. zend_do_assign(&dummy, value, &result_value TSRMLS_CC);
  2384. CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
  2385. if (key->op_type != IS_UNUSED) {
  2386. zend_do_assign(&dummy, key, &result_key TSRMLS_CC);
  2387. CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
  2388. }
  2389. zend_do_free(as_token TSRMLS_CC);
  2390. do_begin_loop(TSRMLS_C);
  2391. INC_BPC(CG(active_op_array));
  2392. }
  2393. void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC)
  2394. {
  2395. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2396. opline->opcode = ZEND_JMP;
  2397. opline->op1.u.opline_num = foreach_token->u.opline_num;
  2398. SET_UNUSED(opline->op1);
  2399. SET_UNUSED(opline->op2);
  2400. CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  2401. do_end_loop(foreach_token->u.opline_num TSRMLS_CC);
  2402. generate_free_foreach_copy(open_brackets_token TSRMLS_CC);
  2403. zend_stack_del_top(&CG(foreach_copy_stack));
  2404. DEC_BPC(CG(active_op_array));
  2405. }
  2406. void zend_do_declare_begin(TSRMLS_D)
  2407. {
  2408. zend_stack_push(&CG(declare_stack), &CG(declarables), sizeof(zend_declarables));
  2409. }
  2410. void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC)
  2411. {
  2412. convert_to_string(&var->u.constant);
  2413. if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
  2414. convert_to_long(&val->u.constant);
  2415. CG(declarables).ticks = val->u.constant;
  2416. }
  2417. zval_dtor(&var->u.constant);
  2418. }
  2419. void zend_do_declare_end(znode *declare_token TSRMLS_DC)
  2420. {
  2421. zend_declarables *declarables;
  2422. zend_stack_top(&CG(declare_stack), (void **) &declarables);
  2423. /* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */
  2424. if ((get_next_op_number(CG(active_op_array)) - declare_token->u.opline_num) - ((CG(declarables).ticks.value.lval)?1:0)) {
  2425. CG(declarables) = *declarables;
  2426. }
  2427. }
  2428. void zend_do_end_heredoc(TSRMLS_D)
  2429. {
  2430. int opline_num = get_next_op_number(CG(active_op_array))-1;
  2431. zend_op *opline = &CG(active_op_array)->opcodes[opline_num];
  2432. if (opline->opcode != ZEND_ADD_STRING) {
  2433. return;
  2434. }
  2435. opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
  2436. if (opline->op2.u.constant.value.str.len>0) {
  2437. if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') {
  2438. opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
  2439. }
  2440. }
  2441. }
  2442. void zend_do_exit(znode *result, znode *message TSRMLS_DC)
  2443. {
  2444. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2445. opline->opcode = ZEND_EXIT;
  2446. opline->op1 = *message;
  2447. SET_UNUSED(opline->op2);
  2448. result->op_type = IS_CONST;
  2449. result->u.constant.type = IS_BOOL;
  2450. result->u.constant.value.lval = 1;
  2451. }
  2452. void zend_do_begin_silence(znode *strudel_token TSRMLS_DC)
  2453. {
  2454. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2455. opline->opcode = ZEND_BEGIN_SILENCE;
  2456. opline->result.op_type = IS_TMP_VAR;
  2457. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2458. SET_UNUSED(opline->op1);
  2459. SET_UNUSED(opline->op2);
  2460. *strudel_token = opline->result;
  2461. }
  2462. void zend_do_end_silence(znode *strudel_token TSRMLS_DC)
  2463. {
  2464. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2465. opline->opcode = ZEND_END_SILENCE;
  2466. opline->op1 = *strudel_token;
  2467. SET_UNUSED(opline->op2);
  2468. }
  2469. void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC)
  2470. {
  2471. int jmpz_op_number = get_next_op_number(CG(active_op_array));
  2472. zend_op *opline;
  2473. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2474. opline->opcode = ZEND_JMPZ;
  2475. opline->op1 = *cond;
  2476. SET_UNUSED(opline->op2);
  2477. opline->op2.u.opline_num = jmpz_op_number;
  2478. *qm_token = opline->op2;
  2479. INC_BPC(CG(active_op_array));
  2480. }
  2481. void zend_do_qm_true(znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC)
  2482. {
  2483. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2484. CG(active_op_array)->opcodes[qm_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */
  2485. opline->opcode = ZEND_QM_ASSIGN;
  2486. opline->result.op_type = IS_TMP_VAR;
  2487. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  2488. opline->op1 = *true_value;
  2489. SET_UNUSED(opline->op2);
  2490. *qm_token = opline->result;
  2491. colon_token->u.opline_num = get_next_op_number(CG(active_op_array));
  2492. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2493. opline->opcode = ZEND_JMP;
  2494. SET_UNUSED(opline->op1);
  2495. SET_UNUSED(opline->op2);
  2496. }
  2497. void zend_do_qm_false(znode *result, znode *false_value, znode *qm_token, znode *colon_token TSRMLS_DC)
  2498. {
  2499. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2500. opline->opcode = ZEND_QM_ASSIGN;
  2501. opline->result = *qm_token;
  2502. opline->op1 = *false_value;
  2503. SET_UNUSED(opline->op2);
  2504. CG(active_op_array)->opcodes[colon_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
  2505. *result = opline->result;
  2506. DEC_BPC(CG(active_op_array));
  2507. }
  2508. void zend_do_extended_info(TSRMLS_D)
  2509. {
  2510. zend_op *opline;
  2511. if (!CG(extended_info)) {
  2512. return;
  2513. }
  2514. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2515. opline->opcode = ZEND_EXT_STMT;
  2516. SET_UNUSED(opline->op1);
  2517. SET_UNUSED(opline->op2);
  2518. }
  2519. void zend_do_extended_fcall_begin(TSRMLS_D)
  2520. {
  2521. zend_op *opline;
  2522. if (!CG(extended_info)) {
  2523. return;
  2524. }
  2525. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2526. opline->opcode = ZEND_EXT_FCALL_BEGIN;
  2527. SET_UNUSED(opline->op1);
  2528. SET_UNUSED(opline->op2);
  2529. }
  2530. void zend_do_extended_fcall_end(TSRMLS_D)
  2531. {
  2532. zend_op *opline;
  2533. if (!CG(extended_info)) {
  2534. return;
  2535. }
  2536. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2537. opline->opcode = ZEND_EXT_FCALL_END;
  2538. SET_UNUSED(opline->op1);
  2539. SET_UNUSED(opline->op2);
  2540. }
  2541. void zend_do_ticks(TSRMLS_D)
  2542. {
  2543. if (CG(declarables).ticks.value.lval) {
  2544. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  2545. opline->opcode = ZEND_TICKS;
  2546. opline->op1.u.constant = CG(declarables).ticks;
  2547. opline->op1.op_type = IS_CONST;
  2548. SET_UNUSED(opline->op2);
  2549. }
  2550. }
  2551. int zend_register_auto_global(char *name, uint name_len TSRMLS_DC)
  2552. {
  2553. return zend_hash_add_empty_element(CG(auto_globals), name, name_len+1);
  2554. }
  2555. int zendlex(znode *zendlval TSRMLS_DC)
  2556. {
  2557. int retval;
  2558. if (CG(increment_lineno)) {
  2559. CG(zend_lineno)++;
  2560. CG(increment_lineno) = 0;
  2561. }
  2562. zendlval->u.constant.type = IS_LONG;
  2563. retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
  2564. switch (retval) {
  2565. case T_COMMENT:
  2566. case T_OPEN_TAG:
  2567. case T_WHITESPACE:
  2568. retval = zendlex(zendlval TSRMLS_CC);
  2569. break;
  2570. case T_CLOSE_TAG:
  2571. if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1]=='\n'
  2572. || (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-2]=='\r' && LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1])) {
  2573. CG(increment_lineno) = 1;
  2574. }
  2575. retval = ';'; /* implicit ; */
  2576. break;
  2577. case T_OPEN_TAG_WITH_ECHO:
  2578. retval = T_ECHO;
  2579. break;
  2580. case T_END_HEREDOC:
  2581. efree(zendlval->u.constant.value.str.val);
  2582. break;
  2583. }
  2584. INIT_PZVAL(&zendlval->u.constant);
  2585. zendlval->op_type = IS_CONST;
  2586. return retval;
  2587. }