PageRenderTime 54ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/Zend/zend_compile.c

http://github.com/infusion/PHP
C | 5454 lines | 4294 code | 754 blank | 406 comment | 1094 complexity | 79b2bba80d4838380d8d3483804f6547 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2011 Zend Technologies Ltd. (http://www.zend.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 2.00 of the Zend license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.zend.com/license/2_00.txt. |
  11. | If you did not receive a copy of the Zend license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@zend.com so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Andi Gutmans <andi@zend.com> |
  16. | Zeev Suraski <zeev@zend.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id: zend_compile.c 308443 2011-02-17 23:24:50Z felipe $ */
  20. #include <zend_language_parser.h>
  21. #include "zend.h"
  22. #include "zend_compile.h"
  23. #include "zend_constants.h"
  24. #include "zend_llist.h"
  25. #include "zend_API.h"
  26. #include "zend_exceptions.h"
  27. #include "tsrm_virtual_cwd.h"
  28. #ifdef ZEND_MULTIBYTE
  29. #include "zend_multibyte.h"
  30. #endif /* ZEND_MULTIBYTE */
  31. ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
  32. ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
  33. #ifndef ZTS
  34. ZEND_API zend_compiler_globals compiler_globals;
  35. ZEND_API zend_executor_globals executor_globals;
  36. #endif
  37. static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
  38. {
  39. property_info->name = estrndup(property_info->name, property_info->name_length);
  40. if (property_info->doc_comment) {
  41. property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
  42. }
  43. }
  44. /* }}} */
  45. static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
  46. {
  47. property_info->name = zend_strndup(property_info->name, property_info->name_length);
  48. }
  49. /* }}} */
  50. static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
  51. {
  52. efree(property_info->name);
  53. if (property_info->doc_comment) {
  54. efree(property_info->doc_comment);
  55. }
  56. }
  57. /* }}} */
  58. static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
  59. {
  60. free(property_info->name);
  61. }
  62. /* }}} */
  63. static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
  64. {
  65. char char_pos_buf[32];
  66. uint char_pos_len;
  67. char *filename;
  68. char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
  69. if (CG(active_op_array)->filename) {
  70. filename = CG(active_op_array)->filename;
  71. } else {
  72. filename = "-";
  73. }
  74. /* NULL, name length, filename length, last accepting char position length */
  75. result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
  76. #ifdef ZEND_MULTIBYTE
  77. /* must be binary safe */
  78. result->value.str.val = (char *) safe_emalloc(result->value.str.len, 1, 1);
  79. result->value.str.val[0] = '\0';
  80. sprintf(result->value.str.val+1, "%s%s%s", name, filename, char_pos_buf);
  81. #else
  82. zend_spprintf(&result->value.str.val, 0, "%c%s%s%s", '\0', name, filename, char_pos_buf);
  83. #endif /* ZEND_MULTIBYTE */
  84. result->type = IS_STRING;
  85. Z_SET_REFCOUNT_P(result, 1);
  86. }
  87. /* }}} */
  88. int zend_auto_global_arm(zend_auto_global *auto_global TSRMLS_DC) /* {{{ */
  89. {
  90. auto_global->armed = (auto_global->auto_global_callback ? 1 : 0);
  91. return 0;
  92. }
  93. /* }}} */
  94. ZEND_API int zend_auto_global_disable_jit(const char *varname, zend_uint varname_length TSRMLS_DC) /* {{{ */
  95. {
  96. zend_auto_global *auto_global;
  97. if (zend_hash_find(CG(auto_globals), varname, varname_length+1, (void **) &auto_global)==FAILURE) {
  98. return FAILURE;
  99. }
  100. auto_global->armed = 0;
  101. return SUCCESS;
  102. }
  103. /* }}} */
  104. static void init_compiler_declarables(TSRMLS_D) /* {{{ */
  105. {
  106. Z_TYPE(CG(declarables).ticks) = IS_LONG;
  107. Z_LVAL(CG(declarables).ticks) = 0;
  108. }
  109. /* }}} */
  110. void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
  111. {
  112. zend_stack_init(&CG(bp_stack));
  113. zend_stack_init(&CG(function_call_stack));
  114. zend_stack_init(&CG(switch_cond_stack));
  115. zend_stack_init(&CG(foreach_copy_stack));
  116. zend_stack_init(&CG(object_stack));
  117. zend_stack_init(&CG(declare_stack));
  118. CG(active_class_entry) = NULL;
  119. zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
  120. zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
  121. zend_stack_init(&CG(list_stack));
  122. CG(in_compilation) = 0;
  123. CG(start_lineno) = 0;
  124. CG(current_namespace) = NULL;
  125. CG(in_namespace) = 0;
  126. CG(has_bracketed_namespaces) = 0;
  127. CG(current_import) = NULL;
  128. init_compiler_declarables(TSRMLS_C);
  129. zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
  130. zend_stack_init(&CG(labels_stack));
  131. CG(labels) = NULL;
  132. #ifdef ZEND_MULTIBYTE
  133. CG(script_encoding_list) = NULL;
  134. CG(script_encoding_list_size) = 0;
  135. CG(internal_encoding) = NULL;
  136. CG(encoding_detector) = NULL;
  137. CG(encoding_converter) = NULL;
  138. CG(encoding_oddlen) = NULL;
  139. CG(encoding_declared) = 0;
  140. #endif /* ZEND_MULTIBYTE */
  141. }
  142. /* }}} */
  143. ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
  144. {
  145. TSRMLS_FETCH();
  146. zend_file_handle_dtor(fh TSRMLS_CC);
  147. }
  148. /* }}} */
  149. void init_compiler(TSRMLS_D) /* {{{ */
  150. {
  151. CG(active_op_array) = NULL;
  152. zend_init_compiler_data_structures(TSRMLS_C);
  153. zend_init_rsrc_list(TSRMLS_C);
  154. zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
  155. zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
  156. CG(unclean_shutdown) = 0;
  157. }
  158. /* }}} */
  159. void shutdown_compiler(TSRMLS_D) /* {{{ */
  160. {
  161. zend_stack_destroy(&CG(bp_stack));
  162. zend_stack_destroy(&CG(function_call_stack));
  163. zend_stack_destroy(&CG(switch_cond_stack));
  164. zend_stack_destroy(&CG(foreach_copy_stack));
  165. zend_stack_destroy(&CG(object_stack));
  166. zend_stack_destroy(&CG(declare_stack));
  167. zend_stack_destroy(&CG(list_stack));
  168. zend_hash_destroy(&CG(filenames_table));
  169. zend_llist_destroy(&CG(open_files));
  170. zend_stack_destroy(&CG(labels_stack));
  171. #ifdef ZEND_MULTIBYTE
  172. if (CG(script_encoding_list)) {
  173. efree(CG(script_encoding_list));
  174. }
  175. #endif /* ZEND_MULTIBYTE */
  176. }
  177. /* }}} */
  178. ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
  179. {
  180. char **pp, *p;
  181. int length = strlen(new_compiled_filename);
  182. if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
  183. CG(compiled_filename) = *pp;
  184. return *pp;
  185. }
  186. p = estrndup(new_compiled_filename, length);
  187. zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
  188. CG(compiled_filename) = p;
  189. return p;
  190. }
  191. /* }}} */
  192. ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
  193. {
  194. CG(compiled_filename) = original_compiled_filename;
  195. }
  196. /* }}} */
  197. ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
  198. {
  199. return CG(compiled_filename);
  200. }
  201. /* }}} */
  202. ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
  203. {
  204. return CG(zend_lineno);
  205. }
  206. /* }}} */
  207. ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
  208. {
  209. return CG(in_compilation);
  210. }
  211. /* }}} */
  212. static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
  213. {
  214. return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable));
  215. }
  216. /* }}} */
  217. static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ */
  218. {
  219. int i = 0;
  220. ulong hash_value = zend_inline_hash_func(name, name_len+1);
  221. while (i < op_array->last_var) {
  222. if (op_array->vars[i].hash_value == hash_value &&
  223. op_array->vars[i].name_len == name_len &&
  224. strcmp(op_array->vars[i].name, name) == 0) {
  225. efree(name);
  226. return i;
  227. }
  228. i++;
  229. }
  230. i = op_array->last_var;
  231. op_array->last_var++;
  232. if (op_array->last_var > op_array->size_var) {
  233. op_array->size_var += 16; /* FIXME */
  234. op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable));
  235. }
  236. op_array->vars[i].name = name; /* estrndup(name, name_len); */
  237. op_array->vars[i].name_len = name_len;
  238. op_array->vars[i].hash_value = hash_value;
  239. return i;
  240. }
  241. /* }}} */
  242. void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
  243. {
  244. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  245. opline->opcode = op;
  246. opline->result.op_type = IS_TMP_VAR;
  247. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  248. opline->op1 = *op1;
  249. opline->op2 = *op2;
  250. *result = opline->result;
  251. }
  252. /* }}} */
  253. void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
  254. {
  255. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  256. opline->opcode = op;
  257. opline->result.op_type = IS_TMP_VAR;
  258. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  259. opline->op1 = *op1;
  260. *result = opline->result;
  261. SET_UNUSED(opline->op2);
  262. }
  263. /* }}} */
  264. #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; }
  265. static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
  266. {
  267. data_op->opcode = ZEND_OP_DATA;
  268. data_op->op1 = *value;
  269. SET_UNUSED(data_op->op2);
  270. }
  271. /* }}} */
  272. void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
  273. {
  274. int last_op_number = get_next_op_number(CG(active_op_array));
  275. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  276. if (last_op_number > 0) {
  277. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
  278. switch (last_op->opcode) {
  279. case ZEND_FETCH_OBJ_RW:
  280. last_op->opcode = op;
  281. last_op->extended_value = ZEND_ASSIGN_OBJ;
  282. zend_do_op_data(opline, op2 TSRMLS_CC);
  283. SET_UNUSED(opline->result);
  284. *result = last_op->result;
  285. return;
  286. case ZEND_FETCH_DIM_RW:
  287. last_op->opcode = op;
  288. last_op->extended_value = ZEND_ASSIGN_DIM;
  289. zend_do_op_data(opline, op2 TSRMLS_CC);
  290. opline->op2.u.var = get_temporary_variable(CG(active_op_array));
  291. opline->op2.u.EA.type = 0;
  292. opline->op2.op_type = IS_VAR;
  293. SET_UNUSED(opline->result);
  294. *result = last_op->result;
  295. return;
  296. default:
  297. break;
  298. }
  299. }
  300. opline->opcode = op;
  301. opline->op1 = *op1;
  302. opline->op2 = *op2;
  303. opline->result.op_type = IS_VAR;
  304. opline->result.u.EA.type = 0;
  305. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  306. *result = opline->result;
  307. }
  308. /* }}} */
  309. void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
  310. {
  311. zend_op opline;
  312. zend_op *opline_ptr;
  313. zend_llist *fetch_list_ptr;
  314. if (varname->op_type == IS_CONST) {
  315. if (Z_TYPE(varname->u.constant) != IS_STRING) {
  316. convert_to_string(&varname->u.constant);
  317. }
  318. if (!zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC) &&
  319. !(varname->u.constant.value.str.len == (sizeof("this")-1) &&
  320. !memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
  321. (CG(active_op_array)->last == 0 ||
  322. CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
  323. result->op_type = IS_CV;
  324. result->u.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
  325. result->u.EA.type = 0;
  326. varname->u.constant.value.str.val = CG(active_op_array)->vars[result->u.var].name;
  327. return;
  328. }
  329. }
  330. if (bp) {
  331. opline_ptr = &opline;
  332. init_op(opline_ptr TSRMLS_CC);
  333. } else {
  334. opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
  335. }
  336. opline_ptr->opcode = op;
  337. opline_ptr->result.op_type = IS_VAR;
  338. opline_ptr->result.u.EA.type = 0;
  339. opline_ptr->result.u.var = get_temporary_variable(CG(active_op_array));
  340. opline_ptr->op1 = *varname;
  341. *result = opline_ptr->result;
  342. SET_UNUSED(opline_ptr->op2);
  343. opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
  344. if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
  345. if (zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC)) {
  346. opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
  347. }
  348. }
  349. if (bp) {
  350. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  351. zend_llist_add_element(fetch_list_ptr, opline_ptr);
  352. }
  353. }
  354. /* }}} */
  355. void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
  356. {
  357. /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
  358. fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
  359. }
  360. /* }}} */
  361. void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
  362. {
  363. znode class_node;
  364. zend_llist *fetch_list_ptr;
  365. zend_llist_element *le;
  366. zend_op *opline_ptr;
  367. zend_op opline;
  368. zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
  369. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  370. if (result->op_type == IS_CV) {
  371. init_op(&opline TSRMLS_CC);
  372. opline.opcode = ZEND_FETCH_W;
  373. opline.result.op_type = IS_VAR;
  374. opline.result.u.EA.type = 0;
  375. opline.result.u.var = get_temporary_variable(CG(active_op_array));
  376. opline.op1.op_type = IS_CONST;
  377. opline.op1.u.constant.type = IS_STRING;
  378. opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
  379. opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
  380. SET_UNUSED(opline.op2);
  381. opline.op2 = class_node;
  382. opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
  383. *result = opline.result;
  384. zend_llist_add_element(fetch_list_ptr, &opline);
  385. } else {
  386. le = fetch_list_ptr->head;
  387. opline_ptr = (zend_op *)le->data;
  388. if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1.op_type == IS_CV) {
  389. init_op(&opline TSRMLS_CC);
  390. opline.opcode = ZEND_FETCH_W;
  391. opline.result.op_type = IS_VAR;
  392. opline.result.u.EA.type = 0;
  393. opline.result.u.var = get_temporary_variable(CG(active_op_array));
  394. opline.op1.op_type = IS_CONST;
  395. opline.op1.u.constant.type = IS_STRING;
  396. opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
  397. opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
  398. SET_UNUSED(opline.op2);
  399. opline.op2 = class_node;
  400. opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
  401. opline_ptr->op1 = opline.result;
  402. zend_llist_prepend_element(fetch_list_ptr, &opline);
  403. } else {
  404. opline_ptr->op2 = class_node;
  405. opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
  406. }
  407. }
  408. }
  409. /* }}} */
  410. void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
  411. {
  412. fetch_simple_variable(result, varname, 1 TSRMLS_CC);
  413. fetch_array_dim(result, result, first_dim TSRMLS_CC);
  414. }
  415. /* }}} */
  416. void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
  417. {
  418. zend_op opline;
  419. zend_llist *fetch_list_ptr;
  420. init_op(&opline TSRMLS_CC);
  421. opline.opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */
  422. opline.result.op_type = IS_VAR;
  423. opline.result.u.EA.type = 0;
  424. opline.result.u.var = get_temporary_variable(CG(active_op_array));
  425. opline.op1 = *parent;
  426. opline.op2 = *dim;
  427. opline.extended_value = ZEND_FETCH_STANDARD;
  428. *result = opline.result;
  429. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  430. zend_llist_add_element(fetch_list_ptr, &opline);
  431. }
  432. /* }}} */
  433. void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
  434. {
  435. fetch_array_dim(result, parent, offset TSRMLS_CC);
  436. }
  437. /* }}} */
  438. void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
  439. {
  440. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  441. opline->result.op_type = IS_TMP_VAR;
  442. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  443. opline->opcode = ZEND_PRINT;
  444. opline->op1 = *arg;
  445. SET_UNUSED(opline->op2);
  446. *result = opline->result;
  447. }
  448. /* }}} */
  449. void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
  450. {
  451. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  452. opline->opcode = ZEND_ECHO;
  453. opline->op1 = *arg;
  454. SET_UNUSED(opline->op2);
  455. }
  456. /* }}} */
  457. void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
  458. {
  459. char *method_type;
  460. if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
  461. Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
  462. method_type = "Interface";
  463. } else {
  464. method_type = "Abstract";
  465. }
  466. if (modifiers->u.constant.value.lval & ZEND_ACC_ABSTRACT) {
  467. if(modifiers->u.constant.value.lval & ZEND_ACC_PRIVATE) {
  468. zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val);
  469. }
  470. if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
  471. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  472. opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
  473. SET_UNUSED(opline->op1);
  474. SET_UNUSED(opline->op2);
  475. } else {
  476. /* we had code in the function body */
  477. zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val);
  478. }
  479. } else {
  480. if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) {
  481. zend_error(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
  482. }
  483. }
  484. }
  485. /* }}} */
  486. static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
  487. {
  488. if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
  489. && (opline->op1.u.constant.type == IS_STRING)
  490. && (opline->op1.u.constant.value.str.len == (sizeof("this")-1))
  491. && !memcmp(opline->op1.u.constant.value.str.val, "this", sizeof("this"))) {
  492. return 1;
  493. } else {
  494. return 0;
  495. }
  496. }
  497. /* }}} */
  498. void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC) /* {{{ */
  499. {
  500. int last_op_number;
  501. zend_op *opline;
  502. if (value->op_type == IS_CV) {
  503. zend_llist *fetch_list_ptr;
  504. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  505. if (fetch_list_ptr && fetch_list_ptr->head) {
  506. opline = (zend_op *)fetch_list_ptr->head->data;
  507. if (opline->opcode == ZEND_FETCH_DIM_W &&
  508. opline->op1.op_type == IS_CV &&
  509. opline->op1.u.var == value->u.var) {
  510. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  511. opline->opcode = ZEND_FETCH_R;
  512. opline->result.op_type = IS_VAR;
  513. opline->result.u.EA.type = 0;
  514. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  515. opline->op1.op_type = IS_CONST;
  516. ZVAL_STRINGL(&opline->op1.u.constant,
  517. CG(active_op_array)->vars[value->u.var].name,
  518. CG(active_op_array)->vars[value->u.var].name_len, 1);
  519. SET_UNUSED(opline->op2);
  520. opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
  521. value = &opline->result;
  522. }
  523. }
  524. }
  525. zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
  526. last_op_number = get_next_op_number(CG(active_op_array));
  527. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  528. if (variable->op_type == IS_CV) {
  529. if (variable->u.var == CG(active_op_array)->this_var) {
  530. zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
  531. }
  532. } else if (variable->op_type == IS_VAR) {
  533. int n = 0;
  534. while (last_op_number - n > 0) {
  535. zend_op *last_op;
  536. last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
  537. if (last_op->result.op_type == IS_VAR &&
  538. last_op->result.u.var == variable->u.var) {
  539. if (last_op->opcode == ZEND_FETCH_OBJ_W) {
  540. if (n > 0) {
  541. int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
  542. *opline = *last_op;
  543. MAKE_NOP(last_op);
  544. /* last_op = opline; */
  545. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  546. /* get_next_op can realloc, we need to move last_op */
  547. last_op = &CG(active_op_array)->opcodes[opline_no];
  548. }
  549. last_op->opcode = ZEND_ASSIGN_OBJ;
  550. zend_do_op_data(opline, value TSRMLS_CC);
  551. SET_UNUSED(opline->result);
  552. *result = last_op->result;
  553. return;
  554. } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
  555. if (n > 0) {
  556. int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
  557. *opline = *last_op;
  558. MAKE_NOP(last_op);
  559. /* last_op = opline; */
  560. /* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
  561. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  562. /* get_next_op can realloc, we need to move last_op */
  563. last_op = &CG(active_op_array)->opcodes[opline_no];
  564. }
  565. last_op->opcode = ZEND_ASSIGN_DIM;
  566. zend_do_op_data(opline, value TSRMLS_CC);
  567. opline->op2.u.var = get_temporary_variable(CG(active_op_array));
  568. opline->op2.u.EA.type = 0;
  569. opline->op2.op_type = IS_VAR;
  570. SET_UNUSED(opline->result);
  571. *result = last_op->result;
  572. return;
  573. } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
  574. zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
  575. } else {
  576. break;
  577. }
  578. }
  579. n++;
  580. }
  581. }
  582. opline->opcode = ZEND_ASSIGN;
  583. opline->op1 = *variable;
  584. opline->op2 = *value;
  585. opline->result.op_type = IS_VAR;
  586. opline->result.u.EA.type = 0;
  587. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  588. *result = opline->result;
  589. }
  590. /* }}} */
  591. static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
  592. {
  593. zend_uint type = variable->u.EA.type;
  594. return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
  595. }
  596. /* }}} */
  597. void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
  598. {
  599. zend_op *opline;
  600. if (lvar->op_type == IS_CV) {
  601. if (lvar->u.var == CG(active_op_array)->this_var) {
  602. zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
  603. }
  604. } else if (lvar->op_type == IS_VAR) {
  605. int last_op_number = get_next_op_number(CG(active_op_array));
  606. if (last_op_number > 0) {
  607. opline = &CG(active_op_array)->opcodes[last_op_number-1];
  608. if (opline_is_fetch_this(opline TSRMLS_CC)) {
  609. zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
  610. }
  611. }
  612. }
  613. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  614. opline->opcode = ZEND_ASSIGN_REF;
  615. if (zend_is_function_or_method_call(rvar)) {
  616. opline->extended_value = ZEND_RETURNS_FUNCTION;
  617. } else if (rvar->u.EA.type & ZEND_PARSED_NEW) {
  618. opline->extended_value = ZEND_RETURNS_NEW;
  619. } else {
  620. opline->extended_value = 0;
  621. }
  622. if (result) {
  623. opline->result.op_type = IS_VAR;
  624. opline->result.u.EA.type = 0;
  625. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  626. *result = opline->result;
  627. } else {
  628. /* SET_UNUSED(opline->result); */
  629. opline->result.u.EA.type |= EXT_TYPE_UNUSED;
  630. }
  631. opline->op1 = *lvar;
  632. opline->op2 = *rvar;
  633. }
  634. /* }}} */
  635. static inline void do_begin_loop(TSRMLS_D) /* {{{ */
  636. {
  637. zend_brk_cont_element *brk_cont_element;
  638. int parent;
  639. parent = CG(active_op_array)->current_brk_cont;
  640. CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont;
  641. brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
  642. brk_cont_element->start = get_next_op_number(CG(active_op_array));
  643. brk_cont_element->parent = parent;
  644. }
  645. /* }}} */
  646. static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
  647. {
  648. if (!has_loop_var) {
  649. /* The start fileld is used to free temporary variables in case of exceptions.
  650. * We won't try to free something of we don't have loop variable.
  651. */
  652. CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
  653. }
  654. CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
  655. CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
  656. CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
  657. }
  658. /* }}} */
  659. void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
  660. {
  661. int while_cond_op_number = get_next_op_number(CG(active_op_array));
  662. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  663. opline->opcode = ZEND_JMPZ;
  664. opline->op1 = *expr;
  665. close_bracket_token->u.opline_num = while_cond_op_number;
  666. SET_UNUSED(opline->op2);
  667. do_begin_loop(TSRMLS_C);
  668. INC_BPC(CG(active_op_array));
  669. }
  670. /* }}} */
  671. void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
  672. {
  673. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  674. /* add unconditional jump */
  675. opline->opcode = ZEND_JMP;
  676. opline->op1.u.opline_num = while_token->u.opline_num;
  677. SET_UNUSED(opline->op1);
  678. SET_UNUSED(opline->op2);
  679. /* update while's conditional jmp */
  680. CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  681. do_end_loop(while_token->u.opline_num, 0 TSRMLS_CC);
  682. DEC_BPC(CG(active_op_array));
  683. }
  684. /* }}} */
  685. void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
  686. {
  687. int for_cond_op_number = get_next_op_number(CG(active_op_array));
  688. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  689. opline->opcode = ZEND_JMPZNZ;
  690. opline->op1 = *expr; /* the conditional expression */
  691. second_semicolon_token->u.opline_num = for_cond_op_number;
  692. SET_UNUSED(opline->op2);
  693. }
  694. /* }}} */
  695. void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
  696. {
  697. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  698. opline->opcode = ZEND_JMP;
  699. opline->op1.u.opline_num = cond_start->u.opline_num;
  700. CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array));
  701. SET_UNUSED(opline->op1);
  702. SET_UNUSED(opline->op2);
  703. do_begin_loop(TSRMLS_C);
  704. INC_BPC(CG(active_op_array));
  705. }
  706. /* }}} */
  707. void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
  708. {
  709. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  710. opline->opcode = ZEND_JMP;
  711. opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1;
  712. CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
  713. SET_UNUSED(opline->op1);
  714. SET_UNUSED(opline->op2);
  715. do_end_loop(second_semicolon_token->u.opline_num+1, 0 TSRMLS_CC);
  716. DEC_BPC(CG(active_op_array));
  717. }
  718. /* }}} */
  719. void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
  720. {
  721. int last_op_number = get_next_op_number(CG(active_op_array));
  722. zend_op *opline;
  723. if (last_op_number > 0) {
  724. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
  725. if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
  726. last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
  727. last_op->result.op_type = IS_VAR;
  728. last_op->result.u.EA.type = 0;
  729. last_op->result.u.var = get_temporary_variable(CG(active_op_array));
  730. *result = last_op->result;
  731. return;
  732. }
  733. }
  734. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  735. opline->opcode = op;
  736. opline->op1 = *op1;
  737. SET_UNUSED(opline->op2);
  738. opline->result.op_type = IS_VAR;
  739. opline->result.u.EA.type = 0;
  740. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  741. *result = opline->result;
  742. }
  743. /* }}} */
  744. void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
  745. {
  746. int last_op_number = get_next_op_number(CG(active_op_array));
  747. zend_op *opline;
  748. if (last_op_number > 0) {
  749. zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
  750. if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
  751. last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
  752. last_op->result.op_type = IS_TMP_VAR;
  753. last_op->result.u.var = get_temporary_variable(CG(active_op_array));
  754. *result = last_op->result;
  755. return;
  756. }
  757. }
  758. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  759. opline->opcode = op;
  760. opline->op1 = *op1;
  761. SET_UNUSED(opline->op2);
  762. opline->result.op_type = IS_TMP_VAR;
  763. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  764. *result = opline->result;
  765. }
  766. /* }}} */
  767. void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
  768. {
  769. int if_cond_op_number = get_next_op_number(CG(active_op_array));
  770. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  771. opline->opcode = ZEND_JMPZ;
  772. opline->op1 = *cond;
  773. closing_bracket_token->u.opline_num = if_cond_op_number;
  774. SET_UNUSED(opline->op2);
  775. INC_BPC(CG(active_op_array));
  776. }
  777. /* }}} */
  778. void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
  779. {
  780. int if_end_op_number = get_next_op_number(CG(active_op_array));
  781. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  782. zend_llist *jmp_list_ptr;
  783. opline->opcode = ZEND_JMP;
  784. /* save for backpatching */
  785. if (initialize) {
  786. zend_llist jmp_list;
  787. zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
  788. zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
  789. }
  790. zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
  791. zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
  792. CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1;
  793. SET_UNUSED(opline->op1);
  794. SET_UNUSED(opline->op2);
  795. }
  796. /* }}} */
  797. void zend_do_if_end(TSRMLS_D) /* {{{ */
  798. {
  799. int next_op_number = get_next_op_number(CG(active_op_array));
  800. zend_llist *jmp_list_ptr;
  801. zend_llist_element *le;
  802. zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
  803. for (le=jmp_list_ptr->head; le; le = le->next) {
  804. CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number;
  805. }
  806. zend_llist_destroy(jmp_list_ptr);
  807. zend_stack_del_top(&CG(bp_stack));
  808. DEC_BPC(CG(active_op_array));
  809. }
  810. /* }}} */
  811. void zend_check_writable_variable(const znode *variable) /* {{{ */
  812. {
  813. zend_uint type = variable->u.EA.type;
  814. if (type & ZEND_PARSED_METHOD_CALL) {
  815. zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
  816. }
  817. if (type == ZEND_PARSED_FUNCTION_CALL) {
  818. zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
  819. }
  820. }
  821. /* }}} */
  822. void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
  823. {
  824. zend_llist fetch_list;
  825. zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
  826. zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
  827. }
  828. /* }}} */
  829. void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
  830. {
  831. zend_llist *fetch_list_ptr;
  832. zend_llist_element *le;
  833. zend_op *opline = NULL;
  834. zend_op *opline_ptr;
  835. zend_uint this_var = -1;
  836. zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
  837. le = fetch_list_ptr->head;
  838. /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
  839. if (le) {
  840. opline_ptr = (zend_op *)le->data;
  841. if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
  842. /* convert to FETCH_?(this) into IS_CV */
  843. if (CG(active_op_array)->last == 0 ||
  844. CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
  845. this_var = opline_ptr->result.u.var;
  846. if (CG(active_op_array)->this_var == -1) {
  847. CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(opline_ptr->op1.u.constant), Z_STRLEN(opline_ptr->op1.u.constant));
  848. } else {
  849. efree(Z_STRVAL(opline_ptr->op1.u.constant));
  850. }
  851. le = le->next;
  852. if (variable->op_type == IS_VAR &&
  853. variable->u.var == this_var) {
  854. variable->op_type = IS_CV;
  855. variable->u.var = CG(active_op_array)->this_var;
  856. }
  857. } else if (CG(active_op_array)->this_var == -1) {
  858. CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1);
  859. }
  860. }
  861. while (le) {
  862. opline_ptr = (zend_op *)le->data;
  863. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  864. memcpy(opline, opline_ptr, sizeof(zend_op));
  865. if (opline->op1.op_type == IS_VAR &&
  866. opline->op1.u.var == this_var) {
  867. opline->op1.op_type = IS_CV;
  868. opline->op1.u.var = CG(active_op_array)->this_var;
  869. }
  870. switch (type) {
  871. case BP_VAR_R:
  872. if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
  873. zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
  874. }
  875. opline->opcode -= 3;
  876. break;
  877. case BP_VAR_W:
  878. break;
  879. case BP_VAR_RW:
  880. opline->opcode += 3;
  881. break;
  882. case BP_VAR_IS:
  883. if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
  884. zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
  885. }
  886. opline->opcode += 6; /* 3+3 */
  887. break;
  888. case BP_VAR_FUNC_ARG:
  889. opline->opcode += 9; /* 3+3+3 */
  890. opline->extended_value = arg_offset;
  891. break;
  892. case BP_VAR_UNSET:
  893. if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
  894. zend_error(E_COMPILE_ERROR, "Cannot use [] for unsetting");
  895. }
  896. opline->opcode += 12; /* 3+3+3+3 */
  897. break;
  898. }
  899. le = le->next;
  900. }
  901. if (opline && type == BP_VAR_W && arg_offset) {
  902. opline->extended_value = ZEND_FETCH_MAKE_REF;
  903. }
  904. }
  905. zend_llist_destroy(fetch_list_ptr);
  906. zend_stack_del_top(&CG(bp_stack));
  907. }
  908. /* }}} */
  909. void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
  910. {
  911. zend_op *opline;
  912. if (Z_STRLEN(op2->u.constant) > 1) {
  913. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  914. opline->opcode = ZEND_ADD_STRING;
  915. } else if (Z_STRLEN(op2->u.constant) == 1) {
  916. int ch = *Z_STRVAL(op2->u.constant);
  917. /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
  918. efree(Z_STRVAL(op2->u.constant));
  919. ZVAL_LONG(&op2->u.constant, ch);
  920. opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  921. opline->opcode = ZEND_ADD_CHAR;
  922. } else { /* String can be empty after a variable at the end of a heredoc */
  923. efree(Z_STRVAL(op2->u.constant));
  924. return;
  925. }
  926. if (op1) {
  927. opline->op1 = *op1;
  928. opline->result = *op1;
  929. } else {
  930. SET_UNUSED(opline->op1);
  931. opline->result.op_type = IS_TMP_VAR;
  932. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  933. }
  934. opline->op2 = *op2;
  935. *result = opline->result;
  936. }
  937. /* }}} */
  938. void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
  939. {
  940. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  941. opline->opcode = ZEND_ADD_VAR;
  942. if (op1) {
  943. opline->op1 = *op1;
  944. opline->result = *op1;
  945. } else {
  946. SET_UNUSED(opline->op1);
  947. opline->result.op_type = IS_TMP_VAR;
  948. opline->result.u.var = get_temporary_variable(CG(active_op_array));
  949. }
  950. opline->op2 = *op2;
  951. *result = opline->result;
  952. }
  953. /* }}} */
  954. void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
  955. {
  956. if (op1->op_type==IS_TMP_VAR) {
  957. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  958. opline->opcode = ZEND_FREE;
  959. opline->op1 = *op1;
  960. SET_UNUSED(opline->op2);
  961. } else if (op1->op_type==IS_VAR) {
  962. zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
  963. while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
  964. opline--;
  965. }
  966. if (opline->result.op_type == IS_VAR
  967. && opline->result.u.var == op1->u.var) {
  968. opline->result.u.EA.type |= EXT_TYPE_UNUSED;
  969. } else {
  970. while (opline>CG(active_op_array)->opcodes) {
  971. if (opline->opcode == ZEND_FETCH_DIM_R
  972. && opline->op1.op_type == IS_VAR
  973. && opline->op1.u.var == op1->u.var) {
  974. /* This should the end of a list() construct
  975. * Mark its result as unused
  976. */
  977. opline->extended_value = ZEND_FETCH_STANDARD;
  978. break;
  979. } else if (opline->result.op_type==IS_VAR
  980. && opline->result.u.var == op1->u.var) {
  981. if (opline->opcode == ZEND_NEW) {
  982. opline->result.u.EA.type |= EXT_TYPE_UNUSED;
  983. }
  984. break;
  985. }
  986. opline--;
  987. }
  988. }
  989. } else if (op1->op_type == IS_CONST) {
  990. zval_dtor(&op1->u.constant);
  991. }
  992. }
  993. /* }}} */
  994. int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
  995. {
  996. if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
  997. && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
  998. zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
  999. }
  1000. if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
  1001. && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
  1002. zend_error(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
  1003. }
  1004. if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
  1005. && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
  1006. zend_error(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
  1007. }
  1008. if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
  1009. && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
  1010. zend_error(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
  1011. }
  1012. if (((Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant)) & (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) == (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) {
  1013. zend_error(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
  1014. }
  1015. return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
  1016. }
  1017. /* }}} */
  1018. void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
  1019. {
  1020. zend_op_array op_array;
  1021. char *name = function_name->u.constant.value.str.val;
  1022. int name_len = function_name->u.constant.value.str.len;
  1023. int function_begin_line = function_token->u.opline_num;
  1024. zend_uint fn_flags;
  1025. char *lcname;
  1026. zend_bool orig_interactive;
  1027. ALLOCA_FLAG(use_heap)
  1028. if (is_method) {
  1029. if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
  1030. if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
  1031. zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
  1032. }
  1033. Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
  1034. }
  1035. fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
  1036. } else {
  1037. fn_flags = 0;
  1038. }
  1039. if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
  1040. zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
  1041. }
  1042. function_token->u.op_array = CG(active_op_array);
  1043. lcname = zend_str_tolower_dup(name, name_len);
  1044. orig_interactive = CG(interactive);
  1045. CG(interactive) = 0;
  1046. init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
  1047. CG(interactive) = orig_interactive;
  1048. op_array.function_name = name;
  1049. op_array.return_reference = return_reference;
  1050. op_array.fn_flags |= fn_flags;
  1051. op_array.pass_rest_by_reference = 0;
  1052. op_array.scope = is_method?CG(active_class_entry):NULL;
  1053. op_array.prototype = NULL;
  1054. op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
  1055. if (is_method) {
  1056. if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
  1057. zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
  1058. }
  1059. if (fn_flags & ZEND_ACC_ABSTRACT) {
  1060. CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
  1061. }
  1062. if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
  1063. fn_flags |= ZEND_ACC_PUBLIC;
  1064. }
  1065. if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
  1066. if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
  1067. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1068. zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
  1069. }
  1070. } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
  1071. if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
  1072. zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
  1073. }
  1074. } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
  1075. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1076. zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
  1077. }
  1078. } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
  1079. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1080. zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
  1081. }
  1082. } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
  1083. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1084. zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
  1085. }
  1086. } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
  1087. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1088. zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
  1089. }
  1090. } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
  1091. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1092. zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
  1093. }
  1094. }
  1095. } else {
  1096. char *class_lcname;
  1097. class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
  1098. zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
  1099. /* Improve after RC: cache the lowercase class name */
  1100. if ((CG(active_class_entry)->name_length == name_len) && (!memcmp(class_lcname, lcname, name_len))) {
  1101. if (!CG(active_class_entry)->constructor) {
  1102. CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
  1103. }
  1104. } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
  1105. if (CG(active_class_entry)->constructor) {
  1106. zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
  1107. }
  1108. CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
  1109. } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
  1110. CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
  1111. } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
  1112. CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
  1113. } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
  1114. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1115. zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
  1116. }
  1117. CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
  1118. } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
  1119. if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
  1120. zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
  1121. }
  1122. CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
  1123. } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
  1124. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1125. zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
  1126. }
  1127. CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
  1128. } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
  1129. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1130. zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
  1131. }
  1132. CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
  1133. } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
  1134. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1135. zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
  1136. }
  1137. CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
  1138. } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
  1139. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1140. zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
  1141. }
  1142. CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
  1143. } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
  1144. if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
  1145. zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
  1146. }
  1147. CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
  1148. } else if (!(fn_flags & ZEND_ACC_STATIC)) {
  1149. CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
  1150. }
  1151. free_alloca(class_lcname, use_heap);
  1152. }
  1153. efree(lcname);
  1154. } else {
  1155. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1156. if (CG(current_namespace)) {
  1157. /* Prefix function name with current namespcae name */
  1158. znode tmp;
  1159. tmp.u.constant = *CG(current_namespace);
  1160. zval_copy_ctor(&tmp.u.constant);
  1161. zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
  1162. op_array.function_name = Z_STRVAL(tmp.u.constant);
  1163. efree(lcname);
  1164. name_len = Z_STRLEN(tmp.u.constant);
  1165. lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
  1166. }
  1167. opline->opcode = ZEND_DECLARE_FUNCTION;
  1168. opline->op1.op_type = IS_CONST;
  1169. build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
  1170. opline->op2.op_type = IS_CONST;
  1171. opline->op2.u.constant.type = IS_STRING;
  1172. opline->op2.u.constant.value.str.val = lcname;
  1173. opline->op2.u.constant.value.str.len = name_len;
  1174. Z_SET_REFCOUNT(opline->op2.u.constant, 1);
  1175. opline->extended_value = ZEND_DECLARE_FUNCTION;
  1176. 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));
  1177. }
  1178. if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
  1179. zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
  1180. opline->opcode = ZEND_EXT_NOP;
  1181. opline->lineno = function_begin_line;
  1182. SET_UNUSED(opline->op1);
  1183. SET_UNUSED(opline->op2);
  1184. }
  1185. {
  1186. /* Push a seperator to the switch and foreach stacks */
  1187. zend_switch_entry switch_entry;
  1188. switch_entry.cond.op_type = IS_UNUSED;
  1189. switch_entry.default_case = 0;
  1190. switch_entry.control_var = 0;
  1191. zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
  1192. {
  1193. /* Foreach stack separator */
  1194. zend_op dummy_opline;
  1195. dummy_opline.result.op_type = IS_UNUSED;
  1196. dummy_opline.op1.op_type = IS_UNUSED;
  1197. zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
  1198. }
  1199. }
  1200. if (CG(doc_comment)) {
  1201. CG(active_op_array)->doc_comment = CG(doc_comment);
  1202. CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
  1203. CG(doc_comment) = NULL;
  1204. CG(doc_comment_len) = 0;
  1205. }
  1206. zend_stack_push(&CG(labels_stack), (void *) &CG(labels), sizeof(HashTable*));
  1207. CG(labels) = NULL;
  1208. }
  1209. /* }}} */
  1210. void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference TSRMLS_DC) /* {{{ */
  1211. {
  1212. znode function_name;
  1213. zend_op_array *current_op_array = CG(active_op_array);
  1214. int current_op_number = get_next_op_number(CG(active_op_array));
  1215. zend_op *current_op;
  1216. function_name.op_type = IS_CONST;
  1217. ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
  1218. zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
  1219. result->op_type = IS_TMP_VAR;
  1220. result->u.var = get_temporary_variable(current_op_array);
  1221. current_op = &current_op_array->opcodes[current_op_number];
  1222. current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
  1223. zval_dtor(&current_op->op2.u.constant);
  1224. ZVAL_LONG(&current_op->op2.u.constant, zend_hash_func(Z_STRVAL(current_op->op1.u.constant), Z_STRLEN(current_op->op1.u.constant)));
  1225. current_op->result = *result;
  1226. CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
  1227. }
  1228. /* }}} */
  1229. void zend_d

Large files files are truncated, but you can click here to view the full file