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.

1656 lines
46 KiB

11 years ago
11 years ago
11 years ago
12 years ago
12 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | Zend Engine |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2015 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: Bob Weinand <bwoebi@php.net> |
  16. | Dmitry Stogov <dmitry@zend.com> |
  17. +----------------------------------------------------------------------+
  18. */
  19. /* $Id$ */
  20. #include "zend_ast.h"
  21. #include "zend_API.h"
  22. #include "zend_operators.h"
  23. #include "zend_language_parser.h"
  24. #include "zend_smart_str.h"
  25. #include "zend_exceptions.h"
  26. ZEND_API zend_ast_process_t zend_ast_process = NULL;
  27. static inline void *zend_ast_alloc(size_t size) {
  28. return zend_arena_alloc(&CG(ast_arena), size);
  29. }
  30. static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
  31. void *new = zend_ast_alloc(new_size);
  32. memcpy(new, old, old_size);
  33. return new;
  34. }
  35. static inline size_t zend_ast_size(uint32_t children) {
  36. return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
  37. }
  38. static inline size_t zend_ast_list_size(uint32_t children) {
  39. return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
  40. }
  41. ZEND_API zend_ast *zend_ast_create_znode(znode *node) {
  42. zend_ast_znode *ast;
  43. ast = zend_ast_alloc(sizeof(zend_ast_znode));
  44. ast->kind = ZEND_AST_ZNODE;
  45. ast->attr = 0;
  46. ast->lineno = CG(zend_lineno);
  47. ast->node = *node;
  48. return (zend_ast *) ast;
  49. }
  50. ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
  51. zend_ast_zval *ast;
  52. ast = zend_ast_alloc(sizeof(zend_ast_zval));
  53. ast->kind = ZEND_AST_ZVAL;
  54. ast->attr = attr;
  55. ZVAL_COPY_VALUE(&ast->val, zv);
  56. ast->val.u2.lineno = CG(zend_lineno);
  57. return (zend_ast *) ast;
  58. }
  59. ZEND_API zend_ast *zend_ast_create_decl(
  60. zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
  61. zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
  62. ) {
  63. zend_ast_decl *ast;
  64. ast = zend_ast_alloc(sizeof(zend_ast_decl));
  65. ast->kind = kind;
  66. ast->attr = 0;
  67. ast->start_lineno = start_lineno;
  68. ast->end_lineno = CG(zend_lineno);
  69. ast->flags = flags;
  70. ast->lex_pos = LANG_SCNG(yy_text);
  71. ast->doc_comment = doc_comment;
  72. ast->name = name;
  73. ast->child[0] = child0;
  74. ast->child[1] = child1;
  75. ast->child[2] = child2;
  76. ast->child[3] = child3;
  77. return (zend_ast *) ast;
  78. }
  79. static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
  80. uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
  81. zend_ast *ast;
  82. ast = zend_ast_alloc(zend_ast_size(children));
  83. ast->kind = kind;
  84. ast->attr = attr;
  85. ast->lineno = (uint32_t) -1;
  86. for (i = 0; i < children; ++i) {
  87. ast->child[i] = va_arg(va, zend_ast *);
  88. if (ast->child[i] != NULL) {
  89. uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
  90. if (lineno < ast->lineno) {
  91. ast->lineno = lineno;
  92. }
  93. }
  94. }
  95. if (ast->lineno == UINT_MAX) {
  96. ast->lineno = CG(zend_lineno);
  97. }
  98. return ast;
  99. }
  100. ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
  101. va_list va;
  102. zend_ast *ast;
  103. va_start(va, attr);
  104. ast = zend_ast_create_from_va_list(kind, attr, va);
  105. va_end(va);
  106. return ast;
  107. }
  108. ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
  109. va_list va;
  110. zend_ast *ast;
  111. va_start(va, kind);
  112. ast = zend_ast_create_from_va_list(kind, 0, va);
  113. va_end(va);
  114. return ast;
  115. }
  116. ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
  117. zend_ast *ast;
  118. zend_ast_list *list;
  119. ast = zend_ast_alloc(zend_ast_list_size(4));
  120. list = (zend_ast_list *) ast;
  121. list->kind = kind;
  122. list->attr = 0;
  123. list->lineno = CG(zend_lineno);
  124. list->children = 0;
  125. {
  126. va_list va;
  127. uint32_t i;
  128. va_start(va, kind);
  129. for (i = 0; i < init_children; ++i) {
  130. ast = zend_ast_list_add(ast, va_arg(va, zend_ast *));
  131. }
  132. va_end(va);
  133. }
  134. return ast;
  135. }
  136. static inline zend_bool is_power_of_two(uint32_t n) {
  137. return ((n != 0) && (n == (n & (~n + 1))));
  138. }
  139. ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
  140. zend_ast_list *list = zend_ast_get_list(ast);
  141. if (list->children >= 4 && is_power_of_two(list->children)) {
  142. list = zend_ast_realloc(list,
  143. zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
  144. }
  145. list->child[list->children++] = op;
  146. return (zend_ast *) list;
  147. }
  148. static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
  149. {
  150. switch (Z_TYPE_P(offset)) {
  151. case IS_UNDEF:
  152. zend_hash_next_index_insert(Z_ARRVAL_P(result), expr);
  153. break;
  154. case IS_STRING:
  155. zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
  156. zval_dtor(offset);
  157. break;
  158. case IS_NULL:
  159. zend_symtable_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), expr);
  160. break;
  161. case IS_LONG:
  162. zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), expr);
  163. break;
  164. case IS_FALSE:
  165. zend_hash_index_update(Z_ARRVAL_P(result), 0, expr);
  166. break;
  167. case IS_TRUE:
  168. zend_hash_index_update(Z_ARRVAL_P(result), 1, expr);
  169. break;
  170. case IS_DOUBLE:
  171. zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
  172. break;
  173. default:
  174. zend_error(E_EXCEPTION | E_ERROR, "Illegal offset type");
  175. return FAILURE;
  176. }
  177. return SUCCESS;
  178. }
  179. ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
  180. {
  181. zval op1, op2;
  182. int ret = SUCCESS;
  183. switch (ast->kind) {
  184. case ZEND_AST_BINARY_OP:
  185. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  186. ret = FAILURE;
  187. } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
  188. zval_dtor(&op1);
  189. ret = FAILURE;
  190. } else {
  191. binary_op_type op = get_binary_op(ast->attr);
  192. ret = op(result, &op1, &op2);
  193. zval_dtor(&op1);
  194. zval_dtor(&op2);
  195. }
  196. break;
  197. case ZEND_AST_GREATER:
  198. case ZEND_AST_GREATER_EQUAL:
  199. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  200. ret = FAILURE;
  201. } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
  202. zval_dtor(&op1);
  203. ret = FAILURE;
  204. } else {
  205. /* op1 > op2 is the same as op2 < op1 */
  206. binary_op_type op = ast->kind == ZEND_AST_GREATER
  207. ? is_smaller_function : is_smaller_or_equal_function;
  208. ret = op(result, &op2, &op1);
  209. zval_dtor(&op1);
  210. zval_dtor(&op2);
  211. }
  212. break;
  213. case ZEND_AST_UNARY_OP:
  214. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  215. ret = FAILURE;
  216. } else {
  217. unary_op_type op = get_unary_op(ast->attr);
  218. ret = op(result, &op1);
  219. zval_dtor(&op1);
  220. }
  221. break;
  222. case ZEND_AST_ZVAL:
  223. {
  224. zval *zv = zend_ast_get_zval(ast);
  225. if (scope) {
  226. /* class constants may be updated in-place */
  227. if (Z_OPT_CONSTANT_P(zv)) {
  228. if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) {
  229. ret = FAILURE;
  230. break;
  231. }
  232. }
  233. ZVAL_DUP(result, zv);
  234. } else {
  235. ZVAL_DUP(result, zv);
  236. if (Z_OPT_CONSTANT_P(result)) {
  237. if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) {
  238. ret = FAILURE;
  239. break;
  240. }
  241. }
  242. }
  243. break;
  244. }
  245. case ZEND_AST_AND:
  246. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  247. ret = FAILURE;
  248. break;
  249. }
  250. if (zend_is_true(&op1)) {
  251. if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
  252. zval_dtor(&op1);
  253. ret = FAILURE;
  254. break;
  255. }
  256. ZVAL_BOOL(result, zend_is_true(&op2));
  257. zval_dtor(&op2);
  258. } else {
  259. ZVAL_FALSE(result);
  260. }
  261. zval_dtor(&op1);
  262. break;
  263. case ZEND_AST_OR:
  264. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  265. ret = FAILURE;
  266. break;
  267. }
  268. if (zend_is_true(&op1)) {
  269. ZVAL_TRUE(result);
  270. } else {
  271. if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
  272. zval_dtor(&op1);
  273. ret = FAILURE;
  274. break;
  275. }
  276. ZVAL_BOOL(result, zend_is_true(&op2));
  277. zval_dtor(&op2);
  278. }
  279. zval_dtor(&op1);
  280. break;
  281. case ZEND_AST_CONDITIONAL:
  282. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  283. ret = FAILURE;
  284. break;
  285. }
  286. if (zend_is_true(&op1)) {
  287. if (!ast->child[1]) {
  288. *result = op1;
  289. } else {
  290. if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
  291. zval_dtor(&op1);
  292. ret = FAILURE;
  293. break;
  294. }
  295. zval_dtor(&op1);
  296. }
  297. } else {
  298. if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) {
  299. zval_dtor(&op1);
  300. ret = FAILURE;
  301. break;
  302. }
  303. zval_dtor(&op1);
  304. }
  305. break;
  306. case ZEND_AST_UNARY_PLUS:
  307. if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
  308. ret = FAILURE;
  309. } else {
  310. ZVAL_LONG(&op1, 0);
  311. ret = add_function(result, &op1, &op2);
  312. zval_dtor(&op2);
  313. }
  314. break;
  315. case ZEND_AST_UNARY_MINUS:
  316. if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
  317. ret = FAILURE;
  318. } else {
  319. ZVAL_LONG(&op1, 0);
  320. ret = sub_function(result, &op1, &op2);
  321. zval_dtor(&op2);
  322. }
  323. break;
  324. case ZEND_AST_ARRAY:
  325. array_init(result);
  326. {
  327. uint32_t i;
  328. zend_ast_list *list = zend_ast_get_list(ast);
  329. for (i = 0; i < list->children; i++) {
  330. zend_ast *elem = list->child[i];
  331. if (elem->child[1]) {
  332. if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[1], scope) != SUCCESS)) {
  333. zval_dtor(result);
  334. return FAILURE;
  335. }
  336. } else {
  337. ZVAL_UNDEF(&op1);
  338. }
  339. if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) {
  340. zval_dtor(&op1);
  341. zval_dtor(result);
  342. return FAILURE;
  343. }
  344. if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
  345. zval_dtor(&op1);
  346. zval_dtor(&op2);
  347. zval_dtor(result);
  348. return FAILURE;
  349. }
  350. }
  351. }
  352. break;
  353. case ZEND_AST_DIM:
  354. if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
  355. ret = FAILURE;
  356. } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
  357. zval_dtor(&op1);
  358. ret = FAILURE;
  359. } else {
  360. zval tmp;
  361. zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
  362. ZVAL_ZVAL(result, &tmp, 1, 1);
  363. zval_dtor(&op1);
  364. zval_dtor(&op2);
  365. }
  366. break;
  367. default:
  368. zend_error(E_EXCEPTION | E_ERROR, "Unsupported constant expression");
  369. ret = FAILURE;
  370. }
  371. return ret;
  372. }
  373. ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
  374. {
  375. if (ast == NULL) {
  376. return NULL;
  377. } else if (ast->kind == ZEND_AST_ZVAL) {
  378. zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
  379. new->kind = ZEND_AST_ZVAL;
  380. new->attr = ast->attr;
  381. ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
  382. return (zend_ast *) new;
  383. } else if (zend_ast_is_list(ast)) {
  384. zend_ast_list *list = zend_ast_get_list(ast);
  385. zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
  386. uint32_t i;
  387. new->kind = list->kind;
  388. new->attr = list->attr;
  389. new->children = list->children;
  390. for (i = 0; i < list->children; i++) {
  391. new->child[i] = zend_ast_copy(list->child[i]);
  392. }
  393. return (zend_ast *) new;
  394. } else {
  395. uint32_t i, children = zend_ast_get_num_children(ast);
  396. zend_ast *new = emalloc(zend_ast_size(children));
  397. new->kind = ast->kind;
  398. new->attr = ast->attr;
  399. for (i = 0; i < children; i++) {
  400. new->child[i] = zend_ast_copy(ast->child[i]);
  401. }
  402. return new;
  403. }
  404. }
  405. static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
  406. if (!ast) {
  407. return;
  408. }
  409. switch (ast->kind) {
  410. case ZEND_AST_ZVAL:
  411. /* Destroy value without using GC: When opcache moves arrays into SHM it will
  412. * free the zend_array structure, so references to it from outside the op array
  413. * become invalid. GC would cause such a reference in the root buffer. */
  414. zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
  415. break;
  416. case ZEND_AST_FUNC_DECL:
  417. case ZEND_AST_CLOSURE:
  418. case ZEND_AST_METHOD:
  419. case ZEND_AST_CLASS:
  420. {
  421. zend_ast_decl *decl = (zend_ast_decl *) ast;
  422. if (decl->name) {
  423. zend_string_release(decl->name);
  424. }
  425. if (decl->doc_comment) {
  426. zend_string_release(decl->doc_comment);
  427. }
  428. zend_ast_destroy_ex(decl->child[0], free);
  429. zend_ast_destroy_ex(decl->child[1], free);
  430. zend_ast_destroy_ex(decl->child[2], free);
  431. zend_ast_destroy_ex(decl->child[3], free);
  432. break;
  433. }
  434. default:
  435. if (zend_ast_is_list(ast)) {
  436. zend_ast_list *list = zend_ast_get_list(ast);
  437. uint32_t i;
  438. for (i = 0; i < list->children; i++) {
  439. zend_ast_destroy_ex(list->child[i], free);
  440. }
  441. } else {
  442. uint32_t i, children = zend_ast_get_num_children(ast);
  443. for (i = 0; i < children; i++) {
  444. zend_ast_destroy_ex(ast->child[i], free);
  445. }
  446. }
  447. }
  448. if (free) {
  449. efree(ast);
  450. }
  451. }
  452. ZEND_API void zend_ast_destroy(zend_ast *ast) {
  453. zend_ast_destroy_ex(ast, 0);
  454. }
  455. ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
  456. zend_ast_destroy_ex(ast, 1);
  457. }
  458. ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
  459. if (zend_ast_is_list(ast)) {
  460. zend_ast_list *list = zend_ast_get_list(ast);
  461. uint32_t i;
  462. for (i = 0; i < list->children; ++i) {
  463. fn(&list->child[i]);
  464. }
  465. } else {
  466. uint32_t i, children = zend_ast_get_num_children(ast);
  467. for (i = 0; i < children; ++i) {
  468. fn(&ast->child[i]);
  469. }
  470. }
  471. }
  472. /*
  473. * Operator Precendence
  474. * ====================
  475. * priority associativity operators
  476. * ----------------------------------
  477. * 10 left include, include_once, eval, require, require_once
  478. * 20 left ,
  479. * 30 left or
  480. * 40 left xor
  481. * 50 left and
  482. * 60 right print
  483. * 70 right yield
  484. * 80 right =>
  485. * 85 right yield from
  486. * 90 right = += -= *= /= .= %= &= |= ^= <<= >>= **=
  487. * 100 left ? :
  488. * 110 right ??
  489. * 120 left ||
  490. * 130 left &&
  491. * 140 left |
  492. * 150 left ^
  493. * 160 left &
  494. * 170 non-associative == != === !==
  495. * 180 non-associative < <= > >= <=>
  496. * 190 left << >>
  497. * 200 left + - .
  498. * 210 left * / %
  499. * 220 right !
  500. * 230 non-associative instanceof
  501. * 240 right + - ++ -- ~ (type) @
  502. * 250 right **
  503. * 260 left [
  504. * 270 non-associative clone new
  505. */
  506. static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
  507. static void zend_ast_export_str(smart_str *str, zend_string *s)
  508. {
  509. size_t i;
  510. for (i = 0; i < s->len; i++) {
  511. unsigned char c = s->val[i];
  512. if (c == '\'' || c == '\\') {
  513. smart_str_appendc(str, '\\');
  514. smart_str_appendc(str, c);
  515. } else {
  516. smart_str_appendc(str, c);
  517. }
  518. }
  519. }
  520. static void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
  521. {
  522. size_t i;
  523. for (i = 0; i < s->len; i++) {
  524. unsigned char c = s->val[i];
  525. if (c < ' ') {
  526. switch (c) {
  527. case '\n':
  528. smart_str_appends(str, "\\n");
  529. break;
  530. case '\r':
  531. smart_str_appends(str, "\\r");
  532. break;
  533. case '\t':
  534. smart_str_appends(str, "\\t");
  535. break;
  536. case '\f':
  537. smart_str_appends(str, "\\f");
  538. break;
  539. case '\v':
  540. smart_str_appends(str, "\\v");
  541. break;
  542. #ifdef PHP_WIN32
  543. case VK_ESCAPE:
  544. #else
  545. case '\e':
  546. #endif
  547. smart_str_appends(str, "\\e");
  548. break;
  549. default:
  550. smart_str_appends(str, "\\0");
  551. smart_str_appendc(str, '0' + (c / 8));
  552. smart_str_appendc(str, '0' + (c % 8));
  553. break;
  554. }
  555. } else {
  556. if (c == quote || c == '$' || c == '\\') {
  557. smart_str_appendc(str, '\\');
  558. }
  559. smart_str_appendc(str, c);
  560. }
  561. }
  562. }
  563. static void zend_ast_export_indent(smart_str *str, int indent)
  564. {
  565. while (indent > 0) {
  566. smart_str_appends(str, " ");
  567. indent--;
  568. }
  569. }
  570. static void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
  571. {
  572. if (ast->kind == ZEND_AST_ZVAL) {
  573. zval *zv = zend_ast_get_zval(ast);
  574. if (Z_TYPE_P(zv) == IS_STRING) {
  575. smart_str_append(str, Z_STR_P(zv));
  576. return;
  577. }
  578. }
  579. zend_ast_export_ex(str, ast, priority, indent);
  580. }
  581. static void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
  582. {
  583. if (ast->kind == ZEND_AST_ZVAL) {
  584. zval *zv = zend_ast_get_zval(ast);
  585. if (Z_TYPE_P(zv) == IS_STRING) {
  586. if (ast->attr == ZEND_NAME_FQ) {
  587. smart_str_appendc(str, '\\');
  588. } else if (ast->attr == ZEND_NAME_RELATIVE) {
  589. smart_str_appends(str, "namespace\\");
  590. }
  591. smart_str_append(str, Z_STR_P(zv));
  592. return;
  593. }
  594. }
  595. zend_ast_export_ex(str, ast, priority, indent);
  596. }
  597. static int zend_ast_valid_var_char(char ch)
  598. {
  599. unsigned char c = (unsigned char)ch;
  600. if (c != '_' && c < 127 &&
  601. (c < '0' || c > '9') &&
  602. (c < 'A' || c > 'Z') &&
  603. (c < 'a' || c > 'z')) {
  604. return 0;
  605. }
  606. return 1;
  607. }
  608. static int zend_ast_valid_var_name(const char *s, size_t len)
  609. {
  610. unsigned char c;
  611. size_t i;
  612. if (len == 0) {
  613. return 0;
  614. }
  615. c = (unsigned char)s[0];
  616. if (c != '_' && c < 127 &&
  617. (c < 'A' || c > 'Z') &&
  618. (c < 'a' || c > 'z')) {
  619. return 0;
  620. }
  621. for (i = 1; i < len; i++) {
  622. c = (unsigned char)s[i];
  623. if (c != '_' && c < 127 &&
  624. (c < '0' || c > '9') &&
  625. (c < 'A' || c > 'Z') &&
  626. (c < 'a' || c > 'z')) {
  627. return 0;
  628. }
  629. }
  630. return 1;
  631. }
  632. static void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
  633. {
  634. if (ast->kind == ZEND_AST_ZVAL) {
  635. zval *zv = zend_ast_get_zval(ast);
  636. if (Z_TYPE_P(zv) == IS_STRING &&
  637. zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
  638. smart_str_append(str, Z_STR_P(zv));
  639. return;
  640. }
  641. } else if (ast->kind == ZEND_AST_VAR) {
  642. zend_ast_export_ex(str, ast, 0, indent);
  643. return;
  644. }
  645. smart_str_appendc(str, '{');
  646. zend_ast_export_name(str, ast, 0, indent);
  647. smart_str_appendc(str, '}');
  648. }
  649. static void zend_ast_export_list(smart_str *str, zend_ast_list *list, int separator, int priority, int indent)
  650. {
  651. uint32_t i = 0;
  652. while (i < list->children) {
  653. if (i != 0 && separator) {
  654. smart_str_appends(str, ", ");
  655. }
  656. zend_ast_export_ex(str, list->child[i], priority, indent);
  657. i++;
  658. }
  659. }
  660. static void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
  661. {
  662. uint32_t i = 0;
  663. zend_ast *ast;
  664. while (i < list->children) {
  665. ast = list->child[i];
  666. if (ast->kind == ZEND_AST_ZVAL) {
  667. zval *zv = zend_ast_get_zval(ast);
  668. ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
  669. zend_ast_export_qstr(str, quote, Z_STR_P(zv));
  670. } else if (ast->kind == ZEND_AST_VAR &&
  671. ast->child[0]->kind == ZEND_AST_ZVAL &&
  672. (i + 1 == list->children ||
  673. list->child[i + 1]->kind != ZEND_AST_ZVAL ||
  674. !zend_ast_valid_var_char(
  675. *Z_STRVAL_P(
  676. zend_ast_get_zval(list->child[i + 1]))))) {
  677. zend_ast_export_ex(str, ast, 0, indent);
  678. } else {
  679. smart_str_appendc(str, '{');
  680. zend_ast_export_ex(str, ast, 0, indent);
  681. smart_str_appendc(str, '}');
  682. }
  683. i++;
  684. }
  685. }
  686. static void zend_ast_export_name_list(smart_str *str, zend_ast_list *list, int indent)
  687. {
  688. uint32_t i = 0;
  689. while (i < list->children) {
  690. if (i != 0) {
  691. smart_str_appends(str, ", ");
  692. }
  693. zend_ast_export_name(str, list->child[i], 0, indent);
  694. i++;
  695. }
  696. }
  697. static void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
  698. {
  699. uint32_t i = 0;
  700. while (i < list->children) {
  701. if (i != 0) {
  702. smart_str_appends(str, ", ");
  703. }
  704. if (list->child[i]->attr) {
  705. smart_str_appendc(str, '&');
  706. }
  707. smart_str_appendc(str, '$');
  708. zend_ast_export_name(str, list->child[i], 20, indent);
  709. i++;
  710. }
  711. }
  712. static void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
  713. {
  714. if (ast->kind == ZEND_AST_STMT_LIST ||
  715. ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
  716. zend_ast_list *list = (zend_ast_list*)ast;
  717. uint32_t i = 0;
  718. while (i < list->children) {
  719. ast = list->child[i];
  720. zend_ast_export_stmt(str, ast, indent);
  721. i++;
  722. }
  723. } else {
  724. zend_ast_export_indent(str, indent);
  725. zend_ast_export_ex(str, ast, 0, indent);
  726. switch (ast->kind) {
  727. case ZEND_AST_LABEL:
  728. case ZEND_AST_IF:
  729. case ZEND_AST_SWITCH:
  730. case ZEND_AST_WHILE:
  731. case ZEND_AST_TRY:
  732. case ZEND_AST_FOR:
  733. case ZEND_AST_FOREACH:
  734. case ZEND_AST_FUNC_DECL:
  735. case ZEND_AST_METHOD:
  736. case ZEND_AST_CLASS:
  737. case ZEND_AST_USE_TRAIT:
  738. case ZEND_AST_NAMESPACE:
  739. case ZEND_AST_DECLARE:
  740. break;
  741. default:
  742. smart_str_appendc(str, ';');
  743. break;
  744. }
  745. smart_str_appendc(str, '\n');
  746. }
  747. }
  748. static void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
  749. {
  750. uint32_t i;
  751. zend_ast *ast;
  752. tail_call:
  753. i = 0;
  754. while (i < list->children) {
  755. ast = list->child[i];
  756. ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
  757. if (ast->child[0]) {
  758. if (i == 0) {
  759. smart_str_appends(str, "if (");
  760. } else {
  761. zend_ast_export_indent(str, indent);
  762. smart_str_appends(str, "} elseif (");
  763. }
  764. zend_ast_export_ex(str, ast->child[0], 0, indent);
  765. smart_str_appends(str, ") {\n");
  766. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  767. } else {
  768. zend_ast_export_indent(str, indent);
  769. smart_str_appends(str, "} else ");
  770. if (ast->child[1]->kind == ZEND_AST_IF) {
  771. list = (zend_ast_list*)ast->child[1];
  772. goto tail_call;
  773. } else {
  774. smart_str_appends(str, "{\n");
  775. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  776. }
  777. }
  778. i++;
  779. }
  780. zend_ast_export_indent(str, indent);
  781. smart_str_appendc(str, '}');
  782. }
  783. static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
  784. {
  785. zend_long idx;
  786. zend_string *key;
  787. zval *val;
  788. int first;
  789. ZVAL_DEREF(zv);
  790. switch (Z_TYPE_P(zv)) {
  791. case IS_NULL:
  792. smart_str_appends(str, "null");
  793. break;
  794. case IS_FALSE:
  795. smart_str_appends(str, "false");
  796. break;
  797. case IS_TRUE:
  798. smart_str_appends(str, "true");
  799. break;
  800. case IS_LONG:
  801. smart_str_append_long(str, Z_LVAL_P(zv));
  802. break;
  803. case IS_DOUBLE:
  804. key = zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(zv));
  805. smart_str_appendl(str, key->val, key->len);
  806. zend_string_release(key);
  807. break;
  808. case IS_STRING:
  809. smart_str_appendc(str, '\'');
  810. zend_ast_export_str(str, Z_STR_P(zv));
  811. smart_str_appendc(str, '\'');
  812. break;
  813. case IS_ARRAY:
  814. smart_str_appendc(str, '[');
  815. first = 1;
  816. ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
  817. if (first) {
  818. first = 0;
  819. } else {
  820. smart_str_appends(str, ", ");
  821. }
  822. if (key) {
  823. smart_str_appendc(str, '\'');
  824. zend_ast_export_str(str, key);
  825. smart_str_appends(str, "' => ");
  826. } else {
  827. smart_str_append_long(str, idx);
  828. smart_str_appends(str, " => ");
  829. }
  830. zend_ast_export_zval(str, val, 0, indent);
  831. } ZEND_HASH_FOREACH_END();
  832. smart_str_appendc(str, ']');
  833. break;
  834. case IS_CONSTANT:
  835. smart_str_appendl(str, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
  836. break;
  837. case IS_CONSTANT_AST:
  838. zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
  839. break;
  840. EMPTY_SWITCH_DEFAULT_CASE();
  841. }
  842. }
  843. #define BINARY_OP(_op, _p, _pl, _pr) do { \
  844. op = _op; \
  845. p = _p; \
  846. pl = _pl; \
  847. pr = _pr; \
  848. goto binary_op; \
  849. } while (0)
  850. #define PREFIX_OP(_op, _p, _pl) do { \
  851. op = _op; \
  852. p = _p; \
  853. pl = _pl; \
  854. goto prefix_op; \
  855. } while (0)
  856. #define FUNC_OP(_op) do { \
  857. op = _op; \
  858. goto func_op; \
  859. } while (0)
  860. #define POSTFIX_OP(_op, _p, _pl) do { \
  861. op = _op; \
  862. p = _p; \
  863. pl = _pl; \
  864. goto postfix_op; \
  865. } while (0)
  866. #define APPEND_NODE_1(_op) do { \
  867. op = _op; \
  868. goto append_node_1; \
  869. } while (0)
  870. #define APPEND_STR(_op) do { \
  871. op = _op; \
  872. goto append_str; \
  873. } while (0)
  874. #define APPEND_DEFAULT_VALUE(n) do { \
  875. p = n; \
  876. goto append_default_value; \
  877. } while (0)
  878. static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
  879. {
  880. zend_ast_decl *decl;
  881. int p, pl, pr;
  882. const char *op;
  883. tail_call:
  884. if (!ast) {
  885. return;
  886. }
  887. switch (ast->kind) {
  888. /* special nodes */
  889. case ZEND_AST_ZVAL:
  890. zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
  891. break;
  892. case ZEND_AST_ZNODE:
  893. /* This AST kind is only used for temporary nodes during compilation */
  894. ZEND_ASSERT(0);
  895. break;
  896. /* declaration nodes */
  897. case ZEND_AST_FUNC_DECL:
  898. case ZEND_AST_CLOSURE:
  899. case ZEND_AST_METHOD:
  900. decl = (zend_ast_decl *) ast;
  901. if (decl->flags & ZEND_ACC_PUBLIC) {
  902. smart_str_appends(str, "public ");
  903. } else if (decl->flags & ZEND_ACC_PROTECTED) {
  904. smart_str_appends(str, "protected ");
  905. } else if (decl->flags & ZEND_ACC_PRIVATE) {
  906. smart_str_appends(str, "private ");
  907. }
  908. if (decl->flags & ZEND_ACC_STATIC) {
  909. smart_str_appends(str, "static ");
  910. }
  911. if (decl->flags & ZEND_ACC_ABSTRACT) {
  912. smart_str_appends(str, "abstract ");
  913. }
  914. if (decl->flags & ZEND_ACC_FINAL) {
  915. smart_str_appends(str, "final ");
  916. }
  917. smart_str_appends(str, "function ");
  918. if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
  919. smart_str_appendc(str, '&');
  920. }
  921. if (ast->kind != ZEND_AST_CLOSURE) {
  922. smart_str_appendl(str, decl->name->val, decl->name->len);
  923. }
  924. smart_str_appendc(str, '(');
  925. zend_ast_export_ex(str, decl->child[0], 0, indent);
  926. smart_str_appendc(str, ')');
  927. zend_ast_export_ex(str, decl->child[1], 0, indent);
  928. if (decl->child[3]) {
  929. smart_str_appends(str, ": ");
  930. zend_ast_export_ns_name(str, decl->child[3], 0, indent);
  931. }
  932. if (decl->child[2]) {
  933. smart_str_appends(str, " {\n");
  934. zend_ast_export_stmt(str, decl->child[2], indent + 1);
  935. zend_ast_export_indent(str, indent);
  936. smart_str_appendc(str, '}');
  937. if (ast->kind != ZEND_AST_CLOSURE) {
  938. smart_str_appendc(str, '\n');
  939. }
  940. } else {
  941. smart_str_appends(str, ";\n");
  942. }
  943. break;
  944. case ZEND_AST_CLASS:
  945. decl = (zend_ast_decl *) ast;
  946. if (decl->flags & ZEND_ACC_INTERFACE) {
  947. smart_str_appends(str, "interface ");
  948. } else if (decl->flags & ZEND_ACC_TRAIT) {
  949. smart_str_appends(str, "trait ");
  950. } else {
  951. if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
  952. smart_str_appends(str, "abstract ");
  953. }
  954. if (decl->flags & ZEND_ACC_FINAL) {
  955. smart_str_appends(str, "final ");
  956. }
  957. smart_str_appends(str, "class ");
  958. }
  959. smart_str_appendl(str, decl->name->val, decl->name->len);
  960. if (decl->child[0]) {
  961. smart_str_appends(str, " extends ");
  962. zend_ast_export_ns_name(str, decl->child[0], 0, indent);
  963. }
  964. if (decl->child[1]) {
  965. smart_str_appends(str, " implements ");
  966. zend_ast_export_ex(str, decl->child[1], 0, indent);
  967. }
  968. smart_str_appends(str, " {\n");
  969. zend_ast_export_stmt(str, decl->child[2], indent + 1);
  970. zend_ast_export_indent(str, indent);
  971. smart_str_appends(str, "}\n");
  972. break;
  973. /* list nodes */
  974. case ZEND_AST_ARG_LIST:
  975. case ZEND_AST_EXPR_LIST:
  976. case ZEND_AST_PARAM_LIST:
  977. simple_list:
  978. zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
  979. break;
  980. case ZEND_AST_LIST:
  981. smart_str_appends(str, "list(");
  982. zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
  983. smart_str_appendc(str, ')');
  984. break;
  985. case ZEND_AST_ARRAY:
  986. smart_str_appendc(str, '[');
  987. zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
  988. smart_str_appendc(str, ']');
  989. break;
  990. case ZEND_AST_ENCAPS_LIST:
  991. smart_str_appendc(str, '"');
  992. zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
  993. smart_str_appendc(str, '"');
  994. break;
  995. case ZEND_AST_STMT_LIST:
  996. case ZEND_AST_TRAIT_ADAPTATIONS:
  997. zend_ast_export_stmt(str, ast, indent);
  998. break;
  999. case ZEND_AST_IF:
  1000. zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
  1001. break;
  1002. case ZEND_AST_SWITCH_LIST:
  1003. case ZEND_AST_CATCH_LIST:
  1004. zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
  1005. break;
  1006. case ZEND_AST_CLOSURE_USES:
  1007. smart_str_appends(str, " use(");
  1008. zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
  1009. smart_str_appendc(str, ')');
  1010. break;
  1011. case ZEND_AST_PROP_DECL:
  1012. if (ast->attr & ZEND_ACC_PUBLIC) {
  1013. smart_str_appends(str, "public ");
  1014. } else if (ast->attr & ZEND_ACC_PROTECTED) {
  1015. smart_str_appends(str, "protected ");
  1016. } else if (ast->attr & ZEND_ACC_PRIVATE) {
  1017. smart_str_appends(str, "private ");
  1018. }
  1019. if (ast->attr & ZEND_ACC_STATIC) {
  1020. smart_str_appends(str, "static ");
  1021. }
  1022. goto simple_list;
  1023. case ZEND_AST_CONST_DECL:
  1024. case ZEND_AST_CLASS_CONST_DECL:
  1025. smart_str_appends(str, "const ");
  1026. goto simple_list;
  1027. case ZEND_AST_NAME_LIST:
  1028. zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
  1029. break;
  1030. case ZEND_AST_USE:
  1031. smart_str_appends(str, "use ");
  1032. if (ast->attr == T_FUNCTION) {
  1033. smart_str_appends(str, "function ");
  1034. } else if (ast->attr == T_CONST) {
  1035. smart_str_appends(str, "const ");
  1036. }
  1037. goto simple_list;
  1038. /* 0 child nodes */
  1039. case ZEND_AST_MAGIC_CONST:
  1040. switch (ast->attr) {
  1041. case T_LINE: APPEND_STR("__LINE__");
  1042. case T_FILE: APPEND_STR("__FILE__");
  1043. case T_DIR: APPEND_STR("__DIR__");
  1044. case T_TRAIT_C: APPEND_STR("__TRAIT__");
  1045. case T_METHOD_C: APPEND_STR("__METHOD__");
  1046. case T_FUNC_C: APPEND_STR("__FUNCTION__");
  1047. case T_NS_C: APPEND_STR("__NAMESPACE__");
  1048. case T_CLASS_C: APPEND_STR("__CLASS__");
  1049. EMPTY_SWITCH_DEFAULT_CASE();
  1050. }
  1051. break;
  1052. case ZEND_AST_TYPE:
  1053. switch (ast->attr) {
  1054. case IS_ARRAY: APPEND_STR("array");
  1055. case IS_CALLABLE: APPEND_STR("callable");
  1056. EMPTY_SWITCH_DEFAULT_CASE();
  1057. }
  1058. break;
  1059. /* 1 child node */
  1060. case ZEND_AST_VAR:
  1061. smart_str_appendc(str, '$');
  1062. zend_ast_export_var(str, ast->child[0], 0, indent);
  1063. break;
  1064. case ZEND_AST_CONST:
  1065. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1066. break;
  1067. case ZEND_AST_RESOLVE_CLASS_NAME:
  1068. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1069. APPEND_STR("::class");
  1070. case ZEND_AST_UNPACK:
  1071. smart_str_appends(str, "...");
  1072. ast = ast->child[0];
  1073. goto tail_call;
  1074. case ZEND_AST_UNARY_PLUS: PREFIX_OP("+", 240, 241);
  1075. case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
  1076. case ZEND_AST_CAST:
  1077. switch (ast->attr) {
  1078. case IS_NULL: PREFIX_OP("(unset)", 240, 241);
  1079. case _IS_BOOL: PREFIX_OP("(bool)", 240, 241);
  1080. case IS_LONG: PREFIX_OP("(int)", 240, 241);
  1081. case IS_DOUBLE: PREFIX_OP("(double)", 240, 241);
  1082. case IS_STRING: PREFIX_OP("(string)", 240, 241);
  1083. case IS_ARRAY: PREFIX_OP("(array)", 240, 241);
  1084. case IS_OBJECT: PREFIX_OP("(object)", 240, 241);
  1085. EMPTY_SWITCH_DEFAULT_CASE();
  1086. }
  1087. break;
  1088. case ZEND_AST_EMPTY:
  1089. FUNC_OP("empty");
  1090. case ZEND_AST_ISSET:
  1091. FUNC_OP("isset");
  1092. case ZEND_AST_SILENCE:
  1093. PREFIX_OP("@", 240, 241);
  1094. case ZEND_AST_SHELL_EXEC:
  1095. smart_str_appendc(str, '`');
  1096. if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
  1097. zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
  1098. } else {
  1099. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1100. }
  1101. smart_str_appendc(str, '`');
  1102. break;
  1103. case ZEND_AST_CLONE:
  1104. PREFIX_OP("clone ", 270, 271);
  1105. case ZEND_AST_EXIT:
  1106. if (ast->child[0]) {
  1107. FUNC_OP("exit");
  1108. } else {
  1109. APPEND_STR("exit");
  1110. }
  1111. break;
  1112. case ZEND_AST_PRINT:
  1113. PREFIX_OP("print ", 60, 61);
  1114. case ZEND_AST_INCLUDE_OR_EVAL:
  1115. switch (ast->attr) {
  1116. case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
  1117. case ZEND_INCLUDE: FUNC_OP("include");
  1118. case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
  1119. case ZEND_REQUIRE: FUNC_OP("require");
  1120. case ZEND_EVAL: FUNC_OP("eval");
  1121. EMPTY_SWITCH_DEFAULT_CASE();
  1122. }
  1123. break;
  1124. case ZEND_AST_UNARY_OP:
  1125. switch (ast->attr) {
  1126. case ZEND_BW_NOT: PREFIX_OP("~", 240, 241);
  1127. case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
  1128. EMPTY_SWITCH_DEFAULT_CASE();
  1129. }
  1130. break;
  1131. case ZEND_AST_PRE_INC:
  1132. PREFIX_OP("++", 240, 241);
  1133. case ZEND_AST_PRE_DEC:
  1134. PREFIX_OP("--", 240, 241);
  1135. case ZEND_AST_POST_INC:
  1136. POSTFIX_OP("++", 240, 241);
  1137. case ZEND_AST_POST_DEC:
  1138. POSTFIX_OP("--", 240, 241);
  1139. case ZEND_AST_GLOBAL:
  1140. APPEND_NODE_1("global");
  1141. case ZEND_AST_UNSET:
  1142. FUNC_OP("unset");
  1143. case ZEND_AST_RETURN:
  1144. APPEND_NODE_1("return");
  1145. case ZEND_AST_LABEL:
  1146. zend_ast_export_name(str, ast->child[0], 0, indent);
  1147. smart_str_appendc(str, ':');
  1148. break;
  1149. case ZEND_AST_REF:
  1150. smart_str_appendc(str, '&');
  1151. ast = ast->child[0];
  1152. goto tail_call;
  1153. case ZEND_AST_HALT_COMPILER:
  1154. APPEND_STR("__HALT_COMPILER()");
  1155. case ZEND_AST_ECHO:
  1156. APPEND_NODE_1("echo");
  1157. case ZEND_AST_THROW:
  1158. APPEND_NODE_1("throw");
  1159. case ZEND_AST_GOTO:
  1160. smart_str_appends(str, "goto ");
  1161. zend_ast_export_name(str, ast->child[0], 0, indent);
  1162. break;
  1163. case ZEND_AST_BREAK:
  1164. APPEND_NODE_1("break");
  1165. case ZEND_AST_CONTINUE:
  1166. APPEND_NODE_1("continue");
  1167. /* 2 child nodes */
  1168. case ZEND_AST_DIM:
  1169. zend_ast_export_ex(str, ast->child[0], 260, indent);
  1170. smart_str_appendc(str, '[');
  1171. if (ast->child[1]) {
  1172. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1173. }
  1174. smart_str_appendc(str, ']');
  1175. break;
  1176. case ZEND_AST_PROP:
  1177. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1178. smart_str_appends(str, "->");
  1179. zend_ast_export_var(str, ast->child[1], 0, indent);
  1180. break;
  1181. case ZEND_AST_STATIC_PROP:
  1182. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1183. smart_str_appends(str, "::$");
  1184. zend_ast_export_var(str, ast->child[1], 0, indent);
  1185. break;
  1186. case ZEND_AST_CALL:
  1187. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1188. smart_str_appendc(str, '(');
  1189. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1190. smart_str_appendc(str, ')');
  1191. break;
  1192. case ZEND_AST_CLASS_CONST:
  1193. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1194. smart_str_appends(str, "::");
  1195. zend_ast_export_name(str, ast->child[1], 0, indent);
  1196. break;
  1197. case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);
  1198. case ZEND_AST_ASSIGN_REF: BINARY_OP(" =& ", 90, 91, 90);
  1199. case ZEND_AST_ASSIGN_OP:
  1200. switch (ast->attr) {
  1201. case ZEND_ASSIGN_ADD: BINARY_OP(" += ", 90, 91, 90);
  1202. case ZEND_ASSIGN_SUB: BINARY_OP(" -= ", 90, 91, 90);
  1203. case ZEND_ASSIGN_MUL: BINARY_OP(" *= ", 90, 91, 90);
  1204. case ZEND_ASSIGN_DIV: BINARY_OP(" /= ", 90, 91, 90);
  1205. case ZEND_ASSIGN_MOD: BINARY_OP(" %= ", 90, 91, 90);
  1206. case ZEND_ASSIGN_SL: BINARY_OP(" <<= ", 90, 91, 90);
  1207. case ZEND_ASSIGN_SR: BINARY_OP(" >>= ", 90, 91, 90);
  1208. case ZEND_ASSIGN_CONCAT: BINARY_OP(" .= ", 90, 91, 90);
  1209. case ZEND_ASSIGN_BW_OR: BINARY_OP(" |= ", 90, 91, 90);
  1210. case ZEND_ASSIGN_BW_AND: BINARY_OP(" &= ", 90, 91, 90);
  1211. case ZEND_ASSIGN_BW_XOR: BINARY_OP(" ^= ", 90, 91, 90);
  1212. case ZEND_POW: BINARY_OP(" **= ", 90, 91, 90);
  1213. EMPTY_SWITCH_DEFAULT_CASE();
  1214. }
  1215. break;
  1216. case ZEND_AST_BINARY_OP:
  1217. switch (ast->attr) {
  1218. case ZEND_ADD: BINARY_OP(" + ", 200, 200, 201);
  1219. case ZEND_SUB: BINARY_OP(" - ", 200, 200, 201);
  1220. case ZEND_MUL: BINARY_OP(" * ", 210, 210, 211);
  1221. case ZEND_DIV: BINARY_OP(" / ", 210, 210, 211);
  1222. case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211);
  1223. case ZEND_SL: BINARY_OP(" << ", 190, 190, 191);
  1224. case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191);
  1225. case ZEND_CONCAT: BINARY_OP(" . ", 200, 200, 201);
  1226. case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141);
  1227. case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161);
  1228. case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151);
  1229. case ZEND_IS_IDENTICAL: BINARY_OP(" === ", 170, 171, 171);
  1230. case ZEND_IS_NOT_IDENTICAL: BINARY_OP(" !== ", 170, 171, 171);
  1231. case ZEND_IS_EQUAL: BINARY_OP(" == ", 170, 171, 171);
  1232. case ZEND_IS_NOT_EQUAL: BINARY_OP(" != ", 170, 171, 171);
  1233. case ZEND_IS_SMALLER: BINARY_OP(" < ", 180, 181, 181);
  1234. case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ", 180, 181, 181);
  1235. case ZEND_POW: BINARY_OP(" ** ", 250, 251, 250);
  1236. case ZEND_BOOL_XOR: BINARY_OP(" xor ", 40, 40, 41);
  1237. case ZEND_SPACESHIP: BINARY_OP(" <=> ", 180, 181, 181);
  1238. EMPTY_SWITCH_DEFAULT_CASE();
  1239. }
  1240. break;
  1241. case ZEND_AST_GREATER: BINARY_OP(" > ", 180, 181, 181);
  1242. case ZEND_AST_GREATER_EQUAL: BINARY_OP(" >= ", 180, 181, 181);
  1243. case ZEND_AST_AND: BINARY_OP(" && ", 130, 130, 131);
  1244. case ZEND_AST_OR: BINARY_OP(" || ", 120, 120, 121);
  1245. case ZEND_AST_ARRAY_ELEM:
  1246. if (ast->child[1]) {
  1247. zend_ast_export_ex(str, ast->child[1], 80, indent);
  1248. smart_str_appends(str, " => ");
  1249. }
  1250. zend_ast_export_ex(str, ast->child[0], 80, indent);
  1251. break;
  1252. case ZEND_AST_NEW:
  1253. smart_str_appends(str, "new ");
  1254. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1255. smart_str_appendc(str, '(');
  1256. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1257. smart_str_appendc(str, ')');
  1258. break;
  1259. case ZEND_AST_INSTANCEOF: BINARY_OP(" instanceof ", 230, 231, 231);
  1260. case ZEND_AST_YIELD:
  1261. if (priority > 70) smart_str_appendc(str, '(');
  1262. smart_str_appends(str, "yield ");
  1263. if (ast->child[0]) {
  1264. if (ast->child[1]) {
  1265. zend_ast_export_ex(str, ast->child[1], 70, indent);
  1266. smart_str_appends(str, " => ");
  1267. }
  1268. zend_ast_export_ex(str, ast->child[0], 70, indent);
  1269. }
  1270. if (priority > 70) smart_str_appendc(str, ')');
  1271. break;
  1272. case ZEND_AST_YIELD_FROM:
  1273. PREFIX_OP("yield from ", 85, 86);
  1274. case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
  1275. case ZEND_AST_STATIC:
  1276. smart_str_appends(str, "static $");
  1277. zend_ast_export_name(str, ast->child[0], 0, indent);
  1278. APPEND_DEFAULT_VALUE(1);
  1279. case ZEND_AST_WHILE:
  1280. smart_str_appends(str, "while (");
  1281. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1282. smart_str_appends(str, ") {\n");
  1283. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  1284. zend_ast_export_indent(str, indent);
  1285. smart_str_appendc(str, '}');
  1286. break;
  1287. case ZEND_AST_DO_WHILE:
  1288. smart_str_appends(str, "do {\n");
  1289. zend_ast_export_stmt(str, ast->child[0], indent + 1);
  1290. zend_ast_export_indent(str, indent);
  1291. smart_str_appends(str, "} while (");
  1292. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1293. smart_str_appendc(str, ')');
  1294. break;
  1295. case ZEND_AST_IF_ELEM:
  1296. if (ast->child[0]) {
  1297. smart_str_appends(str, "if (");
  1298. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1299. smart_str_appends(str, ") {\n");
  1300. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  1301. } else {
  1302. smart_str_appends(str, "else {\n");
  1303. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  1304. }
  1305. zend_ast_export_indent(str, indent);
  1306. smart_str_appendc(str, '}');
  1307. break;
  1308. case ZEND_AST_SWITCH:
  1309. smart_str_appends(str, "switch (");
  1310. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1311. smart_str_appends(str, ") {\n");
  1312. zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
  1313. zend_ast_export_indent(str, indent);
  1314. smart_str_appendc(str, '}');
  1315. break;
  1316. case ZEND_AST_SWITCH_CASE:
  1317. zend_ast_export_indent(str, indent);
  1318. if (ast->child[0]) {
  1319. smart_str_appends(str, "case ");
  1320. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1321. smart_str_appends(str, ":\n");
  1322. } else {
  1323. smart_str_appends(str, "default:\n");
  1324. }
  1325. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  1326. break;
  1327. case ZEND_AST_DECLARE:
  1328. smart_str_appends(str, "declare(");
  1329. ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
  1330. zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
  1331. smart_str_appendc(str, ')');
  1332. if (ast->child[1]) {
  1333. smart_str_appends(str, " {\n");
  1334. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  1335. zend_ast_export_indent(str, indent);
  1336. smart_str_appendc(str, '}');
  1337. } else {
  1338. smart_str_appendc(str, ';');
  1339. }
  1340. break;
  1341. case ZEND_AST_PROP_ELEM:
  1342. smart_str_appendc(str, '$');
  1343. /* break missing intentionally */
  1344. case ZEND_AST_CONST_ELEM:
  1345. zend_ast_export_name(str, ast->child[0], 0, indent);
  1346. APPEND_DEFAULT_VALUE(1);
  1347. case ZEND_AST_USE_TRAIT:
  1348. smart_str_appends(str, "use ");
  1349. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1350. if (ast->child[1]) {
  1351. smart_str_appends(str, " {\n");
  1352. zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
  1353. zend_ast_export_indent(str, indent);
  1354. smart_str_appends(str, "}");
  1355. } else {
  1356. smart_str_appends(str, ";");
  1357. }
  1358. break;
  1359. case ZEND_AST_TRAIT_PRECEDENCE:
  1360. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1361. smart_str_appends(str, " insteadof ");
  1362. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1363. break;
  1364. case ZEND_AST_METHOD_REFERENCE:
  1365. if (ast->child[0]) {
  1366. zend_ast_export_name(str, ast->child[0], 0, indent);
  1367. smart_str_appends(str, "::");
  1368. }
  1369. zend_ast_export_name(str, ast->child[1], 0, indent);
  1370. break;
  1371. case ZEND_AST_NAMESPACE:
  1372. smart_str_appends(str, "namespace");
  1373. if (ast->child[0]) {
  1374. smart_str_appendc(str, ' ');
  1375. zend_ast_export_name(str, ast->child[0], 0, indent);
  1376. }
  1377. if (ast->child[1]) {
  1378. smart_str_appends(str, " {\n");
  1379. zend_ast_export_stmt(str, ast->child[1], indent + 1);
  1380. zend_ast_export_indent(str, indent);
  1381. smart_str_appends(str, "}\n");
  1382. } else {
  1383. smart_str_appendc(str, ';');
  1384. }
  1385. break;
  1386. case ZEND_AST_USE_ELEM:
  1387. case ZEND_AST_TRAIT_ALIAS:
  1388. zend_ast_export_name(str, ast->child[0], 0, indent);
  1389. if (ast->attr & ZEND_ACC_PUBLIC) {
  1390. smart_str_appends(str, " as public");
  1391. } else if (ast->attr & ZEND_ACC_PROTECTED) {
  1392. smart_str_appends(str, " as protected");
  1393. } else if (ast->attr & ZEND_ACC_PRIVATE) {
  1394. smart_str_appends(str, " as private");
  1395. } else if (ast->child[1]) {
  1396. smart_str_appends(str, " as");
  1397. }
  1398. if (ast->child[1]) {
  1399. smart_str_appendc(str, ' ');
  1400. zend_ast_export_name(str, ast->child[1], 0, indent);
  1401. }
  1402. break;
  1403. /* 3 child nodes */
  1404. case ZEND_AST_METHOD_CALL:
  1405. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1406. smart_str_appends(str, "->");
  1407. zend_ast_export_var(str, ast->child[1], 0, indent);
  1408. smart_str_appendc(str, '(');
  1409. zend_ast_export_ex(str, ast->child[2], 0, indent);
  1410. smart_str_appendc(str, ')');
  1411. break;
  1412. case ZEND_AST_STATIC_CALL:
  1413. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1414. smart_str_appends(str, "::");
  1415. zend_ast_export_var(str, ast->child[1], 0, indent);
  1416. smart_str_appendc(str, '(');
  1417. zend_ast_export_ex(str, ast->child[2], 0, indent);
  1418. smart_str_appendc(str, ')');
  1419. break;
  1420. case ZEND_AST_CONDITIONAL:
  1421. if (priority > 100) smart_str_appendc(str, '(');
  1422. zend_ast_export_ex(str, ast->child[0], 100, indent);
  1423. if (ast->child[1]) {
  1424. smart_str_appends(str, " ? ");
  1425. zend_ast_export_ex(str, ast->child[1], 101, indent);
  1426. smart_str_appends(str, " : ");
  1427. } else {
  1428. smart_str_appends(str, " ?: ");
  1429. }
  1430. zend_ast_export_ex(str, ast->child[2], 101, indent);
  1431. if (priority > 100) smart_str_appendc(str, ')');
  1432. break;
  1433. case ZEND_AST_TRY:
  1434. smart_str_appends(str, "try {\n");
  1435. zend_ast_export_stmt(str, ast->child[0], indent + 1);
  1436. zend_ast_export_indent(str, indent);
  1437. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1438. if (ast->child[2]) {
  1439. smart_str_appends(str, "} finally {\n");
  1440. zend_ast_export_stmt(str, ast->child[2], indent + 1);
  1441. zend_ast_export_indent(str, indent);
  1442. }
  1443. smart_str_appendc(str, '}');
  1444. break;
  1445. case ZEND_AST_CATCH:
  1446. smart_str_appends(str, "} catch (");
  1447. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1448. smart_str_appends(str, " $");
  1449. zend_ast_export_var(str, ast->child[1], 0, indent);
  1450. smart_str_appends(str, ") {\n");
  1451. zend_ast_export_stmt(str, ast->child[2], indent + 1);
  1452. zend_ast_export_indent(str, indent);
  1453. break;
  1454. case ZEND_AST_PARAM:
  1455. if (ast->child[0]) {
  1456. zend_ast_export_ns_name(str, ast->child[0], 0, indent);
  1457. smart_str_appendc(str, ' ');
  1458. }
  1459. if (ast->attr & ZEND_PARAM_REF) {
  1460. smart_str_appendc(str, '&');
  1461. }
  1462. if (ast->attr & ZEND_PARAM_VARIADIC) {
  1463. smart_str_appends(str, "...");
  1464. }
  1465. smart_str_appendc(str, '$');
  1466. zend_ast_export_name(str, ast->child[1], 0, indent);
  1467. APPEND_DEFAULT_VALUE(2);
  1468. /* 4 child nodes */
  1469. case ZEND_AST_FOR:
  1470. smart_str_appends(str, "for (");
  1471. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1472. smart_str_appendc(str, ';');
  1473. if (ast->child[1]) {
  1474. smart_str_appendc(str, ' ');
  1475. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1476. }
  1477. smart_str_appendc(str, ';');
  1478. if (ast->child[2]) {
  1479. smart_str_appendc(str, ' ');
  1480. zend_ast_export_ex(str, ast->child[2], 0, indent);
  1481. }
  1482. smart_str_appends(str, ") {\n");
  1483. zend_ast_export_stmt(str, ast->child[3], indent + 1);
  1484. zend_ast_export_indent(str, indent);
  1485. smart_str_appendc(str, '}');
  1486. break;
  1487. case ZEND_AST_FOREACH:
  1488. smart_str_appends(str, "foreach (");
  1489. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1490. smart_str_appends(str, " as ");
  1491. if (ast->child[2]) {
  1492. zend_ast_export_ex(str, ast->child[2], 0, indent);
  1493. smart_str_appends(str, " => ");
  1494. }
  1495. zend_ast_export_ex(str, ast->child[1], 0, indent);
  1496. smart_str_appends(str, ") {\n");
  1497. zend_ast_export_stmt(str, ast->child[3], indent + 1);
  1498. zend_ast_export_indent(str, indent);
  1499. smart_str_appendc(str, '}');
  1500. break;
  1501. EMPTY_SWITCH_DEFAULT_CASE();
  1502. }
  1503. return;
  1504. binary_op:
  1505. if (priority > p) smart_str_appendc(str, '(');
  1506. zend_ast_export_ex(str, ast->child[0], pl, indent);
  1507. smart_str_appends(str, op);
  1508. zend_ast_export_ex(str, ast->child[1], pr, indent);
  1509. if (priority > p) smart_str_appendc(str, ')');
  1510. return;
  1511. prefix_op:
  1512. if (priority > p) smart_str_appendc(str, '(');
  1513. smart_str_appends(str, op);
  1514. zend_ast_export_ex(str, ast->child[0], pl, indent);
  1515. if (priority > p) smart_str_appendc(str, ')');
  1516. return;
  1517. postfix_op:
  1518. if (priority > p) smart_str_appendc(str, '(');
  1519. zend_ast_export_ex(str, ast->child[0], pl, indent);
  1520. smart_str_appends(str, op);
  1521. if (priority > p) smart_str_appendc(str, ')');
  1522. return;
  1523. func_op:
  1524. smart_str_appends(str, op);
  1525. smart_str_appendc(str, '(');
  1526. zend_ast_export_ex(str, ast->child[0], 0, indent);
  1527. smart_str_appendc(str, ')');
  1528. return;
  1529. append_node_1:
  1530. smart_str_appends(str, op);
  1531. if (ast->child[0]) {
  1532. smart_str_appendc(str, ' ');
  1533. ast = ast->child[0];
  1534. goto tail_call;
  1535. }
  1536. return;
  1537. append_str:
  1538. smart_str_appends(str, op);
  1539. return;
  1540. append_default_value:
  1541. if (ast->child[p]) {
  1542. smart_str_appends(str, " = ");
  1543. ast = ast->child[p];
  1544. goto tail_call;
  1545. }
  1546. return;
  1547. }
  1548. ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
  1549. {
  1550. smart_str str = {0};
  1551. smart_str_appends(&str, prefix);
  1552. zend_ast_export_ex(&str, ast, 0, 0);
  1553. smart_str_appends(&str, suffix);
  1554. smart_str_0(&str);
  1555. return str.s;
  1556. }