12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015 |
- /*
- +----------------------------------------------------------------------+
- | Zend Engine |
- +----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
- +----------------------------------------------------------------------+
- | This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.zend.com/license/2_00.txt. |
- | If you did not receive a copy of the Zend license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@zend.com so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Bob Weinand <bwoebi@php.net> |
- | Dmitry Stogov <dmitry@php.net> |
- +----------------------------------------------------------------------+
- */
- #include "zend_ast.h"
- #include "zend_API.h"
- #include "zend_operators.h"
- #include "zend_language_parser.h"
- #include "zend_smart_str.h"
- #include "zend_exceptions.h"
- #include "zend_constants.h"
- ZEND_API zend_ast_process_t zend_ast_process = NULL;
- static inline void *zend_ast_alloc(size_t size) {
- return zend_arena_alloc(&CG(ast_arena), size);
- }
- static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
- void *new = zend_ast_alloc(new_size);
- memcpy(new, old, old_size);
- return new;
- }
- static inline size_t zend_ast_size(uint32_t children) {
- return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
- }
- static inline size_t zend_ast_list_size(uint32_t children) {
- return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
- zend_ast_znode *ast;
- ast = zend_ast_alloc(sizeof(zend_ast_znode));
- ast->kind = ZEND_AST_ZNODE;
- ast->attr = 0;
- ast->lineno = CG(zend_lineno);
- ast->node = *node;
- return (zend_ast *) ast;
- }
- static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t attr, uint32_t lineno) {
- zend_ast_zval *ast;
- ast = zend_ast_alloc(sizeof(zend_ast_zval));
- ast->kind = ZEND_AST_ZVAL;
- ast->attr = attr;
- ZVAL_COPY_VALUE(&ast->val, zv);
- Z_LINENO(ast->val) = lineno;
- return (zend_ast *) ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno) {
- return zend_ast_create_zval_int(zv, 0, lineno);
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
- return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv) {
- return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
- zval zv;
- ZVAL_STR(&zv, str);
- return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
- zval zv;
- ZVAL_LONG(&zv, lval);
- return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
- zend_ast_zval *ast;
- ast = zend_ast_alloc(sizeof(zend_ast_zval));
- ast->kind = ZEND_AST_CONSTANT;
- ast->attr = attr;
- ZVAL_STR(&ast->val, name);
- Z_LINENO(ast->val) = CG(zend_lineno);
- return (zend_ast *) ast;
- }
- ZEND_API zend_ast *zend_ast_create_decl(
- zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
- zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
- ) {
- zend_ast_decl *ast;
- ast = zend_ast_alloc(sizeof(zend_ast_decl));
- ast->kind = kind;
- ast->attr = 0;
- ast->start_lineno = start_lineno;
- ast->end_lineno = CG(zend_lineno);
- ast->flags = flags;
- ast->lex_pos = LANG_SCNG(yy_text);
- ast->doc_comment = doc_comment;
- ast->name = name;
- ast->child[0] = child0;
- ast->child[1] = child1;
- ast->child[2] = child2;
- ast->child[3] = child3;
- return (zend_ast *) ast;
- }
- #if ZEND_AST_SPEC
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
- zend_ast *ast;
- ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
- ast = zend_ast_alloc(zend_ast_size(0));
- ast->kind = kind;
- ast->attr = 0;
- ast->lineno = CG(zend_lineno);
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
- zend_ast *ast;
- uint32_t lineno;
- ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
- ast = zend_ast_alloc(zend_ast_size(1));
- ast->kind = kind;
- ast->attr = 0;
- ast->child[0] = child;
- if (child) {
- lineno = zend_ast_get_lineno(child);
- } else {
- lineno = CG(zend_lineno);
- }
- ast->lineno = lineno;
- ast->lineno = lineno;
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
- zend_ast *ast;
- uint32_t lineno;
- ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
- ast = zend_ast_alloc(zend_ast_size(2));
- ast->kind = kind;
- ast->attr = 0;
- ast->child[0] = child1;
- ast->child[1] = child2;
- if (child1) {
- lineno = zend_ast_get_lineno(child1);
- } else if (child2) {
- lineno = zend_ast_get_lineno(child2);
- } else {
- lineno = CG(zend_lineno);
- }
- ast->lineno = lineno;
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
- zend_ast *ast;
- uint32_t lineno;
- ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
- ast = zend_ast_alloc(zend_ast_size(3));
- ast->kind = kind;
- ast->attr = 0;
- ast->child[0] = child1;
- ast->child[1] = child2;
- ast->child[2] = child3;
- if (child1) {
- lineno = zend_ast_get_lineno(child1);
- } else if (child2) {
- lineno = zend_ast_get_lineno(child2);
- } else if (child3) {
- lineno = zend_ast_get_lineno(child3);
- } else {
- lineno = CG(zend_lineno);
- }
- ast->lineno = lineno;
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
- zend_ast *ast;
- uint32_t lineno;
- ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
- ast = zend_ast_alloc(zend_ast_size(4));
- ast->kind = kind;
- ast->attr = 0;
- ast->child[0] = child1;
- ast->child[1] = child2;
- ast->child[2] = child3;
- ast->child[3] = child4;
- if (child1) {
- lineno = zend_ast_get_lineno(child1);
- } else if (child2) {
- lineno = zend_ast_get_lineno(child2);
- } else if (child3) {
- lineno = zend_ast_get_lineno(child3);
- } else if (child4) {
- lineno = zend_ast_get_lineno(child4);
- } else {
- lineno = CG(zend_lineno);
- }
- ast->lineno = lineno;
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
- zend_ast *ast;
- zend_ast_list *list;
- ast = zend_ast_alloc(zend_ast_list_size(4));
- list = (zend_ast_list *) ast;
- list->kind = kind;
- list->attr = 0;
- list->lineno = CG(zend_lineno);
- list->children = 0;
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
- zend_ast *ast;
- zend_ast_list *list;
- uint32_t lineno;
- ast = zend_ast_alloc(zend_ast_list_size(4));
- list = (zend_ast_list *) ast;
- list->kind = kind;
- list->attr = 0;
- list->children = 1;
- list->child[0] = child;
- if (child) {
- lineno = zend_ast_get_lineno(child);
- if (lineno > CG(zend_lineno)) {
- lineno = CG(zend_lineno);
- }
- } else {
- lineno = CG(zend_lineno);
- }
- list->lineno = lineno;
- return ast;
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
- zend_ast *ast;
- zend_ast_list *list;
- uint32_t lineno;
- ast = zend_ast_alloc(zend_ast_list_size(4));
- list = (zend_ast_list *) ast;
- list->kind = kind;
- list->attr = 0;
- list->children = 2;
- list->child[0] = child1;
- list->child[1] = child2;
- if (child1) {
- lineno = zend_ast_get_lineno(child1);
- if (lineno > CG(zend_lineno)) {
- lineno = CG(zend_lineno);
- }
- } else if (child2) {
- lineno = zend_ast_get_lineno(child2);
- if (lineno > CG(zend_lineno)) {
- lineno = CG(zend_lineno);
- }
- } else {
- list->children = 0;
- lineno = CG(zend_lineno);
- }
- list->lineno = lineno;
- return ast;
- }
- #else
- static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
- uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
- zend_ast *ast;
- ast = zend_ast_alloc(zend_ast_size(children));
- ast->kind = kind;
- ast->attr = attr;
- ast->lineno = (uint32_t) -1;
- for (i = 0; i < children; ++i) {
- ast->child[i] = va_arg(va, zend_ast *);
- if (ast->child[i] != NULL) {
- uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
- if (lineno < ast->lineno) {
- ast->lineno = lineno;
- }
- }
- }
- if (ast->lineno == UINT_MAX) {
- ast->lineno = CG(zend_lineno);
- }
- return ast;
- }
- ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
- va_list va;
- zend_ast *ast;
- va_start(va, attr);
- ast = zend_ast_create_from_va_list(kind, attr, va);
- va_end(va);
- return ast;
- }
- ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
- va_list va;
- zend_ast *ast;
- va_start(va, kind);
- ast = zend_ast_create_from_va_list(kind, 0, va);
- va_end(va);
- return ast;
- }
- ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
- zend_ast *ast;
- zend_ast_list *list;
- ast = zend_ast_alloc(zend_ast_list_size(4));
- list = (zend_ast_list *) ast;
- list->kind = kind;
- list->attr = 0;
- list->lineno = CG(zend_lineno);
- list->children = 0;
- {
- va_list va;
- uint32_t i;
- va_start(va, kind);
- for (i = 0; i < init_children; ++i) {
- zend_ast *child = va_arg(va, zend_ast *);
- ast = zend_ast_list_add(ast, child);
- if (child != NULL) {
- uint32_t lineno = zend_ast_get_lineno(child);
- if (lineno < ast->lineno) {
- ast->lineno = lineno;
- }
- }
- }
- va_end(va);
- }
- return ast;
- }
- #endif
- static inline zend_bool is_power_of_two(uint32_t n) {
- return ((n != 0) && (n == (n & (~n + 1))));
- }
- ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) {
- zend_ast_list *list = zend_ast_get_list(ast);
- if (list->children >= 4 && is_power_of_two(list->children)) {
- list = zend_ast_realloc(list,
- zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
- }
- list->child[list->children++] = op;
- return (zend_ast *) list;
- }
- static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
- {
- switch (Z_TYPE_P(offset)) {
- case IS_UNDEF:
- if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
- zend_error(E_WARNING,
- "Cannot add element to the array as the next element is already occupied");
- zval_ptr_dtor_nogc(expr);
- }
- break;
- case IS_STRING:
- zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
- zval_ptr_dtor_str(offset);
- break;
- case IS_NULL:
- zend_symtable_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), expr);
- break;
- case IS_LONG:
- zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), expr);
- break;
- case IS_FALSE:
- zend_hash_index_update(Z_ARRVAL_P(result), 0, expr);
- break;
- case IS_TRUE:
- zend_hash_index_update(Z_ARRVAL_P(result), 1, expr);
- break;
- case IS_DOUBLE:
- zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
- break;
- case IS_RESOURCE:
- zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
- zend_hash_index_update(Z_ARRVAL_P(result), Z_RES_HANDLE_P(offset), expr);
- break;
- default:
- zend_throw_error(NULL, "Illegal offset type");
- return FAILURE;
- }
- return SUCCESS;
- }
- ZEND_API int ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
- {
- zval op1, op2;
- int ret = SUCCESS;
- switch (ast->kind) {
- case ZEND_AST_BINARY_OP:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- } else {
- binary_op_type op = get_binary_op(ast->attr);
- ret = op(result, &op1, &op2);
- zval_ptr_dtor_nogc(&op1);
- zval_ptr_dtor_nogc(&op2);
- }
- break;
- case ZEND_AST_GREATER:
- case ZEND_AST_GREATER_EQUAL:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- } else {
- /* op1 > op2 is the same as op2 < op1 */
- binary_op_type op = ast->kind == ZEND_AST_GREATER
- ? is_smaller_function : is_smaller_or_equal_function;
- ret = op(result, &op2, &op1);
- zval_ptr_dtor_nogc(&op1);
- zval_ptr_dtor_nogc(&op2);
- }
- break;
- case ZEND_AST_UNARY_OP:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- } else {
- unary_op_type op = get_unary_op(ast->attr);
- ret = op(result, &op1);
- zval_ptr_dtor_nogc(&op1);
- }
- break;
- case ZEND_AST_ZVAL:
- {
- zval *zv = zend_ast_get_zval(ast);
- ZVAL_COPY(result, zv);
- break;
- }
- case ZEND_AST_CONSTANT:
- {
- zend_string *name = zend_ast_get_constant_name(ast);
- zval *zv = zend_get_constant_ex(name, scope, ast->attr);
- if (UNEXPECTED(zv == NULL)) {
- ZVAL_UNDEF(result);
- ret = zend_use_undefined_constant(name, ast->attr, result);
- break;
- }
- ZVAL_COPY_OR_DUP(result, zv);
- break;
- }
- case ZEND_AST_CONSTANT_CLASS:
- ZEND_ASSERT(EG(current_execute_data));
- if (scope && scope->name) {
- ZVAL_STR_COPY(result, scope->name);
- } else {
- ZVAL_EMPTY_STRING(result);
- }
- break;
- case ZEND_AST_AND:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- break;
- }
- if (zend_is_true(&op1)) {
- if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- break;
- }
- ZVAL_BOOL(result, zend_is_true(&op2));
- zval_ptr_dtor_nogc(&op2);
- } else {
- ZVAL_FALSE(result);
- }
- zval_ptr_dtor_nogc(&op1);
- break;
- case ZEND_AST_OR:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- break;
- }
- if (zend_is_true(&op1)) {
- ZVAL_TRUE(result);
- } else {
- if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- break;
- }
- ZVAL_BOOL(result, zend_is_true(&op2));
- zval_ptr_dtor_nogc(&op2);
- }
- zval_ptr_dtor_nogc(&op1);
- break;
- case ZEND_AST_CONDITIONAL:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- break;
- }
- if (zend_is_true(&op1)) {
- if (!ast->child[1]) {
- *result = op1;
- } else {
- if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- break;
- }
- zval_ptr_dtor_nogc(&op1);
- }
- } else {
- if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- break;
- }
- zval_ptr_dtor_nogc(&op1);
- }
- break;
- case ZEND_AST_COALESCE:
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- break;
- }
- if (Z_TYPE(op1) > IS_NULL) {
- *result = op1;
- } else {
- if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- break;
- }
- zval_ptr_dtor_nogc(&op1);
- }
- break;
- case ZEND_AST_UNARY_PLUS:
- if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- } else {
- ZVAL_LONG(&op1, 0);
- ret = add_function(result, &op1, &op2);
- zval_ptr_dtor_nogc(&op2);
- }
- break;
- case ZEND_AST_UNARY_MINUS:
- if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- } else {
- ZVAL_LONG(&op1, 0);
- ret = sub_function(result, &op1, &op2);
- zval_ptr_dtor_nogc(&op2);
- }
- break;
- case ZEND_AST_ARRAY:
- {
- uint32_t i;
- zend_ast_list *list = zend_ast_get_list(ast);
- if (!list->children) {
- ZVAL_EMPTY_ARRAY(result);
- break;
- }
- array_init(result);
- for (i = 0; i < list->children; i++) {
- zend_ast *elem = list->child[i];
- if (elem->child[1]) {
- if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(result);
- return FAILURE;
- }
- } else {
- ZVAL_UNDEF(&op1);
- }
- if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- zval_ptr_dtor_nogc(result);
- return FAILURE;
- }
- if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- zval_ptr_dtor_nogc(&op2);
- zval_ptr_dtor_nogc(result);
- return FAILURE;
- }
- }
- }
- break;
- case ZEND_AST_DIM:
- if (ast->child[1] == NULL) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
- }
- if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
- ret = FAILURE;
- } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
- zval_ptr_dtor_nogc(&op1);
- ret = FAILURE;
- } else {
- zend_fetch_dimension_const(result, &op1, &op2, (ast->attr == ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
- zval_ptr_dtor_nogc(&op1);
- zval_ptr_dtor_nogc(&op2);
- }
- break;
- default:
- zend_throw_error(NULL, "Unsupported constant expression");
- ret = FAILURE;
- }
- return ret;
- }
- static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
- {
- size_t size;
- if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
- size = sizeof(zend_ast_zval);
- } else if (zend_ast_is_list(ast)) {
- uint32_t i;
- zend_ast_list *list = zend_ast_get_list(ast);
- size = zend_ast_list_size(list->children);
- for (i = 0; i < list->children; i++) {
- if (list->child[i]) {
- size += zend_ast_tree_size(list->child[i]);
- }
- }
- } else {
- uint32_t i, children = zend_ast_get_num_children(ast);
- size = zend_ast_size(children);
- for (i = 0; i < children; i++) {
- if (ast->child[i]) {
- size += zend_ast_tree_size(ast->child[i]);
- }
- }
- }
- return size;
- }
- static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
- {
- if (ast->kind == ZEND_AST_ZVAL) {
- zend_ast_zval *new = (zend_ast_zval*)buf;
- new->kind = ZEND_AST_ZVAL;
- new->attr = ast->attr;
- ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
- buf = (void*)((char*)buf + sizeof(zend_ast_zval));
- } else if (ast->kind == ZEND_AST_CONSTANT) {
- zend_ast_zval *new = (zend_ast_zval*)buf;
- new->kind = ZEND_AST_CONSTANT;
- new->attr = ast->attr;
- ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
- buf = (void*)((char*)buf + sizeof(zend_ast_zval));
- } else if (zend_ast_is_list(ast)) {
- zend_ast_list *list = zend_ast_get_list(ast);
- zend_ast_list *new = (zend_ast_list*)buf;
- uint32_t i;
- new->kind = list->kind;
- new->attr = list->attr;
- new->children = list->children;
- buf = (void*)((char*)buf + zend_ast_list_size(list->children));
- for (i = 0; i < list->children; i++) {
- if (list->child[i]) {
- new->child[i] = (zend_ast*)buf;
- buf = zend_ast_tree_copy(list->child[i], buf);
- } else {
- new->child[i] = NULL;
- }
- }
- } else {
- uint32_t i, children = zend_ast_get_num_children(ast);
- zend_ast *new = (zend_ast*)buf;
- new->kind = ast->kind;
- new->attr = ast->attr;
- buf = (void*)((char*)buf + zend_ast_size(children));
- for (i = 0; i < children; i++) {
- if (ast->child[i]) {
- new->child[i] = (zend_ast*)buf;
- buf = zend_ast_tree_copy(ast->child[i], buf);
- } else {
- new->child[i] = NULL;
- }
- }
- }
- return buf;
- }
- ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast)
- {
- size_t tree_size;
- zend_ast_ref *ref;
- ZEND_ASSERT(ast != NULL);
- tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
- ref = emalloc(tree_size);
- zend_ast_tree_copy(ast, GC_AST(ref));
- GC_SET_REFCOUNT(ref, 1);
- GC_TYPE_INFO(ref) = IS_CONSTANT_AST;
- return ref;
- }
- ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
- {
- tail_call:
- if (!ast) {
- return;
- }
- if (EXPECTED(ast->kind >= ZEND_AST_VAR)) {
- uint32_t i, children = zend_ast_get_num_children(ast);
- for (i = 1; i < children; i++) {
- zend_ast_destroy(ast->child[i]);
- }
- ast = ast->child[0];
- goto tail_call;
- } else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) {
- zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
- } else if (EXPECTED(zend_ast_is_list(ast))) {
- zend_ast_list *list = zend_ast_get_list(ast);
- if (list->children) {
- uint32_t i;
- for (i = 1; i < list->children; i++) {
- zend_ast_destroy(list->child[i]);
- }
- ast = list->child[0];
- goto tail_call;
- }
- } else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
- zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
- } else if (EXPECTED(ast->kind >= ZEND_AST_FUNC_DECL)) {
- zend_ast_decl *decl = (zend_ast_decl *) ast;
- if (decl->name) {
- zend_string_release_ex(decl->name, 0);
- }
- if (decl->doc_comment) {
- zend_string_release_ex(decl->doc_comment, 0);
- }
- zend_ast_destroy(decl->child[0]);
- zend_ast_destroy(decl->child[1]);
- zend_ast_destroy(decl->child[2]);
- ast = decl->child[3];
- goto tail_call;
- }
- }
- ZEND_API void ZEND_FASTCALL zend_ast_ref_destroy(zend_ast_ref *ast)
- {
- zend_ast_destroy(GC_AST(ast));
- efree(ast);
- }
- ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
- if (zend_ast_is_list(ast)) {
- zend_ast_list *list = zend_ast_get_list(ast);
- uint32_t i;
- for (i = 0; i < list->children; ++i) {
- fn(&list->child[i]);
- }
- } else {
- uint32_t i, children = zend_ast_get_num_children(ast);
- for (i = 0; i < children; ++i) {
- fn(&ast->child[i]);
- }
- }
- }
- /*
- * Operator Precendence
- * ====================
- * priority associativity operators
- * ----------------------------------
- * 10 left include, include_once, eval, require, require_once
- * 20 left ,
- * 30 left or
- * 40 left xor
- * 50 left and
- * 60 right print
- * 70 right yield
- * 80 right =>
- * 85 right yield from
- * 90 right = += -= *= /= .= %= &= |= ^= <<= >>= **=
- * 100 left ? :
- * 110 right ??
- * 120 left ||
- * 130 left &&
- * 140 left |
- * 150 left ^
- * 160 left &
- * 170 non-associative == != === !==
- * 180 non-associative < <= > >= <=>
- * 190 left << >>
- * 200 left + - .
- * 210 left * / %
- * 220 right !
- * 230 non-associative instanceof
- * 240 right + - ++ -- ~ (type) @
- * 250 right **
- * 260 left [
- * 270 non-associative clone new
- */
- static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
- static ZEND_COLD void zend_ast_export_str(smart_str *str, zend_string *s)
- {
- size_t i;
- for (i = 0; i < ZSTR_LEN(s); i++) {
- unsigned char c = ZSTR_VAL(s)[i];
- if (c == '\'' || c == '\\') {
- smart_str_appendc(str, '\\');
- smart_str_appendc(str, c);
- } else {
- smart_str_appendc(str, c);
- }
- }
- }
- static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
- {
- size_t i;
- for (i = 0; i < ZSTR_LEN(s); i++) {
- unsigned char c = ZSTR_VAL(s)[i];
- if (c < ' ') {
- switch (c) {
- case '\n':
- smart_str_appends(str, "\\n");
- break;
- case '\r':
- smart_str_appends(str, "\\r");
- break;
- case '\t':
- smart_str_appends(str, "\\t");
- break;
- case '\f':
- smart_str_appends(str, "\\f");
- break;
- case '\v':
- smart_str_appends(str, "\\v");
- break;
- #ifdef ZEND_WIN32
- case VK_ESCAPE:
- #else
- case '\e':
- #endif
- smart_str_appends(str, "\\e");
- break;
- default:
- smart_str_appends(str, "\\0");
- smart_str_appendc(str, '0' + (c / 8));
- smart_str_appendc(str, '0' + (c % 8));
- break;
- }
- } else {
- if (c == quote || c == '$' || c == '\\') {
- smart_str_appendc(str, '\\');
- }
- smart_str_appendc(str, c);
- }
- }
- }
- static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent)
- {
- while (indent > 0) {
- smart_str_appends(str, " ");
- indent--;
- }
- }
- static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
- {
- if (ast->kind == ZEND_AST_ZVAL) {
- zval *zv = zend_ast_get_zval(ast);
- if (Z_TYPE_P(zv) == IS_STRING) {
- smart_str_append(str, Z_STR_P(zv));
- return;
- }
- }
- zend_ast_export_ex(str, ast, priority, indent);
- }
- static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
- {
- if (ast->kind == ZEND_AST_ZVAL) {
- zval *zv = zend_ast_get_zval(ast);
- if (Z_TYPE_P(zv) == IS_STRING) {
- if (ast->attr == ZEND_NAME_FQ) {
- smart_str_appendc(str, '\\');
- } else if (ast->attr == ZEND_NAME_RELATIVE) {
- smart_str_appends(str, "namespace\\");
- }
- smart_str_append(str, Z_STR_P(zv));
- return;
- }
- }
- zend_ast_export_ex(str, ast, priority, indent);
- }
- static ZEND_COLD int zend_ast_valid_var_char(char ch)
- {
- unsigned char c = (unsigned char)ch;
- if (c != '_' && c < 127 &&
- (c < '0' || c > '9') &&
- (c < 'A' || c > 'Z') &&
- (c < 'a' || c > 'z')) {
- return 0;
- }
- return 1;
- }
- static ZEND_COLD int zend_ast_valid_var_name(const char *s, size_t len)
- {
- unsigned char c;
- size_t i;
- if (len == 0) {
- return 0;
- }
- c = (unsigned char)s[0];
- if (c != '_' && c < 127 &&
- (c < 'A' || c > 'Z') &&
- (c < 'a' || c > 'z')) {
- return 0;
- }
- for (i = 1; i < len; i++) {
- c = (unsigned char)s[i];
- if (c != '_' && c < 127 &&
- (c < '0' || c > '9') &&
- (c < 'A' || c > 'Z') &&
- (c < 'a' || c > 'z')) {
- return 0;
- }
- }
- return 1;
- }
- static ZEND_COLD int zend_ast_var_needs_braces(char ch)
- {
- return ch == '[' || zend_ast_valid_var_char(ch);
- }
- static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
- {
- if (ast->kind == ZEND_AST_ZVAL) {
- zval *zv = zend_ast_get_zval(ast);
- if (Z_TYPE_P(zv) == IS_STRING &&
- zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
- smart_str_append(str, Z_STR_P(zv));
- return;
- }
- } else if (ast->kind == ZEND_AST_VAR) {
- zend_ast_export_ex(str, ast, 0, indent);
- return;
- }
- smart_str_appendc(str, '{');
- zend_ast_export_name(str, ast, 0, indent);
- smart_str_appendc(str, '}');
- }
- static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, int separator, int priority, int indent)
- {
- uint32_t i = 0;
- while (i < list->children) {
- if (i != 0 && separator) {
- smart_str_appends(str, ", ");
- }
- zend_ast_export_ex(str, list->child[i], priority, indent);
- i++;
- }
- }
- static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
- {
- uint32_t i = 0;
- zend_ast *ast;
- while (i < list->children) {
- ast = list->child[i];
- if (ast->kind == ZEND_AST_ZVAL) {
- zval *zv = zend_ast_get_zval(ast);
- ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
- zend_ast_export_qstr(str, quote, Z_STR_P(zv));
- } else if (ast->kind == ZEND_AST_VAR &&
- ast->child[0]->kind == ZEND_AST_ZVAL &&
- (i + 1 == list->children ||
- list->child[i + 1]->kind != ZEND_AST_ZVAL ||
- !zend_ast_var_needs_braces(
- *Z_STRVAL_P(
- zend_ast_get_zval(list->child[i + 1]))))) {
- zend_ast_export_ex(str, ast, 0, indent);
- } else {
- smart_str_appendc(str, '{');
- zend_ast_export_ex(str, ast, 0, indent);
- smart_str_appendc(str, '}');
- }
- i++;
- }
- }
- static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list *list, int indent, const char *separator)
- {
- uint32_t i = 0;
- while (i < list->children) {
- if (i != 0) {
- smart_str_appends(str, separator);
- }
- zend_ast_export_name(str, list->child[i], 0, indent);
- i++;
- }
- }
- #define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ")
- #define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|")
- static ZEND_COLD void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
- {
- uint32_t i = 0;
- while (i < list->children) {
- if (i != 0) {
- smart_str_appends(str, ", ");
- }
- if (list->child[i]->attr) {
- smart_str_appendc(str, '&');
- }
- smart_str_appendc(str, '$');
- zend_ast_export_name(str, list->child[i], 20, indent);
- i++;
- }
- }
- static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
- {
- if (!ast) {
- return;
- }
- if (ast->kind == ZEND_AST_STMT_LIST ||
- ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
- zend_ast_list *list = (zend_ast_list*)ast;
- uint32_t i = 0;
- while (i < list->children) {
- ast = list->child[i];
- zend_ast_export_stmt(str, ast, indent);
- i++;
- }
- } else {
- zend_ast_export_indent(str, indent);
- zend_ast_export_ex(str, ast, 0, indent);
- switch (ast->kind) {
- case ZEND_AST_LABEL:
- case ZEND_AST_IF:
- case ZEND_AST_SWITCH:
- case ZEND_AST_WHILE:
- case ZEND_AST_TRY:
- case ZEND_AST_FOR:
- case ZEND_AST_FOREACH:
- case ZEND_AST_FUNC_DECL:
- case ZEND_AST_METHOD:
- case ZEND_AST_CLASS:
- case ZEND_AST_USE_TRAIT:
- case ZEND_AST_NAMESPACE:
- case ZEND_AST_DECLARE:
- break;
- default:
- smart_str_appendc(str, ';');
- break;
- }
- smart_str_appendc(str, '\n');
- }
- }
- static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
- {
- uint32_t i;
- zend_ast *ast;
- tail_call:
- i = 0;
- while (i < list->children) {
- ast = list->child[i];
- ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
- if (ast->child[0]) {
- if (i == 0) {
- smart_str_appends(str, "if (");
- } else {
- zend_ast_export_indent(str, indent);
- smart_str_appends(str, "} elseif (");
- }
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, ") {\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- } else {
- zend_ast_export_indent(str, indent);
- smart_str_appends(str, "} else ");
- if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) {
- list = (zend_ast_list*)ast->child[1];
- goto tail_call;
- } else {
- smart_str_appends(str, "{\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- }
- }
- i++;
- }
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- }
- static ZEND_COLD void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
- {
- zend_long idx;
- zend_string *key;
- zval *val;
- int first;
- ZVAL_DEREF(zv);
- switch (Z_TYPE_P(zv)) {
- case IS_NULL:
- smart_str_appends(str, "null");
- break;
- case IS_FALSE:
- smart_str_appends(str, "false");
- break;
- case IS_TRUE:
- smart_str_appends(str, "true");
- break;
- case IS_LONG:
- smart_str_append_long(str, Z_LVAL_P(zv));
- break;
- case IS_DOUBLE:
- key = zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(zv));
- smart_str_appendl(str, ZSTR_VAL(key), ZSTR_LEN(key));
- zend_string_release_ex(key, 0);
- break;
- case IS_STRING:
- smart_str_appendc(str, '\'');
- zend_ast_export_str(str, Z_STR_P(zv));
- smart_str_appendc(str, '\'');
- break;
- case IS_ARRAY:
- smart_str_appendc(str, '[');
- first = 1;
- ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
- if (first) {
- first = 0;
- } else {
- smart_str_appends(str, ", ");
- }
- if (key) {
- smart_str_appendc(str, '\'');
- zend_ast_export_str(str, key);
- smart_str_appends(str, "' => ");
- } else {
- smart_str_append_long(str, idx);
- smart_str_appends(str, " => ");
- }
- zend_ast_export_zval(str, val, 0, indent);
- } ZEND_HASH_FOREACH_END();
- smart_str_appendc(str, ']');
- break;
- case IS_CONSTANT_AST:
- zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- }
- static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) {
- if (decl->child[0]) {
- smart_str_appends(str, " extends ");
- zend_ast_export_ns_name(str, decl->child[0], 0, indent);
- }
- if (decl->child[1]) {
- smart_str_appends(str, " implements ");
- zend_ast_export_ex(str, decl->child[1], 0, indent);
- }
- smart_str_appends(str, " {\n");
- zend_ast_export_stmt(str, decl->child[2], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appends(str, "}");
- }
- #define BINARY_OP(_op, _p, _pl, _pr) do { \
- op = _op; \
- p = _p; \
- pl = _pl; \
- pr = _pr; \
- goto binary_op; \
- } while (0)
- #define PREFIX_OP(_op, _p, _pl) do { \
- op = _op; \
- p = _p; \
- pl = _pl; \
- goto prefix_op; \
- } while (0)
- #define FUNC_OP(_op) do { \
- op = _op; \
- goto func_op; \
- } while (0)
- #define POSTFIX_OP(_op, _p, _pl) do { \
- op = _op; \
- p = _p; \
- pl = _pl; \
- goto postfix_op; \
- } while (0)
- #define APPEND_NODE_1(_op) do { \
- op = _op; \
- goto append_node_1; \
- } while (0)
- #define APPEND_STR(_op) do { \
- op = _op; \
- goto append_str; \
- } while (0)
- #define APPEND_DEFAULT_VALUE(n) do { \
- p = n; \
- goto append_default_value; \
- } while (0)
- static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
- {
- zend_ast_decl *decl;
- int p, pl, pr;
- const char *op;
- tail_call:
- if (!ast) {
- return;
- }
- switch (ast->kind) {
- /* special nodes */
- case ZEND_AST_ZVAL:
- zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
- break;
- case ZEND_AST_CONSTANT: {
- zend_string *name = zend_ast_get_constant_name(ast);
- smart_str_appendl(str, ZSTR_VAL(name), ZSTR_LEN(name));
- break;
- }
- case ZEND_AST_CONSTANT_CLASS:
- smart_str_appendl(str, "__CLASS__", sizeof("__CLASS__")-1);
- break;
- case ZEND_AST_ZNODE:
- /* This AST kind is only used for temporary nodes during compilation */
- ZEND_ASSERT(0);
- break;
- /* declaration nodes */
- case ZEND_AST_FUNC_DECL:
- case ZEND_AST_CLOSURE:
- case ZEND_AST_METHOD:
- decl = (zend_ast_decl *) ast;
- if (decl->flags & ZEND_ACC_PUBLIC) {
- smart_str_appends(str, "public ");
- } else if (decl->flags & ZEND_ACC_PROTECTED) {
- smart_str_appends(str, "protected ");
- } else if (decl->flags & ZEND_ACC_PRIVATE) {
- smart_str_appends(str, "private ");
- }
- if (decl->flags & ZEND_ACC_STATIC) {
- smart_str_appends(str, "static ");
- }
- if (decl->flags & ZEND_ACC_ABSTRACT) {
- smart_str_appends(str, "abstract ");
- }
- if (decl->flags & ZEND_ACC_FINAL) {
- smart_str_appends(str, "final ");
- }
- smart_str_appends(str, "function ");
- if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
- smart_str_appendc(str, '&');
- }
- if (ast->kind != ZEND_AST_CLOSURE) {
- smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
- }
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, decl->child[0], 0, indent);
- smart_str_appendc(str, ')');
- zend_ast_export_ex(str, decl->child[1], 0, indent);
- if (decl->child[3]) {
- smart_str_appends(str, ": ");
- if (decl->child[3]->attr & ZEND_TYPE_NULLABLE) {
- smart_str_appendc(str, '?');
- }
- zend_ast_export_ns_name(str, decl->child[3], 0, indent);
- }
- if (decl->child[2]) {
- smart_str_appends(str, " {\n");
- zend_ast_export_stmt(str, decl->child[2], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- if (ast->kind != ZEND_AST_CLOSURE) {
- smart_str_appendc(str, '\n');
- }
- } else {
- smart_str_appends(str, ";\n");
- }
- break;
- case ZEND_AST_CLASS:
- decl = (zend_ast_decl *) ast;
- if (decl->flags & ZEND_ACC_INTERFACE) {
- smart_str_appends(str, "interface ");
- } else if (decl->flags & ZEND_ACC_TRAIT) {
- smart_str_appends(str, "trait ");
- } else {
- if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
- smart_str_appends(str, "abstract ");
- }
- if (decl->flags & ZEND_ACC_FINAL) {
- smart_str_appends(str, "final ");
- }
- smart_str_appends(str, "class ");
- }
- smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
- zend_ast_export_class_no_header(str, decl, indent);
- smart_str_appendc(str, '\n');
- break;
- /* list nodes */
- case ZEND_AST_ARG_LIST:
- case ZEND_AST_EXPR_LIST:
- case ZEND_AST_PARAM_LIST:
- simple_list:
- zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
- break;
- case ZEND_AST_ARRAY:
- smart_str_appendc(str, '[');
- zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
- smart_str_appendc(str, ']');
- break;
- case ZEND_AST_ENCAPS_LIST:
- smart_str_appendc(str, '"');
- zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
- smart_str_appendc(str, '"');
- break;
- case ZEND_AST_STMT_LIST:
- case ZEND_AST_TRAIT_ADAPTATIONS:
- zend_ast_export_stmt(str, ast, indent);
- break;
- case ZEND_AST_IF:
- zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
- break;
- case ZEND_AST_SWITCH_LIST:
- case ZEND_AST_CATCH_LIST:
- zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
- break;
- case ZEND_AST_CLOSURE_USES:
- smart_str_appends(str, " use(");
- zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
- smart_str_appendc(str, ')');
- break;
- case ZEND_AST_PROP_DECL:
- if (ast->attr & ZEND_ACC_PUBLIC) {
- smart_str_appends(str, "public ");
- } else if (ast->attr & ZEND_ACC_PROTECTED) {
- smart_str_appends(str, "protected ");
- } else if (ast->attr & ZEND_ACC_PRIVATE) {
- smart_str_appends(str, "private ");
- }
- if (ast->attr & ZEND_ACC_STATIC) {
- smart_str_appends(str, "static ");
- }
- goto simple_list;
- case ZEND_AST_CONST_DECL:
- case ZEND_AST_CLASS_CONST_DECL:
- smart_str_appends(str, "const ");
- goto simple_list;
- case ZEND_AST_NAME_LIST:
- zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
- break;
- case ZEND_AST_USE:
- smart_str_appends(str, "use ");
- if (ast->attr == T_FUNCTION) {
- smart_str_appends(str, "function ");
- } else if (ast->attr == T_CONST) {
- smart_str_appends(str, "const ");
- }
- goto simple_list;
- /* 0 child nodes */
- case ZEND_AST_MAGIC_CONST:
- switch (ast->attr) {
- case T_LINE: APPEND_STR("__LINE__");
- case T_FILE: APPEND_STR("__FILE__");
- case T_DIR: APPEND_STR("__DIR__");
- case T_TRAIT_C: APPEND_STR("__TRAIT__");
- case T_METHOD_C: APPEND_STR("__METHOD__");
- case T_FUNC_C: APPEND_STR("__FUNCTION__");
- case T_NS_C: APPEND_STR("__NAMESPACE__");
- case T_CLASS_C: APPEND_STR("__CLASS__");
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- case ZEND_AST_TYPE:
- switch (ast->attr & ~ZEND_TYPE_NULLABLE) {
- case IS_ARRAY: APPEND_STR("array");
- case IS_CALLABLE: APPEND_STR("callable");
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- /* 1 child node */
- case ZEND_AST_VAR:
- smart_str_appendc(str, '$');
- zend_ast_export_var(str, ast->child[0], 0, indent);
- break;
- case ZEND_AST_CONST:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- break;
- case ZEND_AST_UNPACK:
- smart_str_appends(str, "...");
- ast = ast->child[0];
- goto tail_call;
- case ZEND_AST_UNARY_PLUS: PREFIX_OP("+", 240, 241);
- case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
- case ZEND_AST_CAST:
- switch (ast->attr) {
- case IS_NULL: PREFIX_OP("(unset)", 240, 241);
- case _IS_BOOL: PREFIX_OP("(bool)", 240, 241);
- case IS_LONG: PREFIX_OP("(int)", 240, 241);
- case IS_DOUBLE: PREFIX_OP("(double)", 240, 241);
- case IS_STRING: PREFIX_OP("(string)", 240, 241);
- case IS_ARRAY: PREFIX_OP("(array)", 240, 241);
- case IS_OBJECT: PREFIX_OP("(object)", 240, 241);
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- case ZEND_AST_EMPTY:
- FUNC_OP("empty");
- case ZEND_AST_ISSET:
- FUNC_OP("isset");
- case ZEND_AST_SILENCE:
- PREFIX_OP("@", 240, 241);
- case ZEND_AST_SHELL_EXEC:
- smart_str_appendc(str, '`');
- if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
- zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
- } else {
- zval *zv;
- ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
- zv = zend_ast_get_zval(ast->child[0]);
- ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
- zend_ast_export_qstr(str, '`', Z_STR_P(zv));
- }
- smart_str_appendc(str, '`');
- break;
- case ZEND_AST_CLONE:
- PREFIX_OP("clone ", 270, 271);
- case ZEND_AST_EXIT:
- if (ast->child[0]) {
- FUNC_OP("exit");
- } else {
- APPEND_STR("exit");
- }
- break;
- case ZEND_AST_PRINT:
- PREFIX_OP("print ", 60, 61);
- case ZEND_AST_INCLUDE_OR_EVAL:
- switch (ast->attr) {
- case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
- case ZEND_INCLUDE: FUNC_OP("include");
- case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
- case ZEND_REQUIRE: FUNC_OP("require");
- case ZEND_EVAL: FUNC_OP("eval");
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- case ZEND_AST_UNARY_OP:
- switch (ast->attr) {
- case ZEND_BW_NOT: PREFIX_OP("~", 240, 241);
- case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- case ZEND_AST_PRE_INC:
- PREFIX_OP("++", 240, 241);
- case ZEND_AST_PRE_DEC:
- PREFIX_OP("--", 240, 241);
- case ZEND_AST_POST_INC:
- POSTFIX_OP("++", 240, 241);
- case ZEND_AST_POST_DEC:
- POSTFIX_OP("--", 240, 241);
- case ZEND_AST_GLOBAL:
- APPEND_NODE_1("global");
- case ZEND_AST_UNSET:
- FUNC_OP("unset");
- case ZEND_AST_RETURN:
- APPEND_NODE_1("return");
- case ZEND_AST_LABEL:
- zend_ast_export_name(str, ast->child[0], 0, indent);
- smart_str_appendc(str, ':');
- break;
- case ZEND_AST_REF:
- smart_str_appendc(str, '&');
- ast = ast->child[0];
- goto tail_call;
- case ZEND_AST_HALT_COMPILER:
- APPEND_STR("__HALT_COMPILER()");
- case ZEND_AST_ECHO:
- APPEND_NODE_1("echo");
- case ZEND_AST_THROW:
- APPEND_NODE_1("throw");
- case ZEND_AST_GOTO:
- smart_str_appends(str, "goto ");
- zend_ast_export_name(str, ast->child[0], 0, indent);
- break;
- case ZEND_AST_BREAK:
- APPEND_NODE_1("break");
- case ZEND_AST_CONTINUE:
- APPEND_NODE_1("continue");
- /* 2 child nodes */
- case ZEND_AST_DIM:
- zend_ast_export_ex(str, ast->child[0], 260, indent);
- smart_str_appendc(str, '[');
- if (ast->child[1]) {
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- }
- smart_str_appendc(str, ']');
- break;
- case ZEND_AST_PROP:
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, "->");
- zend_ast_export_var(str, ast->child[1], 0, indent);
- break;
- case ZEND_AST_STATIC_PROP:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- smart_str_appends(str, "::$");
- zend_ast_export_var(str, ast->child[1], 0, indent);
- break;
- case ZEND_AST_CALL:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- smart_str_appendc(str, ')');
- break;
- case ZEND_AST_CLASS_CONST:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- smart_str_appends(str, "::");
- zend_ast_export_name(str, ast->child[1], 0, indent);
- break;
- case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);
- case ZEND_AST_ASSIGN_REF: BINARY_OP(" =& ", 90, 91, 90);
- case ZEND_AST_ASSIGN_OP:
- switch (ast->attr) {
- case ZEND_ASSIGN_ADD: BINARY_OP(" += ", 90, 91, 90);
- case ZEND_ASSIGN_SUB: BINARY_OP(" -= ", 90, 91, 90);
- case ZEND_ASSIGN_MUL: BINARY_OP(" *= ", 90, 91, 90);
- case ZEND_ASSIGN_DIV: BINARY_OP(" /= ", 90, 91, 90);
- case ZEND_ASSIGN_MOD: BINARY_OP(" %= ", 90, 91, 90);
- case ZEND_ASSIGN_SL: BINARY_OP(" <<= ", 90, 91, 90);
- case ZEND_ASSIGN_SR: BINARY_OP(" >>= ", 90, 91, 90);
- case ZEND_ASSIGN_CONCAT: BINARY_OP(" .= ", 90, 91, 90);
- case ZEND_ASSIGN_BW_OR: BINARY_OP(" |= ", 90, 91, 90);
- case ZEND_ASSIGN_BW_AND: BINARY_OP(" &= ", 90, 91, 90);
- case ZEND_ASSIGN_BW_XOR: BINARY_OP(" ^= ", 90, 91, 90);
- case ZEND_ASSIGN_POW: BINARY_OP(" **= ", 90, 91, 90);
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- case ZEND_AST_BINARY_OP:
- switch (ast->attr) {
- case ZEND_ADD: BINARY_OP(" + ", 200, 200, 201);
- case ZEND_SUB: BINARY_OP(" - ", 200, 200, 201);
- case ZEND_MUL: BINARY_OP(" * ", 210, 210, 211);
- case ZEND_DIV: BINARY_OP(" / ", 210, 210, 211);
- case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211);
- case ZEND_SL: BINARY_OP(" << ", 190, 190, 191);
- case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191);
- case ZEND_CONCAT: BINARY_OP(" . ", 200, 200, 201);
- case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141);
- case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161);
- case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151);
- case ZEND_IS_IDENTICAL: BINARY_OP(" === ", 170, 171, 171);
- case ZEND_IS_NOT_IDENTICAL: BINARY_OP(" !== ", 170, 171, 171);
- case ZEND_IS_EQUAL: BINARY_OP(" == ", 170, 171, 171);
- case ZEND_IS_NOT_EQUAL: BINARY_OP(" != ", 170, 171, 171);
- case ZEND_IS_SMALLER: BINARY_OP(" < ", 180, 181, 181);
- case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ", 180, 181, 181);
- case ZEND_POW: BINARY_OP(" ** ", 250, 251, 250);
- case ZEND_BOOL_XOR: BINARY_OP(" xor ", 40, 40, 41);
- case ZEND_SPACESHIP: BINARY_OP(" <=> ", 180, 181, 181);
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- break;
- case ZEND_AST_GREATER: BINARY_OP(" > ", 180, 181, 181);
- case ZEND_AST_GREATER_EQUAL: BINARY_OP(" >= ", 180, 181, 181);
- case ZEND_AST_AND: BINARY_OP(" && ", 130, 130, 131);
- case ZEND_AST_OR: BINARY_OP(" || ", 120, 120, 121);
- case ZEND_AST_ARRAY_ELEM:
- if (ast->child[1]) {
- zend_ast_export_ex(str, ast->child[1], 80, indent);
- smart_str_appends(str, " => ");
- }
- if (ast->attr)
- smart_str_appendc(str, '&');
- zend_ast_export_ex(str, ast->child[0], 80, indent);
- break;
- case ZEND_AST_NEW:
- smart_str_appends(str, "new ");
- if (ast->child[0]->kind == ZEND_AST_CLASS) {
- smart_str_appends(str, "class");
- if (zend_ast_get_list(ast->child[1])->children) {
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- smart_str_appendc(str, ')');
- }
- zend_ast_export_class_no_header(str, (zend_ast_decl *) ast->child[0], indent);
- } else {
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- smart_str_appendc(str, ')');
- }
- break;
- case ZEND_AST_INSTANCEOF:
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, " instanceof ");
- zend_ast_export_ns_name(str, ast->child[1], 0, indent);
- break;
- case ZEND_AST_YIELD:
- if (priority > 70) smart_str_appendc(str, '(');
- smart_str_appends(str, "yield ");
- if (ast->child[0]) {
- if (ast->child[1]) {
- zend_ast_export_ex(str, ast->child[1], 70, indent);
- smart_str_appends(str, " => ");
- }
- zend_ast_export_ex(str, ast->child[0], 70, indent);
- }
- if (priority > 70) smart_str_appendc(str, ')');
- break;
- case ZEND_AST_YIELD_FROM:
- PREFIX_OP("yield from ", 85, 86);
- case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
- case ZEND_AST_STATIC:
- smart_str_appends(str, "static $");
- zend_ast_export_name(str, ast->child[0], 0, indent);
- APPEND_DEFAULT_VALUE(1);
- case ZEND_AST_WHILE:
- smart_str_appends(str, "while (");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, ") {\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- break;
- case ZEND_AST_DO_WHILE:
- smart_str_appends(str, "do {\n");
- zend_ast_export_stmt(str, ast->child[0], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appends(str, "} while (");
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- smart_str_appendc(str, ')');
- break;
- case ZEND_AST_IF_ELEM:
- if (ast->child[0]) {
- smart_str_appends(str, "if (");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, ") {\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- } else {
- smart_str_appends(str, "else {\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- }
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- break;
- case ZEND_AST_SWITCH:
- smart_str_appends(str, "switch (");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, ") {\n");
- zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- break;
- case ZEND_AST_SWITCH_CASE:
- zend_ast_export_indent(str, indent);
- if (ast->child[0]) {
- smart_str_appends(str, "case ");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, ":\n");
- } else {
- smart_str_appends(str, "default:\n");
- }
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- break;
- case ZEND_AST_DECLARE:
- smart_str_appends(str, "declare(");
- ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
- zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
- smart_str_appendc(str, ')');
- if (ast->child[1]) {
- smart_str_appends(str, " {\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- } else {
- smart_str_appendc(str, ';');
- }
- break;
- case ZEND_AST_PROP_ELEM:
- smart_str_appendc(str, '$');
- /* break missing intentionally */
- case ZEND_AST_CONST_ELEM:
- zend_ast_export_name(str, ast->child[0], 0, indent);
- APPEND_DEFAULT_VALUE(1);
- case ZEND_AST_USE_TRAIT:
- smart_str_appends(str, "use ");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- if (ast->child[1]) {
- smart_str_appends(str, " {\n");
- zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appends(str, "}");
- } else {
- smart_str_appends(str, ";");
- }
- break;
- case ZEND_AST_TRAIT_PRECEDENCE:
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, " insteadof ");
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- break;
- case ZEND_AST_METHOD_REFERENCE:
- if (ast->child[0]) {
- zend_ast_export_name(str, ast->child[0], 0, indent);
- smart_str_appends(str, "::");
- }
- zend_ast_export_name(str, ast->child[1], 0, indent);
- break;
- case ZEND_AST_NAMESPACE:
- smart_str_appends(str, "namespace");
- if (ast->child[0]) {
- smart_str_appendc(str, ' ');
- zend_ast_export_name(str, ast->child[0], 0, indent);
- }
- if (ast->child[1]) {
- smart_str_appends(str, " {\n");
- zend_ast_export_stmt(str, ast->child[1], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appends(str, "}\n");
- } else {
- smart_str_appendc(str, ';');
- }
- break;
- case ZEND_AST_USE_ELEM:
- case ZEND_AST_TRAIT_ALIAS:
- zend_ast_export_name(str, ast->child[0], 0, indent);
- if (ast->attr & ZEND_ACC_PUBLIC) {
- smart_str_appends(str, " as public");
- } else if (ast->attr & ZEND_ACC_PROTECTED) {
- smart_str_appends(str, " as protected");
- } else if (ast->attr & ZEND_ACC_PRIVATE) {
- smart_str_appends(str, " as private");
- } else if (ast->child[1]) {
- smart_str_appends(str, " as");
- }
- if (ast->child[1]) {
- smart_str_appendc(str, ' ');
- zend_ast_export_name(str, ast->child[1], 0, indent);
- }
- break;
- /* 3 child nodes */
- case ZEND_AST_METHOD_CALL:
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, "->");
- zend_ast_export_var(str, ast->child[1], 0, indent);
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[2], 0, indent);
- smart_str_appendc(str, ')');
- break;
- case ZEND_AST_STATIC_CALL:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- smart_str_appends(str, "::");
- zend_ast_export_var(str, ast->child[1], 0, indent);
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[2], 0, indent);
- smart_str_appendc(str, ')');
- break;
- case ZEND_AST_CONDITIONAL:
- if (priority > 100) smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[0], 100, indent);
- if (ast->child[1]) {
- smart_str_appends(str, " ? ");
- zend_ast_export_ex(str, ast->child[1], 101, indent);
- smart_str_appends(str, " : ");
- } else {
- smart_str_appends(str, " ?: ");
- }
- zend_ast_export_ex(str, ast->child[2], 101, indent);
- if (priority > 100) smart_str_appendc(str, ')');
- break;
- case ZEND_AST_TRY:
- smart_str_appends(str, "try {\n");
- zend_ast_export_stmt(str, ast->child[0], indent + 1);
- zend_ast_export_indent(str, indent);
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- if (ast->child[2]) {
- smart_str_appends(str, "} finally {\n");
- zend_ast_export_stmt(str, ast->child[2], indent + 1);
- zend_ast_export_indent(str, indent);
- }
- smart_str_appendc(str, '}');
- break;
- case ZEND_AST_CATCH:
- smart_str_appends(str, "} catch (");
- zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
- smart_str_appends(str, " $");
- zend_ast_export_var(str, ast->child[1], 0, indent);
- smart_str_appends(str, ") {\n");
- zend_ast_export_stmt(str, ast->child[2], indent + 1);
- zend_ast_export_indent(str, indent);
- break;
- case ZEND_AST_PARAM:
- if (ast->child[0]) {
- if (ast->child[0]->attr & ZEND_TYPE_NULLABLE) {
- smart_str_appendc(str, '?');
- }
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- smart_str_appendc(str, ' ');
- }
- if (ast->attr & ZEND_PARAM_REF) {
- smart_str_appendc(str, '&');
- }
- if (ast->attr & ZEND_PARAM_VARIADIC) {
- smart_str_appends(str, "...");
- }
- smart_str_appendc(str, '$');
- zend_ast_export_name(str, ast->child[1], 0, indent);
- APPEND_DEFAULT_VALUE(2);
- /* 4 child nodes */
- case ZEND_AST_FOR:
- smart_str_appends(str, "for (");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appendc(str, ';');
- if (ast->child[1]) {
- smart_str_appendc(str, ' ');
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- }
- smart_str_appendc(str, ';');
- if (ast->child[2]) {
- smart_str_appendc(str, ' ');
- zend_ast_export_ex(str, ast->child[2], 0, indent);
- }
- smart_str_appends(str, ") {\n");
- zend_ast_export_stmt(str, ast->child[3], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- break;
- case ZEND_AST_FOREACH:
- smart_str_appends(str, "foreach (");
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appends(str, " as ");
- if (ast->child[2]) {
- zend_ast_export_ex(str, ast->child[2], 0, indent);
- smart_str_appends(str, " => ");
- }
- zend_ast_export_ex(str, ast->child[1], 0, indent);
- smart_str_appends(str, ") {\n");
- zend_ast_export_stmt(str, ast->child[3], indent + 1);
- zend_ast_export_indent(str, indent);
- smart_str_appendc(str, '}');
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
- return;
- binary_op:
- if (priority > p) smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[0], pl, indent);
- smart_str_appends(str, op);
- zend_ast_export_ex(str, ast->child[1], pr, indent);
- if (priority > p) smart_str_appendc(str, ')');
- return;
- prefix_op:
- if (priority > p) smart_str_appendc(str, '(');
- smart_str_appends(str, op);
- zend_ast_export_ex(str, ast->child[0], pl, indent);
- if (priority > p) smart_str_appendc(str, ')');
- return;
- postfix_op:
- if (priority > p) smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[0], pl, indent);
- smart_str_appends(str, op);
- if (priority > p) smart_str_appendc(str, ')');
- return;
- func_op:
- smart_str_appends(str, op);
- smart_str_appendc(str, '(');
- zend_ast_export_ex(str, ast->child[0], 0, indent);
- smart_str_appendc(str, ')');
- return;
- append_node_1:
- smart_str_appends(str, op);
- if (ast->child[0]) {
- smart_str_appendc(str, ' ');
- ast = ast->child[0];
- goto tail_call;
- }
- return;
- append_str:
- smart_str_appends(str, op);
- return;
- append_default_value:
- if (ast->child[p]) {
- smart_str_appends(str, " = ");
- ast = ast->child[p];
- goto tail_call;
- }
- return;
- }
- ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
- {
- smart_str str = {0};
- smart_str_appends(&str, prefix);
- zend_ast_export_ex(&str, ast, 0, 0);
- smart_str_appends(&str, suffix);
- smart_str_0(&str);
- return str.s;
- }
- /*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * indent-tabs-mode: t
- * End:
- * vim600: sw=4 ts=4 fdm=marker
- * vim<600: sw=4 ts=4
- */
|