From e5a1a53bd9085dc147e093b93ca3f0fb9a13ed97 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 21 Apr 2016 00:19:47 +0300 Subject: [PATCH 1/5] Implement PHP attributes --- Zend/tests/attributes_001.phpt | 84 +++ Zend/zend.h | 1 + Zend/zend_API.c | 10 +- Zend/zend_API.h | 6 +- Zend/zend_ast.c | 6 +- Zend/zend_ast.h | 19 +- Zend/zend_compile.c | 102 ++- Zend/zend_compile.h | 10 + Zend/zend_globals.h | 1 + Zend/zend_inheritance.c | 7 +- Zend/zend_language_parser.y | 120 +-- Zend/zend_language_scanner.c | 697 +++++++++--------- Zend/zend_language_scanner.l | 1 + Zend/zend_opcode.c | 16 + Zend/zend_types.h | 8 + Zend/zend_variables.h | 9 + ext/opcache/zend_file_cache.c | 64 ++ ext/opcache/zend_persist.c | 42 ++ ext/opcache/zend_persist_calc.c | 17 + ext/reflection/php_reflection.c | 96 +++ .../tests/ReflectionClass_toString_001.phpt | 8 +- ext/standard/var.c | 18 + 22 files changed, 933 insertions(+), 409 deletions(-) create mode 100644 Zend/tests/attributes_001.phpt diff --git a/Zend/tests/attributes_001.phpt b/Zend/tests/attributes_001.phpt new file mode 100644 index 0000000000000..0bac9f2f57189 --- /dev/null +++ b/Zend/tests/attributes_001.phpt @@ -0,0 +1,84 @@ +--TEST-- +Basic attributes usage +--FILE-- +> +function foo() { +} +$r = new ReflectionFunction("foo"); +var_dump($r->getAttributes()); + +// Class attributes +<> +class Bar { + <> + const C = 2; + <> + public $x = 3; + +} +$r = new ReflectionClass("Bar"); +var_dump($r->getAttributes()); +$r1 = $r->getReflectionConstant("C"); +var_dump($r1->getAttributes()); +$r2 = $r->getProperty("x"); +var_dump($r2->getAttributes()); + +// Multiple attributes with multiple values +<> +function f1() {} +$r = new ReflectionFunction("f1"); +var_dump($r->getAttributes()); + +// Attributes with AST +<1,"b"=>2])>> +function f2() {} +$r = new ReflectionFunction("f2"); +var_dump($r->getAttributes()); +?> +--EXPECT-- +array(1) { + ["TestFunction"]=> + bool(true) +} +array(1) { + ["TestClass"]=> + bool(true) +} +array(1) { + ["TestConst"]=> + bool(true) +} +array(1) { + ["TestProp"]=> + bool(true) +} +array(3) { + ["a1"]=> + bool(true) + ["a2"]=> + int(1) + ["a3"]=> + array(2) { + [0]=> + int(1) + [1]=> + int(2) + } +} +array(4) { + ["a1"]=> + bool(true) + ["a2"]=> + AST(1 + 'a') + ["a3"]=> + array(2) { + [0]=> + AST(1 + 'b') + [1]=> + AST(2 + 'c') + } + ["a4"]=> + AST(['a' => 1, 'b' => 2]) +} diff --git a/Zend/zend.h b/Zend/zend.h index e886ba20d374c..ecad67fec520f 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -179,6 +179,7 @@ struct _zend_class_entry { uint32_t line_start; uint32_t line_end; zend_string *doc_comment; + HashTable *attributes; } user; struct { const struct _zend_function_entry *builtin_functions; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 18e6e0f4f4a2e..1789721fcf934 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -3598,7 +3598,7 @@ ZEND_API const char *zend_get_module_version(const char *module_name) /* {{{ */ } /* }}} */ -ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment) /* {{{ */ +ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, HashTable *attributes) /* {{{ */ { zend_property_info *property_info, *property_info_ptr; @@ -3667,6 +3667,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z property_info->name = zend_new_interned_string(property_info->name); property_info->flags = access_type; property_info->doc_comment = doc_comment; + property_info->attributes = attributes; property_info->ce = ce; zend_hash_update_ptr(&ce->properties_info, name, property_info); @@ -3677,7 +3678,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type) /* {{{ */ { zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS); - int ret = zend_declare_property_ex(ce, key, property, access_type, NULL); + int ret = zend_declare_property_ex(ce, key, property, access_type, NULL, NULL); zend_string_release(key); return ret; } @@ -3737,7 +3738,7 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *nam } /* }}} */ -ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment) /* {{{ */ +ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment, HashTable *attributes) /* {{{ */ { zend_class_constant *c; @@ -3760,6 +3761,7 @@ ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *n ZVAL_COPY_VALUE(&c->value, value); Z_ACCESS_FLAGS(c->value) = access_type; c->doc_comment = doc_comment; + c->attributes = attributes; c->ce = ce; if (Z_CONSTANT_P(value)) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; @@ -3779,7 +3781,7 @@ ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, int ret; zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS); - ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL); + ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL, NULL); zend_string_release(key); return ret; } diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 07b48365f33b4..d5367e4a57082 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -314,7 +314,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, zend_strin ZEND_API zend_bool zend_make_callable(zval *callable, zend_string **callable_name); ZEND_API const char *zend_get_module_version(const char *module_name); ZEND_API int zend_get_module_started(const char *module_name); -ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment); +ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, zval *property, int access_type, zend_string *doc_comment, HashTable *attributes); ZEND_API int zend_declare_property(zend_class_entry *ce, const char *name, size_t name_length, zval *property, int access_type); ZEND_API int zend_declare_property_null(zend_class_entry *ce, const char *name, size_t name_length, int access_type); ZEND_API int zend_declare_property_bool(zend_class_entry *ce, const char *name, size_t name_length, zend_long value, int access_type); @@ -323,7 +323,7 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type); ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type); -ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment); +ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment, HashTable *attributes); ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value); ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length); ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value); @@ -624,6 +624,7 @@ END_EXTERN_C() #define RETVAL_EMPTY_STRING() ZVAL_EMPTY_STRING(return_value) #define RETVAL_RES(r) ZVAL_RES(return_value, r) #define RETVAL_ARR(r) ZVAL_ARR(return_value, r) +#define RETVAL_IMMUTABLE_ARR(r) ZVAL_IMMUTABLE_ARR(return_value, r) #define RETVAL_OBJ(r) ZVAL_OBJ(return_value, r) #define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor) #define RETVAL_FALSE ZVAL_FALSE(return_value) @@ -642,6 +643,7 @@ END_EXTERN_C() #define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; } #define RETURN_RES(r) { RETVAL_RES(r); return; } #define RETURN_ARR(r) { RETVAL_ARR(r); return; } +#define RETURN_IMMUTABLE_ARR(r) { RETVAL_IMMUTABLE_ARR(r); return; } #define RETURN_OBJ(r) { RETVAL_OBJ(r); return; } #define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } #define RETURN_FALSE { RETVAL_FALSE; return; } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index cfcd636269cb8..1abd801f93aa7 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -69,7 +69,7 @@ ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) { } ZEND_API zend_ast *zend_ast_create_decl( - zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, + zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, HashTable *attributes, zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3 ) { zend_ast_decl *ast; @@ -82,6 +82,7 @@ ZEND_API zend_ast *zend_ast_create_decl( ast->flags = flags; ast->lex_pos = LANG_SCNG(yy_text); ast->doc_comment = doc_comment; + ast->attributes = attributes; ast->name = name; ast->child[0] = child0; ast->child[1] = child1; @@ -468,6 +469,9 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) { if (decl->doc_comment) { zend_string_release(decl->doc_comment); } + if (decl->attributes) { + zend_array_ptr_dtor(decl->attributes); + } zend_ast_destroy_ex(decl->child[0], free); zend_ast_destroy_ex(decl->child[1], free); zend_ast_destroy_ex(decl->child[2], free); diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index ec771003c0c9d..49128bf3a4cce 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -140,12 +140,12 @@ enum _zend_ast_kind { ZEND_AST_TRY, ZEND_AST_CATCH, ZEND_AST_PARAM, - ZEND_AST_PROP_ELEM, - ZEND_AST_CONST_ELEM, /* 4 child nodes */ ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_FOREACH, + ZEND_AST_PROP_ELEM, + ZEND_AST_CONST_ELEM, }; typedef uint16_t zend_ast_kind; @@ -183,6 +183,7 @@ typedef struct _zend_ast_decl { uint32_t flags; unsigned char *lex_pos; zend_string *doc_comment; + HashTable *attributes; zend_string *name; zend_ast *child[4]; } zend_ast_decl; @@ -196,7 +197,7 @@ ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, .. ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...); ZEND_API zend_ast *zend_ast_create_decl( - zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, + zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, HashTable *attributes, zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3 ); @@ -231,6 +232,12 @@ static zend_always_inline zend_string *zend_ast_get_str(zend_ast *ast) { return Z_STR_P(zv); } +static zend_always_inline HashTable *zend_ast_get_hash(zend_ast *ast) { + zval *zv = zend_ast_get_zval(ast); + ZEND_ASSERT(Z_TYPE_P(zv) == IS_ARRAY); + return Z_ARR_P(zv); +} + static zend_always_inline uint32_t zend_ast_get_num_children(zend_ast *ast) { ZEND_ASSERT(!zend_ast_is_list(ast)); return ast->kind >> ZEND_AST_NUM_CHILDREN_SHIFT; @@ -258,6 +265,12 @@ static zend_always_inline zend_ast *zend_ast_create_zval_from_long(zend_long lva return zend_ast_create_zval(&zv); } +static zend_always_inline zend_ast *zend_ast_create_zval_from_hash(HashTable *hash) { + zval zv; + ZVAL_ARR(&zv, hash); + return zend_ast_create_zval(&zv); +} + static zend_always_inline zend_ast *zend_ast_create_binary_op(uint32_t opcode, zend_ast *op0, zend_ast *op1) { return zend_ast_create_ex(ZEND_AST_BINARY_OP, opcode, op0, op1); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 11eb04040bacf..5347666e91b1c 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1752,6 +1752,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify } else { ce->static_members_table = ce->default_static_members_table; ce->info.user.doc_comment = NULL; + ce->info.user.attributes = NULL; } ce->default_properties_count = 0; @@ -1820,6 +1821,68 @@ zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */ } /* }}} */ +void zend_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */ +{ + zval *val, tmp; + zend_string *key = zend_ast_get_str(name); + + if (!CG(attributes)) { + ALLOC_HASHTABLE(CG(attributes)); + zend_hash_init(CG(attributes), 8, NULL, ZVAL_PTR_DTOR, 0); + } + if (value) { + if (value->kind == ZEND_AST_ZVAL) { + val = zend_ast_get_zval(value); + } else { + ZVAL_NEW_AST(&tmp, zend_ast_copy(value)); + zend_ast_destroy(value); + val = &tmp; + } + } else { + ZVAL_TRUE(&tmp); + val = &tmp; + } + + if (!zend_hash_add(CG(attributes), key, val)) { + zend_error_noreturn(E_COMPILE_ERROR, "Redeclared attribute %s", ZSTR_VAL(key)); + } + zend_string_release(key); +} +/* }}} */ + +zend_ast *zend_add_attribute_value(zend_ast *list_ast, zend_ast *val_ast) /* {{{ */ +{ + zval *list, *val, arr, tmp; + + if (list_ast->kind == ZEND_AST_ZVAL) { + list = zend_ast_get_zval(list_ast); + if (Z_TYPE_P(list) != IS_ARRAY) { + array_init(&arr); + zend_hash_next_index_insert_new(Z_ARRVAL(arr), list); + ZVAL_ARR(list, Z_ARR(arr)); + } + } else { + array_init(&arr); + ZVAL_NEW_AST(&tmp, zend_ast_copy(list_ast)); + zend_ast_destroy(list_ast); + zend_hash_next_index_insert_new(Z_ARRVAL(arr), &tmp); + list_ast = zend_ast_create_zval(&arr); + list = zend_ast_get_zval(list_ast); + } + + if (val_ast->kind == ZEND_AST_ZVAL) { + val = zend_ast_get_zval(val_ast); + } else { + ZVAL_NEW_AST(&tmp, zend_ast_copy(val_ast)); + zend_ast_destroy(val_ast); + val = &tmp; + } + zend_hash_next_index_insert_new(Z_ARRVAL_P(list), val); + + return list_ast; +} +/* }}} */ + void zend_verify_namespace(void) /* {{{ */ { if (FC(has_bracketed_namespaces) && !FC(in_namespace)) { @@ -5336,7 +5399,12 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */ op_array->line_start = decl->start_lineno; op_array->line_end = decl->end_lineno; if (decl->doc_comment) { - op_array->doc_comment = zend_string_copy(decl->doc_comment); + op_array->doc_comment = decl->doc_comment; + decl->doc_comment = NULL; + } + if (decl->attributes) { + op_array->attributes = decl->attributes; + decl->attributes = NULL; } if (decl->kind == ZEND_AST_CLOSURE) { op_array->fn_flags |= ZEND_ACC_CLOSURE; @@ -5416,13 +5484,20 @@ void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ zend_ast *name_ast = prop_ast->child[0]; zend_ast *value_ast = prop_ast->child[1]; zend_ast *doc_comment_ast = prop_ast->child[2]; + zend_ast *attributes_ast = prop_ast->child[3]; zend_string *name = zend_ast_get_str(name_ast); zend_string *doc_comment = NULL; + HashTable *attributes = NULL; zval value_zv; /* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */ if (doc_comment_ast) { - doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast)); + doc_comment = zend_ast_get_str(doc_comment_ast); + prop_ast->child[2] = NULL; + } + if (attributes_ast) { + attributes = zend_ast_get_hash(attributes_ast); + prop_ast->child[3] = NULL; } if (flags & ZEND_ACC_FINAL) { @@ -5443,7 +5518,7 @@ void zend_compile_prop_decl(zend_ast *ast) /* {{{ */ } name = zend_new_interned_string_safe(name); - zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment); + zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment, attributes); } } /* }}} */ @@ -5464,10 +5539,20 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zend_ast *name_ast = const_ast->child[0]; zend_ast *value_ast = const_ast->child[1]; zend_ast *doc_comment_ast = const_ast->child[2]; + zend_ast *attributes_ast = const_ast->child[3]; zend_string *name = zend_ast_get_str(name_ast); - zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL; + zend_string *doc_comment = NULL; + HashTable *attributes = NULL; zval value_zv; + if (doc_comment_ast) { + doc_comment = zend_ast_get_str(doc_comment_ast); + const_ast->child[2] = NULL; + } + if (attributes_ast) { + attributes = zend_ast_get_hash(attributes_ast); + const_ast->child[3] = NULL; + } if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) { if (ast->attr & ZEND_ACC_STATIC) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier"); @@ -5481,7 +5566,7 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */ zend_const_expr_to_zval(&value_zv, value_ast); name = zend_new_interned_string_safe(name); - zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment); + zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment, attributes); } } /* }}} */ @@ -5716,7 +5801,12 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ ce->info.user.line_end = decl->end_lineno; if (decl->doc_comment) { - ce->info.user.doc_comment = zend_string_copy(decl->doc_comment); + ce->info.user.doc_comment = decl->doc_comment; + decl->doc_comment = NULL; + } + if (decl->attributes) { + ce->info.user.attributes = decl->attributes; + decl->attributes = NULL; } if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8fe291f4432a1..77fc7ad68bcad 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -48,6 +48,10 @@ zend_string_release(CG(doc_comment)); \ CG(doc_comment) = NULL; \ } \ + if (CG(attributes)) { \ + zend_array_ptr_dtor(CG(attributes)); \ + CG(attributes) = NULL; \ + } \ } while (0) typedef struct _zend_op_array zend_op_array; @@ -126,6 +130,7 @@ typedef struct _zend_file_context { typedef union _zend_parser_stack_elem { zend_ast *ast; zend_string *str; + HashTable *hash; zend_ulong num; } zend_parser_stack_elem; @@ -296,6 +301,7 @@ typedef struct _zend_property_info { uint32_t flags; zend_string *name; zend_string *doc_comment; + HashTable *attributes; zend_class_entry *ce; } zend_property_info; @@ -311,6 +317,7 @@ typedef struct _zend_property_info { typedef struct _zend_class_constant { zval value; /* access flags are stored in reserved: zval.u2.access_flags */ zend_string *doc_comment; + HashTable *attributes; zend_class_entry *ce; } zend_class_constant; @@ -384,6 +391,7 @@ struct _zend_op_array { uint32_t line_start; uint32_t line_end; zend_string *doc_comment; + HashTable *attributes; uint32_t early_binding; /* the linked list of delayed declarations */ int last_literal; @@ -725,6 +733,8 @@ zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right); uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag); uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag); void zend_handle_encoding_declaration(zend_ast *ast); +void zend_add_attribute(zend_ast *name, zend_ast *value); +zend_ast *zend_add_attribute_value(zend_ast *list_ast, zend_ast *val_ast); /* parser-driven code generators */ void zend_do_free(znode *op1); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index a6a89377f757b..6218fd0aeba85 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -101,6 +101,7 @@ struct _zend_compiler_globals { zend_bool increment_lineno; zend_string *doc_comment; + HashTable *attributes; uint32_t compiler_options; /* set of ZEND_COMPILE_* constants */ diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index f376150f404c3..4119470fac18d 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1505,6 +1505,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */ zval* prop_value; uint32_t flags; zend_string *doc_comment; + HashTable *attributes = NULL; /* In the following steps the properties are inserted into the property table * for that, a very strict approach is applied: @@ -1581,9 +1582,13 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */ if (Z_REFCOUNTED_P(prop_value)) Z_ADDREF_P(prop_value); doc_comment = property_info->doc_comment ? zend_string_copy(property_info->doc_comment) : NULL; + if (property_info->attributes) { + attributes = property_info->attributes; + GC_REFCOUNT(attributes)++; + } zend_declare_property_ex(ce, prop_name, prop_value, flags, - doc_comment); + doc_comment, attributes); zend_string_release(prop_name); } ZEND_HASH_FOREACH_END(); } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 53b2f3f50bea1..947ce66032aa6 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -51,6 +51,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %destructor { zend_ast_destroy($$); } %destructor { if ($$) zend_string_release($$); } +%destructor { if ($$) zend_array_ptr_dtor($$); } %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' @@ -225,16 +226,16 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); /* Token used to force a parse error from the lexer */ %token T_ERROR -%type top_statement namespace_name name statement function_declaration_statement +%type top_statement namespace_name name statement annotated_statement function_declaration_statement %type class_declaration_statement trait_declaration_statement %type interface_declaration_statement interface_extends_list %type group_use_declaration inline_use_declarations inline_use_declaration %type mixed_group_use_declaration use_declaration unprefixed_use_declaration %type unprefixed_use_declarations const_decl inner_statement -%type expr optional_expr while_statement for_statement foreach_variable +%type attribute_values expr optional_expr while_statement for_statement foreach_variable %type foreach_statement declare_statement finally_statement unset_variable variable %type extends_from parameter optional_type argument expr_without_variable global_var -%type static_var class_statement trait_adaptation trait_precedence trait_alias +%type static_var class_statement annotated_class_statement trait_adaptation trait_precedence trait_alias %type absolute_trait_method_reference trait_method_reference property echo_expr %type new_expr anonymous_class class_name class_name_reference simple_variable %type internal_functions_in_yacc @@ -261,6 +262,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type backup_doc_comment +%type backup_attributes + %% /* Rules */ start: @@ -307,12 +310,37 @@ name: | T_NS_SEPARATOR namespace_name { $$ = $2; $$->attr = ZEND_NAME_FQ; } ; -top_statement: - statement { $$ = $1; } - | function_declaration_statement { $$ = $1; } +attribute_values: + expr { $$ = $1; } + | attribute_values ',' expr { $$ = zend_add_attribute_value($1, $3); } + +attribute_list: + T_STRING { zend_add_attribute($1, NULL); } + | T_STRING '(' attribute_values ')' { zend_add_attribute($1, $3); } + | attribute_list ',' T_STRING { zend_add_attribute($3, NULL); } + | attribute_list ',' T_STRING '(' attribute_values ')' { zend_add_attribute($3, $5); } +; + +attribute: + T_SL attribute_list T_SR +; + +attributes: + attributes attribute + | attribute +; + +annotated_statement: + function_declaration_statement { $$ = $1; } | class_declaration_statement { $$ = $1; } | trait_declaration_statement { $$ = $1; } | interface_declaration_statement { $$ = $1; } +; + +top_statement: + statement { $$ = $1; } + | annotated_statement { $$ = $1; } + | attributes annotated_statement { $$ = $2; } | T_HALT_COMPILER '(' ')' ';' { $$ = zend_ast_create(ZEND_AST_HALT_COMPILER, zend_ast_create_zval_from_long(zend_get_scanned_file_offset())); @@ -404,11 +432,9 @@ inner_statement_list: inner_statement: - statement { $$ = $1; } - | function_declaration_statement { $$ = $1; } - | class_declaration_statement { $$ = $1; } - | trait_declaration_statement { $$ = $1; } - | interface_declaration_statement { $$ = $1; } + statement { $$ = $1; } + | annotated_statement { $$ = $1; } + | attributes annotated_statement { $$ = $2; } | T_HALT_COMPILER '(' ')' ';' { $$ = NULL; zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); } @@ -475,10 +501,10 @@ unset_variable: ; function_declaration_statement: - function returns_ref T_STRING backup_doc_comment '(' parameter_list ')' return_type + function returns_ref T_STRING backup_doc_comment backup_attributes '(' parameter_list ')' return_type '{' inner_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2, $1, $4, - zend_ast_get_str($3), $6, NULL, $10, $8); } + { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2, $1, $4, $5, + zend_ast_get_str($3), $7, NULL, $11, $9); } ; is_reference: @@ -493,11 +519,11 @@ is_variadic: class_declaration_statement: class_modifiers T_CLASS { $$ = CG(zend_lineno); } - T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $3, $7, zend_ast_get_str($4), $5, $6, $9, NULL); } + T_STRING extends_from implements_list backup_doc_comment backup_attributes '{' class_statement_list '}' + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $3, $7, $8, zend_ast_get_str($4), $5, $6, $10, NULL); } | T_CLASS { $$ = CG(zend_lineno); } - T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $2, $6, zend_ast_get_str($3), $4, $5, $8, NULL); } + T_STRING extends_from implements_list backup_doc_comment backup_attributes '{' class_statement_list '}' + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $2, $6, $7, zend_ast_get_str($3), $4, $5, $9, NULL); } ; class_modifiers: @@ -512,14 +538,14 @@ class_modifier: trait_declaration_statement: T_TRAIT { $$ = CG(zend_lineno); } - T_STRING backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL); } + T_STRING backup_doc_comment backup_attributes '{' class_statement_list '}' + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $2, $4, $5, zend_ast_get_str($3), NULL, NULL, $7, NULL); } ; interface_declaration_statement: T_INTERFACE { $$ = CG(zend_lineno); } - T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL); } + T_STRING interface_extends_list backup_doc_comment backup_attributes '{' class_statement_list '}' + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $2, $5, $6, zend_ast_get_str($3), NULL, $4, $8, NULL); } ; extends_from: @@ -699,18 +725,22 @@ class_statement_list: { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); } ; - -class_statement: +annotated_class_statement: variable_modifiers property_list ';' { $$ = $2; $$->attr = $1; } | method_modifiers T_CONST class_const_list ';' { $$ = $3; $$->attr = $1; } + | method_modifiers function returns_ref identifier backup_doc_comment backup_attributes '(' parameter_list ')' + return_type method_body + { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $5, $6, + zend_ast_get_str($4), $8, NULL, $11, $10); } +; + +class_statement: + annotated_class_statement { $$ = $1; } + | attributes annotated_class_statement { $$ = $2; } | T_USE name_list trait_adaptations { $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); } - | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' - return_type method_body - { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $5, - zend_ast_get_str($4), $7, NULL, $10, $9); } ; name_list: @@ -800,10 +830,10 @@ property_list: ; property: - T_VARIABLE backup_doc_comment - { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, NULL, ($2 ? zend_ast_create_zval_from_str($2) : NULL)); } - | T_VARIABLE '=' expr backup_doc_comment - { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } + T_VARIABLE backup_doc_comment backup_attributes + { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, NULL, ($2 ? zend_ast_create_zval_from_str($2) : NULL), ($3 ? zend_ast_create_zval_from_hash($3) : NULL)); } + | T_VARIABLE '=' expr backup_doc_comment backup_attributes + { $$ = zend_ast_create(ZEND_AST_PROP_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), ($5 ? zend_ast_create_zval_from_hash($5) : NULL)); } ; class_const_list: @@ -812,11 +842,11 @@ class_const_list: ; class_const_decl: - identifier '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } + identifier '=' expr backup_doc_comment backup_attributes { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), ($5 ? zend_ast_create_zval_from_hash($5) : NULL)); } ; const_decl: - T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); } + T_STRING '=' expr backup_doc_comment backup_attributes { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL), ($5 ? zend_ast_create_zval_from_hash($5) : NULL)); } ; echo_expr_list: @@ -839,10 +869,10 @@ non_empty_for_exprs: anonymous_class: T_CLASS { $$ = CG(zend_lineno); } ctor_arguments - extends_from implements_list backup_doc_comment '{' class_statement_list '}' { + extends_from implements_list backup_doc_comment backup_attributes '{' class_statement_list '}' { zend_ast *decl = zend_ast_create_decl( - ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS, $2, $6, NULL, - $4, $5, $8, NULL); + ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS, $2, $6, $7, NULL, + $4, $5, $9, NULL); $$ = zend_ast_create(ZEND_AST_NEW, decl, $3); } ; @@ -961,16 +991,16 @@ expr_without_variable: | T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); } | T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); } | T_YIELD_FROM expr { $$ = zend_ast_create(ZEND_AST_YIELD_FROM, $2); } - | function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type + | function returns_ref backup_doc_comment backup_attributes '(' parameter_list ')' lexical_vars return_type '{' inner_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2, $1, $3, + { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2, $1, $3, $4, zend_string_init("{closure}", sizeof("{closure}") - 1, 0), - $5, $7, $10, $8); } - | T_STATIC function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars + $6, $8, $11, $9); } + | T_STATIC function returns_ref backup_doc_comment backup_attributes '(' parameter_list ')' lexical_vars return_type '{' inner_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | ZEND_ACC_STATIC, $2, $4, + { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | ZEND_ACC_STATIC, $2, $4, $5, zend_string_init("{closure}", sizeof("{closure}") - 1, 0), - $6, $8, $11, $9); } + $7, $9, $12, $10); } ; function: @@ -981,6 +1011,10 @@ backup_doc_comment: /* empty */ { $$ = CG(doc_comment); CG(doc_comment) = NULL; } ; +backup_attributes: + /* empty */ { $$ = CG(attributes); CG(attributes) = NULL; } +; + returns_ref: /* empty */ { $$ = 0; } | '&' { $$ = ZEND_ACC_RETURN_REFERENCE; } diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c index 7809f95f11c8b..cb2cf9c71df45 100644 --- a/Zend/zend_language_scanner.c +++ b/Zend/zend_language_scanner.c @@ -180,6 +180,7 @@ void startup_scanner(void) { CG(parse_error) = 0; CG(doc_comment) = NULL; + CG(attributes) = NULL; zend_stack_init(&SCNG(state_stack), sizeof(int)); zend_ptr_stack_init(&SCNG(heredoc_label_stack)); } @@ -1093,7 +1094,7 @@ int start_line = CG(zend_lineno); SCNG(yy_text) = YYCURSOR; -#line 1097 "Zend/zend_language_scanner.c" +#line 1098 "Zend/zend_language_scanner.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1147,7 +1148,7 @@ int start_line = CG(zend_lineno); yy3: YYDEBUG(3, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1789 "Zend/zend_language_scanner.l" +#line 1790 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { RETURN_TOKEN(END); @@ -1192,7 +1193,7 @@ int start_line = CG(zend_lineno); HANDLE_NEWLINES(yytext, yyleng); RETURN_TOKEN(T_INLINE_HTML); } -#line 1196 "Zend/zend_language_scanner.c" +#line 1197 "Zend/zend_language_scanner.c" yy4: YYDEBUG(4, *YYCURSOR); yych = *++YYCURSOR; @@ -1210,7 +1211,7 @@ int start_line = CG(zend_lineno); yy6: YYDEBUG(6, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1780 "Zend/zend_language_scanner.l" +#line 1781 "Zend/zend_language_scanner.l" { if (CG(short_tags)) { BEGIN(ST_IN_SCRIPTING); @@ -1219,18 +1220,18 @@ int start_line = CG(zend_lineno); goto inline_char_handler; } } -#line 1223 "Zend/zend_language_scanner.c" +#line 1224 "Zend/zend_language_scanner.c" yy7: YYDEBUG(7, *YYCURSOR); ++YYCURSOR; YYDEBUG(8, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1767 "Zend/zend_language_scanner.l" +#line 1768 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); RETURN_TOKEN(T_OPEN_TAG_WITH_ECHO); } -#line 1234 "Zend/zend_language_scanner.c" +#line 1235 "Zend/zend_language_scanner.c" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1261,13 +1262,13 @@ int start_line = CG(zend_lineno); yy14: YYDEBUG(14, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1773 "Zend/zend_language_scanner.l" +#line 1774 "Zend/zend_language_scanner.l" { HANDLE_NEWLINE(yytext[yyleng-1]); BEGIN(ST_IN_SCRIPTING); RETURN_TOKEN(T_OPEN_TAG); } -#line 1271 "Zend/zend_language_scanner.c" +#line 1272 "Zend/zend_language_scanner.c" yy15: YYDEBUG(15, *YYCURSOR); ++YYCURSOR; @@ -1337,7 +1338,7 @@ int start_line = CG(zend_lineno); yy19: YYDEBUG(19, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2199 "Zend/zend_language_scanner.l" +#line 2200 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { RETURN_TOKEN(END); @@ -1378,7 +1379,7 @@ int start_line = CG(zend_lineno); zend_scan_escape_string(zendlval, yytext, yyleng, '`'); RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE); } -#line 1382 "Zend/zend_language_scanner.c" +#line 1383 "Zend/zend_language_scanner.c" yy20: YYDEBUG(20, *YYCURSOR); yych = *++YYCURSOR; @@ -1389,12 +1390,12 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(22, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2143 "Zend/zend_language_scanner.l" +#line 2144 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); RETURN_TOKEN('`'); } -#line 1398 "Zend/zend_language_scanner.c" +#line 1399 "Zend/zend_language_scanner.c" yy23: YYDEBUG(23, *YYCURSOR); yych = *++YYCURSOR; @@ -1404,14 +1405,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(25, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2130 "Zend/zend_language_scanner.l" +#line 2131 "Zend/zend_language_scanner.l" { Z_LVAL_P(zendlval) = (zend_long) '{'; yy_push_state(ST_IN_SCRIPTING); yyless(1); RETURN_TOKEN(T_CURLY_OPEN); } -#line 1415 "Zend/zend_language_scanner.c" +#line 1416 "Zend/zend_language_scanner.c" yy26: YYDEBUG(26, *YYCURSOR); yyaccept = 0; @@ -1427,23 +1428,23 @@ int start_line = CG(zend_lineno); yy28: YYDEBUG(28, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1854 "Zend/zend_language_scanner.l" +#line 1855 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1436 "Zend/zend_language_scanner.c" +#line 1437 "Zend/zend_language_scanner.c" yy29: YYDEBUG(29, *YYCURSOR); ++YYCURSOR; YYDEBUG(30, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1572 "Zend/zend_language_scanner.l" +#line 1573 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME); RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES); } -#line 1447 "Zend/zend_language_scanner.c" +#line 1448 "Zend/zend_language_scanner.c" yy31: YYDEBUG(31, *YYCURSOR); yych = *++YYCURSOR; @@ -1457,14 +1458,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(34, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1847 "Zend/zend_language_scanner.l" +#line 1848 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1468 "Zend/zend_language_scanner.c" +#line 1469 "Zend/zend_language_scanner.c" yy35: YYDEBUG(35, *YYCURSOR); yych = *++YYCURSOR; @@ -1482,14 +1483,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(37, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1838 "Zend/zend_language_scanner.l" +#line 1839 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1493 "Zend/zend_language_scanner.c" +#line 1494 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_DOUBLE_QUOTES: @@ -1557,7 +1558,7 @@ int start_line = CG(zend_lineno); yy41: YYDEBUG(41, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2149 "Zend/zend_language_scanner.l" +#line 2150 "Zend/zend_language_scanner.l" { if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) { YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1; @@ -1606,7 +1607,7 @@ int start_line = CG(zend_lineno); zend_scan_escape_string(zendlval, yytext, yyleng, '"'); RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE); } -#line 1610 "Zend/zend_language_scanner.c" +#line 1611 "Zend/zend_language_scanner.c" yy42: YYDEBUG(42, *YYCURSOR); yych = *++YYCURSOR; @@ -1617,12 +1618,12 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(44, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2138 "Zend/zend_language_scanner.l" +#line 2139 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); RETURN_TOKEN('"'); } -#line 1626 "Zend/zend_language_scanner.c" +#line 1627 "Zend/zend_language_scanner.c" yy45: YYDEBUG(45, *YYCURSOR); yych = *++YYCURSOR; @@ -1632,14 +1633,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(47, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2130 "Zend/zend_language_scanner.l" +#line 2131 "Zend/zend_language_scanner.l" { Z_LVAL_P(zendlval) = (zend_long) '{'; yy_push_state(ST_IN_SCRIPTING); yyless(1); RETURN_TOKEN(T_CURLY_OPEN); } -#line 1643 "Zend/zend_language_scanner.c" +#line 1644 "Zend/zend_language_scanner.c" yy48: YYDEBUG(48, *YYCURSOR); yyaccept = 0; @@ -1655,23 +1656,23 @@ int start_line = CG(zend_lineno); yy50: YYDEBUG(50, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1854 "Zend/zend_language_scanner.l" +#line 1855 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1664 "Zend/zend_language_scanner.c" +#line 1665 "Zend/zend_language_scanner.c" yy51: YYDEBUG(51, *YYCURSOR); ++YYCURSOR; YYDEBUG(52, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1572 "Zend/zend_language_scanner.l" +#line 1573 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME); RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES); } -#line 1675 "Zend/zend_language_scanner.c" +#line 1676 "Zend/zend_language_scanner.c" yy53: YYDEBUG(53, *YYCURSOR); yych = *++YYCURSOR; @@ -1685,14 +1686,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(56, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1847 "Zend/zend_language_scanner.l" +#line 1848 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1696 "Zend/zend_language_scanner.c" +#line 1697 "Zend/zend_language_scanner.c" yy57: YYDEBUG(57, *YYCURSOR); yych = *++YYCURSOR; @@ -1710,14 +1711,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(59, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1838 "Zend/zend_language_scanner.l" +#line 1839 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1721 "Zend/zend_language_scanner.c" +#line 1722 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_END_HEREDOC: @@ -1728,7 +1729,7 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(63, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2116 "Zend/zend_language_scanner.l" +#line 2117 "Zend/zend_language_scanner.l" { zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack)); @@ -1741,7 +1742,7 @@ int start_line = CG(zend_lineno); BEGIN(ST_IN_SCRIPTING); RETURN_TOKEN(T_END_HEREDOC); } -#line 1745 "Zend/zend_language_scanner.c" +#line 1746 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_HEREDOC: { @@ -1803,7 +1804,7 @@ int start_line = CG(zend_lineno); yy67: YYDEBUG(67, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2241 "Zend/zend_language_scanner.l" +#line 2242 "Zend/zend_language_scanner.l" { int newline = 0; @@ -1876,7 +1877,7 @@ int start_line = CG(zend_lineno); zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0); RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE); } -#line 1880 "Zend/zend_language_scanner.c" +#line 1881 "Zend/zend_language_scanner.c" yy68: YYDEBUG(68, *YYCURSOR); yych = *++YYCURSOR; @@ -1891,14 +1892,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(71, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2130 "Zend/zend_language_scanner.l" +#line 2131 "Zend/zend_language_scanner.l" { Z_LVAL_P(zendlval) = (zend_long) '{'; yy_push_state(ST_IN_SCRIPTING); yyless(1); RETURN_TOKEN(T_CURLY_OPEN); } -#line 1902 "Zend/zend_language_scanner.c" +#line 1903 "Zend/zend_language_scanner.c" yy72: YYDEBUG(72, *YYCURSOR); yyaccept = 0; @@ -1914,23 +1915,23 @@ int start_line = CG(zend_lineno); yy74: YYDEBUG(74, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1854 "Zend/zend_language_scanner.l" +#line 1855 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1923 "Zend/zend_language_scanner.c" +#line 1924 "Zend/zend_language_scanner.c" yy75: YYDEBUG(75, *YYCURSOR); ++YYCURSOR; YYDEBUG(76, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1572 "Zend/zend_language_scanner.l" +#line 1573 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME); RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES); } -#line 1934 "Zend/zend_language_scanner.c" +#line 1935 "Zend/zend_language_scanner.c" yy77: YYDEBUG(77, *YYCURSOR); yych = *++YYCURSOR; @@ -1944,14 +1945,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(80, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1847 "Zend/zend_language_scanner.l" +#line 1848 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1955 "Zend/zend_language_scanner.c" +#line 1956 "Zend/zend_language_scanner.c" yy81: YYDEBUG(81, *YYCURSOR); yych = *++YYCURSOR; @@ -1969,14 +1970,14 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(83, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1838 "Zend/zend_language_scanner.l" +#line 1839 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY); zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 1980 "Zend/zend_language_scanner.c" +#line 1981 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_IN_SCRIPTING: @@ -2159,12 +2160,12 @@ int start_line = CG(zend_lineno); yy87: YYDEBUG(87, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1877 "Zend/zend_language_scanner.l" +#line 1878 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); RETURN_TOKEN(T_STRING); } -#line 2168 "Zend/zend_language_scanner.c" +#line 2169 "Zend/zend_language_scanner.c" yy88: YYDEBUG(88, *YYCURSOR); yych = *++YYCURSOR; @@ -2396,11 +2397,11 @@ int start_line = CG(zend_lineno); yy102: YYDEBUG(102, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1561 "Zend/zend_language_scanner.l" +#line 1562 "Zend/zend_language_scanner.l" { RETURN_TOKEN(yytext[0]); } -#line 2404 "Zend/zend_language_scanner.c" +#line 2405 "Zend/zend_language_scanner.c" yy103: YYDEBUG(103, *YYCURSOR); ++YYCURSOR; @@ -2409,12 +2410,12 @@ int start_line = CG(zend_lineno); yy104: YYDEBUG(104, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1276 "Zend/zend_language_scanner.l" +#line 1277 "Zend/zend_language_scanner.l" { HANDLE_NEWLINES(yytext, yyleng); RETURN_TOKEN(T_WHITESPACE); } -#line 2418 "Zend/zend_language_scanner.c" +#line 2419 "Zend/zend_language_scanner.c" yy105: YYDEBUG(105, *YYCURSOR); yych = *++YYCURSOR; @@ -2425,11 +2426,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(107, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1301 "Zend/zend_language_scanner.l" +#line 1302 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_NS_SEPARATOR); } -#line 2433 "Zend/zend_language_scanner.c" +#line 2434 "Zend/zend_language_scanner.c" yy108: YYDEBUG(108, *YYCURSOR); yyaccept = 1; @@ -2658,18 +2659,18 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(132, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1566 "Zend/zend_language_scanner.l" +#line 1567 "Zend/zend_language_scanner.l" { yy_push_state(ST_IN_SCRIPTING); RETURN_TOKEN('{'); } -#line 2667 "Zend/zend_language_scanner.c" +#line 2668 "Zend/zend_language_scanner.c" yy133: YYDEBUG(133, *YYCURSOR); ++YYCURSOR; YYDEBUG(134, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1578 "Zend/zend_language_scanner.l" +#line 1579 "Zend/zend_language_scanner.l" { RESET_DOC_COMMENT(); if (!zend_stack_is_empty(&SCNG(state_stack))) { @@ -2677,7 +2678,7 @@ int start_line = CG(zend_lineno); } RETURN_TOKEN('}'); } -#line 2681 "Zend/zend_language_scanner.c" +#line 2682 "Zend/zend_language_scanner.c" yy135: YYDEBUG(135, *YYCURSOR); yyaccept = 2; @@ -2705,7 +2706,7 @@ int start_line = CG(zend_lineno); yy136: YYDEBUG(136, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1631 "Zend/zend_language_scanner.l" +#line 1632 "Zend/zend_language_scanner.l" { char *end; if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ @@ -2750,7 +2751,7 @@ int start_line = CG(zend_lineno); ZEND_ASSERT(!errno); RETURN_TOKEN(T_LNUMBER); } -#line 2754 "Zend/zend_language_scanner.c" +#line 2755 "Zend/zend_language_scanner.c" yy137: YYDEBUG(137, *YYCURSOR); yyaccept = 2; @@ -2778,7 +2779,7 @@ int start_line = CG(zend_lineno); yy140: YYDEBUG(140, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1883 "Zend/zend_language_scanner.l" +#line 1884 "Zend/zend_language_scanner.l" { while (YYCURSOR < YYLIMIT) { switch (*YYCURSOR++) { @@ -2807,14 +2808,14 @@ int start_line = CG(zend_lineno); RETURN_TOKEN(T_COMMENT); } -#line 2811 "Zend/zend_language_scanner.c" +#line 2812 "Zend/zend_language_scanner.c" yy141: YYDEBUG(141, *YYCURSOR); ++YYCURSOR; yy142: YYDEBUG(142, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1951 "Zend/zend_language_scanner.l" +#line 1952 "Zend/zend_language_scanner.l" { register char *s, *t; char *end; @@ -2882,14 +2883,14 @@ int start_line = CG(zend_lineno); } RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING); } -#line 2886 "Zend/zend_language_scanner.c" +#line 2887 "Zend/zend_language_scanner.c" yy143: YYDEBUG(143, *YYCURSOR); ++YYCURSOR; yy144: YYDEBUG(144, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2020 "Zend/zend_language_scanner.l" +#line 2021 "Zend/zend_language_scanner.l" { int bprefix = (yytext[0] != '"') ? 1 : 0; @@ -2930,24 +2931,24 @@ int start_line = CG(zend_lineno); BEGIN(ST_DOUBLE_QUOTES); RETURN_TOKEN('"'); } -#line 2934 "Zend/zend_language_scanner.c" +#line 2935 "Zend/zend_language_scanner.c" yy145: YYDEBUG(145, *YYCURSOR); ++YYCURSOR; YYDEBUG(146, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2110 "Zend/zend_language_scanner.l" +#line 2111 "Zend/zend_language_scanner.l" { BEGIN(ST_BACKQUOTE); RETURN_TOKEN('`'); } -#line 2945 "Zend/zend_language_scanner.c" +#line 2946 "Zend/zend_language_scanner.c" yy147: YYDEBUG(147, *YYCURSOR); ++YYCURSOR; YYDEBUG(148, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2372 "Zend/zend_language_scanner.l" +#line 2373 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { RETURN_TOKEN(END); @@ -2956,7 +2957,7 @@ int start_line = CG(zend_lineno); zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 2960 "Zend/zend_language_scanner.c" +#line 2961 "Zend/zend_language_scanner.c" yy149: YYDEBUG(149, *YYCURSOR); ++YYCURSOR; @@ -2983,7 +2984,7 @@ int start_line = CG(zend_lineno); yy153: YYDEBUG(153, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1725 "Zend/zend_language_scanner.l" +#line 1726 "Zend/zend_language_scanner.l" { const char *end; @@ -2992,7 +2993,7 @@ int start_line = CG(zend_lineno); ZEND_ASSERT(end == yytext + yyleng); RETURN_TOKEN(T_DNUMBER); } -#line 2996 "Zend/zend_language_scanner.c" +#line 2997 "Zend/zend_language_scanner.c" yy154: YYDEBUG(154, *YYCURSOR); yyaccept = 2; @@ -3088,7 +3089,7 @@ int start_line = CG(zend_lineno); } YYDEBUG(165, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1603 "Zend/zend_language_scanner.l" +#line 1604 "Zend/zend_language_scanner.l" { char *bin = yytext + 2; /* Skip "0b" */ int len = yyleng - 2; @@ -3116,7 +3117,7 @@ int start_line = CG(zend_lineno); RETURN_TOKEN(T_DNUMBER); } } -#line 3120 "Zend/zend_language_scanner.c" +#line 3121 "Zend/zend_language_scanner.c" yy166: YYDEBUG(166, *YYCURSOR); ++YYCURSOR; @@ -3128,7 +3129,7 @@ int start_line = CG(zend_lineno); } YYDEBUG(168, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1676 "Zend/zend_language_scanner.l" +#line 1677 "Zend/zend_language_scanner.l" { char *hex = yytext + 2; /* Skip "0x" */ int len = yyleng - 2; @@ -3156,7 +3157,7 @@ int start_line = CG(zend_lineno); RETURN_TOKEN(T_DNUMBER); } } -#line 3160 "Zend/zend_language_scanner.c" +#line 3161 "Zend/zend_language_scanner.c" yy169: YYDEBUG(169, *YYCURSOR); ++YYCURSOR; @@ -3181,12 +3182,12 @@ int start_line = CG(zend_lineno); yy171: YYDEBUG(171, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1854 "Zend/zend_language_scanner.l" +#line 1855 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 3190 "Zend/zend_language_scanner.c" +#line 3191 "Zend/zend_language_scanner.c" yy172: YYDEBUG(172, *YYCURSOR); yych = *++YYCURSOR; @@ -3200,11 +3201,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(174, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1549 "Zend/zend_language_scanner.l" +#line 1550 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_LOGICAL_XOR); } -#line 3208 "Zend/zend_language_scanner.c" +#line 3209 "Zend/zend_language_scanner.c" yy175: YYDEBUG(175, *YYCURSOR); ++YYCURSOR; @@ -3213,71 +3214,71 @@ int start_line = CG(zend_lineno); } YYDEBUG(176, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1541 "Zend/zend_language_scanner.l" +#line 1542 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_LOGICAL_OR); } -#line 3221 "Zend/zend_language_scanner.c" +#line 3222 "Zend/zend_language_scanner.c" yy177: YYDEBUG(177, *YYCURSOR); ++YYCURSOR; YYDEBUG(178, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1529 "Zend/zend_language_scanner.l" +#line 1530 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_XOR_EQUAL); } -#line 3231 "Zend/zend_language_scanner.c" +#line 3232 "Zend/zend_language_scanner.c" yy179: YYDEBUG(179, *YYCURSOR); ++YYCURSOR; YYDEBUG(180, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1533 "Zend/zend_language_scanner.l" +#line 1534 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_BOOLEAN_OR); } -#line 3241 "Zend/zend_language_scanner.c" +#line 3242 "Zend/zend_language_scanner.c" yy181: YYDEBUG(181, *YYCURSOR); ++YYCURSOR; YYDEBUG(182, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1525 "Zend/zend_language_scanner.l" +#line 1526 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_OR_EQUAL); } -#line 3251 "Zend/zend_language_scanner.c" +#line 3252 "Zend/zend_language_scanner.c" yy183: YYDEBUG(183, *YYCURSOR); ++YYCURSOR; YYDEBUG(184, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1537 "Zend/zend_language_scanner.l" +#line 1538 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_BOOLEAN_AND); } -#line 3261 "Zend/zend_language_scanner.c" +#line 3262 "Zend/zend_language_scanner.c" yy185: YYDEBUG(185, *YYCURSOR); ++YYCURSOR; YYDEBUG(186, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1521 "Zend/zend_language_scanner.l" +#line 1522 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_AND_EQUAL); } -#line 3271 "Zend/zend_language_scanner.c" +#line 3272 "Zend/zend_language_scanner.c" yy187: YYDEBUG(187, *YYCURSOR); ++YYCURSOR; YYDEBUG(188, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1509 "Zend/zend_language_scanner.l" +#line 1510 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_MOD_EQUAL); } -#line 3281 "Zend/zend_language_scanner.c" +#line 3282 "Zend/zend_language_scanner.c" yy189: YYDEBUG(189, *YYCURSOR); yyaccept = 4; @@ -3286,7 +3287,7 @@ int start_line = CG(zend_lineno); yy190: YYDEBUG(190, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1912 "Zend/zend_language_scanner.l" +#line 1913 "Zend/zend_language_scanner.l" { int doc_com; @@ -3319,7 +3320,7 @@ int start_line = CG(zend_lineno); RETURN_TOKEN(T_COMMENT); } -#line 3323 "Zend/zend_language_scanner.c" +#line 3324 "Zend/zend_language_scanner.c" yy191: YYDEBUG(191, *YYCURSOR); yych = *++YYCURSOR; @@ -3329,11 +3330,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(193, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1501 "Zend/zend_language_scanner.l" +#line 1502 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DIV_EQUAL); } -#line 3337 "Zend/zend_language_scanner.c" +#line 3338 "Zend/zend_language_scanner.c" yy194: YYDEBUG(194, *YYCURSOR); yych = *++YYCURSOR; @@ -3357,62 +3358,62 @@ int start_line = CG(zend_lineno); if ((yych = *YYCURSOR) == '=') goto yy201; YYDEBUG(198, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1493 "Zend/zend_language_scanner.l" +#line 1494 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_POW); } -#line 3365 "Zend/zend_language_scanner.c" +#line 3366 "Zend/zend_language_scanner.c" yy199: YYDEBUG(199, *YYCURSOR); ++YYCURSOR; YYDEBUG(200, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1489 "Zend/zend_language_scanner.l" +#line 1490 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_MUL_EQUAL); } -#line 3375 "Zend/zend_language_scanner.c" +#line 3376 "Zend/zend_language_scanner.c" yy201: YYDEBUG(201, *YYCURSOR); ++YYCURSOR; YYDEBUG(202, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1497 "Zend/zend_language_scanner.l" +#line 1498 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_POW_EQUAL); } -#line 3385 "Zend/zend_language_scanner.c" +#line 3386 "Zend/zend_language_scanner.c" yy203: YYDEBUG(203, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '=') goto yy207; YYDEBUG(204, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1557 "Zend/zend_language_scanner.l" +#line 1558 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_SR); } -#line 3396 "Zend/zend_language_scanner.c" +#line 3397 "Zend/zend_language_scanner.c" yy205: YYDEBUG(205, *YYCURSOR); ++YYCURSOR; YYDEBUG(206, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1477 "Zend/zend_language_scanner.l" +#line 1478 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IS_GREATER_OR_EQUAL); } -#line 3406 "Zend/zend_language_scanner.c" +#line 3407 "Zend/zend_language_scanner.c" yy207: YYDEBUG(207, *YYCURSOR); ++YYCURSOR; YYDEBUG(208, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1517 "Zend/zend_language_scanner.l" +#line 1518 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_SR_EQUAL); } -#line 3416 "Zend/zend_language_scanner.c" +#line 3417 "Zend/zend_language_scanner.c" yy209: YYDEBUG(209, *YYCURSOR); yyaccept = 5; @@ -3423,53 +3424,53 @@ int start_line = CG(zend_lineno); yy210: YYDEBUG(210, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1553 "Zend/zend_language_scanner.l" +#line 1554 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_SL); } -#line 3431 "Zend/zend_language_scanner.c" +#line 3432 "Zend/zend_language_scanner.c" yy211: YYDEBUG(211, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '>') goto yy215; YYDEBUG(212, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1473 "Zend/zend_language_scanner.l" +#line 1474 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IS_SMALLER_OR_EQUAL); } -#line 3442 "Zend/zend_language_scanner.c" +#line 3443 "Zend/zend_language_scanner.c" yy213: YYDEBUG(213, *YYCURSOR); ++YYCURSOR; yy214: YYDEBUG(214, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1465 "Zend/zend_language_scanner.l" +#line 1466 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IS_NOT_EQUAL); } -#line 3453 "Zend/zend_language_scanner.c" +#line 3454 "Zend/zend_language_scanner.c" yy215: YYDEBUG(215, *YYCURSOR); ++YYCURSOR; YYDEBUG(216, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1469 "Zend/zend_language_scanner.l" +#line 1470 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_SPACESHIP); } -#line 3463 "Zend/zend_language_scanner.c" +#line 3464 "Zend/zend_language_scanner.c" yy217: YYDEBUG(217, *YYCURSOR); ++YYCURSOR; YYDEBUG(218, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1513 "Zend/zend_language_scanner.l" +#line 1514 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_SL_EQUAL); } -#line 3473 "Zend/zend_language_scanner.c" +#line 3474 "Zend/zend_language_scanner.c" yy219: YYDEBUG(219, *YYCURSOR); ++YYCURSOR; @@ -3574,7 +3575,7 @@ int start_line = CG(zend_lineno); yy229: YYDEBUG(229, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2062 "Zend/zend_language_scanner.l" +#line 2063 "Zend/zend_language_scanner.l" { char *s; int bprefix = (yytext[0] != '<') ? 1 : 0; @@ -3621,7 +3622,7 @@ int start_line = CG(zend_lineno); RETURN_TOKEN(T_START_HEREDOC); } -#line 3625 "Zend/zend_language_scanner.c" +#line 3626 "Zend/zend_language_scanner.c" yy230: YYDEBUG(230, *YYCURSOR); yych = *++YYCURSOR; @@ -3661,31 +3662,31 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(235, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1457 "Zend/zend_language_scanner.l" +#line 1458 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IS_NOT_IDENTICAL); } -#line 3669 "Zend/zend_language_scanner.c" +#line 3670 "Zend/zend_language_scanner.c" yy236: YYDEBUG(236, *YYCURSOR); ++YYCURSOR; YYDEBUG(237, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1481 "Zend/zend_language_scanner.l" +#line 1482 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_PLUS_EQUAL); } -#line 3679 "Zend/zend_language_scanner.c" +#line 3680 "Zend/zend_language_scanner.c" yy238: YYDEBUG(238, *YYCURSOR); ++YYCURSOR; YYDEBUG(239, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1445 "Zend/zend_language_scanner.l" +#line 1446 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INC); } -#line 3689 "Zend/zend_language_scanner.c" +#line 3690 "Zend/zend_language_scanner.c" yy240: YYDEBUG(240, *YYCURSOR); yych = *++YYCURSOR; @@ -3704,42 +3705,42 @@ int start_line = CG(zend_lineno); } YYDEBUG(243, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1433 "Zend/zend_language_scanner.l" +#line 1434 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_LIST); } -#line 3712 "Zend/zend_language_scanner.c" +#line 3713 "Zend/zend_language_scanner.c" yy244: YYDEBUG(244, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '=') goto yy248; YYDEBUG(245, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1461 "Zend/zend_language_scanner.l" +#line 1462 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IS_EQUAL); } -#line 3723 "Zend/zend_language_scanner.c" +#line 3724 "Zend/zend_language_scanner.c" yy246: YYDEBUG(246, *YYCURSOR); ++YYCURSOR; YYDEBUG(247, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1429 "Zend/zend_language_scanner.l" +#line 1430 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DOUBLE_ARROW); } -#line 3733 "Zend/zend_language_scanner.c" +#line 3734 "Zend/zend_language_scanner.c" yy248: YYDEBUG(248, *YYCURSOR); ++YYCURSOR; YYDEBUG(249, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1453 "Zend/zend_language_scanner.l" +#line 1454 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IS_IDENTICAL); } -#line 3743 "Zend/zend_language_scanner.c" +#line 3744 "Zend/zend_language_scanner.c" yy250: YYDEBUG(250, *YYCURSOR); yych = *++YYCURSOR; @@ -3869,11 +3870,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(269, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1762 "Zend/zend_language_scanner.l" +#line 1763 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_NS_C); } -#line 3877 "Zend/zend_language_scanner.c" +#line 3878 "Zend/zend_language_scanner.c" yy270: YYDEBUG(270, *YYCURSOR); yych = *++YYCURSOR; @@ -3893,11 +3894,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(274, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1758 "Zend/zend_language_scanner.l" +#line 1759 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DIR); } -#line 3901 "Zend/zend_language_scanner.c" +#line 3902 "Zend/zend_language_scanner.c" yy275: YYDEBUG(275, *YYCURSOR); yych = *++YYCURSOR; @@ -3922,11 +3923,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(280, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1750 "Zend/zend_language_scanner.l" +#line 1751 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_LINE); } -#line 3930 "Zend/zend_language_scanner.c" +#line 3931 "Zend/zend_language_scanner.c" yy281: YYDEBUG(281, *YYCURSOR); yych = *++YYCURSOR; @@ -3961,11 +3962,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(288, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1746 "Zend/zend_language_scanner.l" +#line 1747 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_METHOD_C); } -#line 3969 "Zend/zend_language_scanner.c" +#line 3970 "Zend/zend_language_scanner.c" yy289: YYDEBUG(289, *YYCURSOR); yych = *++YYCURSOR; @@ -4016,11 +4017,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(299, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1742 "Zend/zend_language_scanner.l" +#line 1743 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FUNC_C); } -#line 4024 "Zend/zend_language_scanner.c" +#line 4025 "Zend/zend_language_scanner.c" yy300: YYDEBUG(300, *YYCURSOR); yych = *++YYCURSOR; @@ -4040,11 +4041,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(304, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1754 "Zend/zend_language_scanner.l" +#line 1755 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FILE); } -#line 4048 "Zend/zend_language_scanner.c" +#line 4049 "Zend/zend_language_scanner.c" yy305: YYDEBUG(305, *YYCURSOR); yych = *++YYCURSOR; @@ -4074,11 +4075,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(311, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1738 "Zend/zend_language_scanner.l" +#line 1739 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_TRAIT_C); } -#line 4082 "Zend/zend_language_scanner.c" +#line 4083 "Zend/zend_language_scanner.c" yy312: YYDEBUG(312, *YYCURSOR); yych = *++YYCURSOR; @@ -4108,11 +4109,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(318, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1734 "Zend/zend_language_scanner.l" +#line 1735 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CLASS_C); } -#line 4116 "Zend/zend_language_scanner.c" +#line 4117 "Zend/zend_language_scanner.c" yy319: YYDEBUG(319, *YYCURSOR); yych = *++YYCURSOR; @@ -4174,11 +4175,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(331, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1397 "Zend/zend_language_scanner.l" +#line 1398 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_HALT_COMPILER); } -#line 4182 "Zend/zend_language_scanner.c" +#line 4183 "Zend/zend_language_scanner.c" yy332: YYDEBUG(332, *YYCURSOR); yych = *++YYCURSOR; @@ -4198,11 +4199,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(335, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1377 "Zend/zend_language_scanner.l" +#line 1378 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_USE); } -#line 4206 "Zend/zend_language_scanner.c" +#line 4207 "Zend/zend_language_scanner.c" yy336: YYDEBUG(336, *YYCURSOR); yych = *++YYCURSOR; @@ -4221,11 +4222,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(339, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1425 "Zend/zend_language_scanner.l" +#line 1426 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_UNSET); } -#line 4229 "Zend/zend_language_scanner.c" +#line 4230 "Zend/zend_language_scanner.c" yy340: YYDEBUG(340, *YYCURSOR); ++YYCURSOR; @@ -4397,11 +4398,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(357, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1325 "Zend/zend_language_scanner.l" +#line 1326 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INT_CAST); } -#line 4405 "Zend/zend_language_scanner.c" +#line 4406 "Zend/zend_language_scanner.c" yy358: YYDEBUG(358, *YYCURSOR); yych = *++YYCURSOR; @@ -4445,11 +4446,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(366, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1329 "Zend/zend_language_scanner.l" +#line 1330 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DOUBLE_CAST); } -#line 4453 "Zend/zend_language_scanner.c" +#line 4454 "Zend/zend_language_scanner.c" yy367: YYDEBUG(367, *YYCURSOR); yych = *++YYCURSOR; @@ -4519,11 +4520,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(380, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1333 "Zend/zend_language_scanner.l" +#line 1334 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_STRING_CAST); } -#line 4527 "Zend/zend_language_scanner.c" +#line 4528 "Zend/zend_language_scanner.c" yy381: YYDEBUG(381, *YYCURSOR); yych = *++YYCURSOR; @@ -4556,11 +4557,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(387, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1337 "Zend/zend_language_scanner.l" +#line 1338 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ARRAY_CAST); } -#line 4564 "Zend/zend_language_scanner.c" +#line 4565 "Zend/zend_language_scanner.c" yy388: YYDEBUG(388, *YYCURSOR); yych = *++YYCURSOR; @@ -4598,11 +4599,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(395, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1341 "Zend/zend_language_scanner.l" +#line 1342 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_OBJECT_CAST); } -#line 4606 "Zend/zend_language_scanner.c" +#line 4607 "Zend/zend_language_scanner.c" yy396: YYDEBUG(396, *YYCURSOR); yych = *++YYCURSOR; @@ -4643,11 +4644,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(403, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1345 "Zend/zend_language_scanner.l" +#line 1346 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_BOOL_CAST); } -#line 4651 "Zend/zend_language_scanner.c" +#line 4652 "Zend/zend_language_scanner.c" yy404: YYDEBUG(404, *YYCURSOR); yych = *++YYCURSOR; @@ -4707,11 +4708,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(415, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1349 "Zend/zend_language_scanner.l" +#line 1350 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_UNSET_CAST); } -#line 4715 "Zend/zend_language_scanner.c" +#line 4716 "Zend/zend_language_scanner.c" yy416: YYDEBUG(416, *YYCURSOR); yych = *++YYCURSOR; @@ -4725,11 +4726,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(418, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1321 "Zend/zend_language_scanner.l" +#line 1322 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_VAR); } -#line 4733 "Zend/zend_language_scanner.c" +#line 4734 "Zend/zend_language_scanner.c" yy419: YYDEBUG(419, *YYCURSOR); yych = *++YYCURSOR; @@ -4749,11 +4750,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(422, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1313 "Zend/zend_language_scanner.l" +#line 1314 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_NEW); } -#line 4757 "Zend/zend_language_scanner.c" +#line 4758 "Zend/zend_language_scanner.c" yy423: YYDEBUG(423, *YYCURSOR); yych = *++YYCURSOR; @@ -4792,11 +4793,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(430, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1373 "Zend/zend_language_scanner.l" +#line 1374 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_NAMESPACE); } -#line 4800 "Zend/zend_language_scanner.c" +#line 4801 "Zend/zend_language_scanner.c" yy431: YYDEBUG(431, *YYCURSOR); ++YYCURSOR; @@ -4805,22 +4806,22 @@ int start_line = CG(zend_lineno); yy432: YYDEBUG(432, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1945 "Zend/zend_language_scanner.l" +#line 1946 "Zend/zend_language_scanner.l" { BEGIN(INITIAL); RETURN_TOKEN(T_CLOSE_TAG); /* implicit ';' at php-end tag */ } -#line 4814 "Zend/zend_language_scanner.c" +#line 4815 "Zend/zend_language_scanner.c" yy433: YYDEBUG(433, *YYCURSOR); ++YYCURSOR; YYDEBUG(434, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1309 "Zend/zend_language_scanner.l" +#line 1310 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_COALESCE); } -#line 4824 "Zend/zend_language_scanner.c" +#line 4825 "Zend/zend_language_scanner.c" yy435: YYDEBUG(435, *YYCURSOR); yych = *++YYCURSOR; @@ -4851,11 +4852,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(440, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1505 "Zend/zend_language_scanner.l" +#line 1506 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CONCAT_EQUAL); } -#line 4859 "Zend/zend_language_scanner.c" +#line 4860 "Zend/zend_language_scanner.c" yy441: YYDEBUG(441, *YYCURSOR); yych = *++YYCURSOR; @@ -4864,21 +4865,21 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(443, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1305 "Zend/zend_language_scanner.l" +#line 1306 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ELLIPSIS); } -#line 4872 "Zend/zend_language_scanner.c" +#line 4873 "Zend/zend_language_scanner.c" yy444: YYDEBUG(444, *YYCURSOR); ++YYCURSOR; YYDEBUG(445, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1297 "Zend/zend_language_scanner.l" +#line 1298 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_PAAMAYIM_NEKUDOTAYIM); } -#line 4882 "Zend/zend_language_scanner.c" +#line 4883 "Zend/zend_language_scanner.c" yy446: YYDEBUG(446, *YYCURSOR); ++YYCURSOR; @@ -4900,32 +4901,32 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(449, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1485 "Zend/zend_language_scanner.l" +#line 1486 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_MINUS_EQUAL); } -#line 4908 "Zend/zend_language_scanner.c" +#line 4909 "Zend/zend_language_scanner.c" yy450: YYDEBUG(450, *YYCURSOR); ++YYCURSOR; YYDEBUG(451, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1449 "Zend/zend_language_scanner.l" +#line 1450 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DEC); } -#line 4918 "Zend/zend_language_scanner.c" +#line 4919 "Zend/zend_language_scanner.c" yy452: YYDEBUG(452, *YYCURSOR); ++YYCURSOR; YYDEBUG(453, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1271 "Zend/zend_language_scanner.l" +#line 1272 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_PROPERTY); RETURN_TOKEN(T_OBJECT_OPERATOR); } -#line 4929 "Zend/zend_language_scanner.c" +#line 4930 "Zend/zend_language_scanner.c" yy454: YYDEBUG(454, *YYCURSOR); yych = *++YYCURSOR; @@ -4970,11 +4971,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(460, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1421 "Zend/zend_language_scanner.l" +#line 1422 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_PUBLIC); } -#line 4978 "Zend/zend_language_scanner.c" +#line 4979 "Zend/zend_language_scanner.c" yy461: YYDEBUG(461, *YYCURSOR); yych = *++YYCURSOR; @@ -5029,11 +5030,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(469, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1417 "Zend/zend_language_scanner.l" +#line 1418 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_PROTECTED); } -#line 5037 "Zend/zend_language_scanner.c" +#line 5038 "Zend/zend_language_scanner.c" yy470: YYDEBUG(470, *YYCURSOR); yych = *++YYCURSOR; @@ -5063,11 +5064,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(475, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1413 "Zend/zend_language_scanner.l" +#line 1414 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_PRIVATE); } -#line 5071 "Zend/zend_language_scanner.c" +#line 5072 "Zend/zend_language_scanner.c" yy476: YYDEBUG(476, *YYCURSOR); ++YYCURSOR; @@ -5076,11 +5077,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(477, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1247 "Zend/zend_language_scanner.l" +#line 1248 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_PRINT); } -#line 5084 "Zend/zend_language_scanner.c" +#line 5085 "Zend/zend_language_scanner.c" yy478: YYDEBUG(478, *YYCURSOR); yych = *++YYCURSOR; @@ -5105,11 +5106,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(482, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1239 "Zend/zend_language_scanner.l" +#line 1240 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_GOTO); } -#line 5113 "Zend/zend_language_scanner.c" +#line 5114 "Zend/zend_language_scanner.c" yy483: YYDEBUG(483, *YYCURSOR); yych = *++YYCURSOR; @@ -5133,11 +5134,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(487, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1385 "Zend/zend_language_scanner.l" +#line 1386 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_GLOBAL); } -#line 5141 "Zend/zend_language_scanner.c" +#line 5142 "Zend/zend_language_scanner.c" yy488: YYDEBUG(488, *YYCURSOR); yych = *++YYCURSOR; @@ -5174,11 +5175,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(495, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1231 "Zend/zend_language_scanner.l" +#line 1232 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_BREAK); } -#line 5182 "Zend/zend_language_scanner.c" +#line 5183 "Zend/zend_language_scanner.c" yy496: YYDEBUG(496, *YYCURSOR); yych = *++YYCURSOR; @@ -5218,11 +5219,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(503, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1215 "Zend/zend_language_scanner.l" +#line 1216 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_SWITCH); } -#line 5226 "Zend/zend_language_scanner.c" +#line 5227 "Zend/zend_language_scanner.c" yy504: YYDEBUG(504, *YYCURSOR); yych = *++YYCURSOR; @@ -5246,11 +5247,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(508, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1401 "Zend/zend_language_scanner.l" +#line 1402 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_STATIC); } -#line 5254 "Zend/zend_language_scanner.c" +#line 5255 "Zend/zend_language_scanner.c" yy509: YYDEBUG(509, *YYCURSOR); yych = *++YYCURSOR; @@ -5277,11 +5278,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(513, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1211 "Zend/zend_language_scanner.l" +#line 1212 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_AS); } -#line 5285 "Zend/zend_language_scanner.c" +#line 5286 "Zend/zend_language_scanner.c" yy514: YYDEBUG(514, *YYCURSOR); yych = *++YYCURSOR; @@ -5300,11 +5301,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(517, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1437 "Zend/zend_language_scanner.l" +#line 1438 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ARRAY); } -#line 5308 "Zend/zend_language_scanner.c" +#line 5309 "Zend/zend_language_scanner.c" yy518: YYDEBUG(518, *YYCURSOR); ++YYCURSOR; @@ -5313,11 +5314,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(519, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1545 "Zend/zend_language_scanner.l" +#line 1546 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_LOGICAL_AND); } -#line 5321 "Zend/zend_language_scanner.c" +#line 5322 "Zend/zend_language_scanner.c" yy520: YYDEBUG(520, *YYCURSOR); yych = *++YYCURSOR; @@ -5351,11 +5352,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(526, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1405 "Zend/zend_language_scanner.l" +#line 1406 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ABSTRACT); } -#line 5359 "Zend/zend_language_scanner.c" +#line 5360 "Zend/zend_language_scanner.c" yy527: YYDEBUG(527, *YYCURSOR); yych = *++YYCURSOR; @@ -5379,11 +5380,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(531, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1171 "Zend/zend_language_scanner.l" +#line 1172 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_WHILE); } -#line 5387 "Zend/zend_language_scanner.c" +#line 5388 "Zend/zend_language_scanner.c" yy532: YYDEBUG(532, *YYCURSOR); ++YYCURSOR; @@ -5392,11 +5393,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(533, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1155 "Zend/zend_language_scanner.l" +#line 1156 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IF); } -#line 5400 "Zend/zend_language_scanner.c" +#line 5401 "Zend/zend_language_scanner.c" yy534: YYDEBUG(534, *YYCURSOR); yych = *++YYCURSOR; @@ -5448,11 +5449,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(540, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1389 "Zend/zend_language_scanner.l" +#line 1390 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ISSET); } -#line 5456 "Zend/zend_language_scanner.c" +#line 5457 "Zend/zend_language_scanner.c" yy541: YYDEBUG(541, *YYCURSOR); yych = *++YYCURSOR; @@ -5506,11 +5507,11 @@ int start_line = CG(zend_lineno); yy548: YYDEBUG(548, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1357 "Zend/zend_language_scanner.l" +#line 1358 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INCLUDE); } -#line 5514 "Zend/zend_language_scanner.c" +#line 5515 "Zend/zend_language_scanner.c" yy549: YYDEBUG(549, *YYCURSOR); yych = *++YYCURSOR; @@ -5539,11 +5540,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(554, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1361 "Zend/zend_language_scanner.l" +#line 1362 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INCLUDE_ONCE); } -#line 5547 "Zend/zend_language_scanner.c" +#line 5548 "Zend/zend_language_scanner.c" yy555: YYDEBUG(555, *YYCURSOR); yych = *++YYCURSOR; @@ -5577,11 +5578,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(561, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1255 "Zend/zend_language_scanner.l" +#line 1256 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INTERFACE); } -#line 5585 "Zend/zend_language_scanner.c" +#line 5586 "Zend/zend_language_scanner.c" yy562: YYDEBUG(562, *YYCURSOR); yych = *++YYCURSOR; @@ -5631,11 +5632,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(569, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1381 "Zend/zend_language_scanner.l" +#line 1382 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INSTEADOF); } -#line 5639 "Zend/zend_language_scanner.c" +#line 5640 "Zend/zend_language_scanner.c" yy570: YYDEBUG(570, *YYCURSOR); yych = *++YYCURSOR; @@ -5664,11 +5665,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(575, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1207 "Zend/zend_language_scanner.l" +#line 1208 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_INSTANCEOF); } -#line 5672 "Zend/zend_language_scanner.c" +#line 5673 "Zend/zend_language_scanner.c" yy576: YYDEBUG(576, *YYCURSOR); yych = *++YYCURSOR; @@ -5712,11 +5713,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(584, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1267 "Zend/zend_language_scanner.l" +#line 1268 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_IMPLEMENTS); } -#line 5720 "Zend/zend_language_scanner.c" +#line 5721 "Zend/zend_language_scanner.c" yy585: YYDEBUG(585, *YYCURSOR); yych = *++YYCURSOR; @@ -5744,11 +5745,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(588, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1139 "Zend/zend_language_scanner.l" +#line 1140 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_TRY); } -#line 5752 "Zend/zend_language_scanner.c" +#line 5753 "Zend/zend_language_scanner.c" yy589: YYDEBUG(589, *YYCURSOR); yych = *++YYCURSOR; @@ -5767,11 +5768,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(592, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1259 "Zend/zend_language_scanner.l" +#line 1260 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_TRAIT); } -#line 5775 "Zend/zend_language_scanner.c" +#line 5776 "Zend/zend_language_scanner.c" yy593: YYDEBUG(593, *YYCURSOR); yych = *++YYCURSOR; @@ -5790,11 +5791,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(596, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1151 "Zend/zend_language_scanner.l" +#line 1152 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_THROW); } -#line 5798 "Zend/zend_language_scanner.c" +#line 5799 "Zend/zend_language_scanner.c" yy597: YYDEBUG(597, *YYCURSOR); yych = *++YYCURSOR; @@ -5827,11 +5828,11 @@ int start_line = CG(zend_lineno); yy601: YYDEBUG(601, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1135 "Zend/zend_language_scanner.l" +#line 1136 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_YIELD); } -#line 5835 "Zend/zend_language_scanner.c" +#line 5836 "Zend/zend_language_scanner.c" yy602: YYDEBUG(602, *YYCURSOR); ++YYCURSOR; @@ -5873,12 +5874,12 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(608, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1130 "Zend/zend_language_scanner.l" +#line 1131 "Zend/zend_language_scanner.l" { HANDLE_NEWLINES(yytext, yyleng); RETURN_TOKEN(T_YIELD_FROM); } -#line 5882 "Zend/zend_language_scanner.c" +#line 5883 "Zend/zend_language_scanner.c" yy609: YYDEBUG(609, *YYCURSOR); yych = *++YYCURSOR; @@ -5939,11 +5940,11 @@ int start_line = CG(zend_lineno); yy616: YYDEBUG(616, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1365 "Zend/zend_language_scanner.l" +#line 1366 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_REQUIRE); } -#line 5947 "Zend/zend_language_scanner.c" +#line 5948 "Zend/zend_language_scanner.c" yy617: YYDEBUG(617, *YYCURSOR); yych = *++YYCURSOR; @@ -5972,11 +5973,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(622, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1369 "Zend/zend_language_scanner.l" +#line 1370 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_REQUIRE_ONCE); } -#line 5980 "Zend/zend_language_scanner.c" +#line 5981 "Zend/zend_language_scanner.c" yy623: YYDEBUG(623, *YYCURSOR); yych = *++YYCURSOR; @@ -5995,11 +5996,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(626, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1126 "Zend/zend_language_scanner.l" +#line 1127 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_RETURN); } -#line 6003 "Zend/zend_language_scanner.c" +#line 6004 "Zend/zend_language_scanner.c" yy627: YYDEBUG(627, *YYCURSOR); yych = *++YYCURSOR; @@ -6089,11 +6090,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(637, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1235 "Zend/zend_language_scanner.l" +#line 1236 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CONTINUE); } -#line 6097 "Zend/zend_language_scanner.c" +#line 6098 "Zend/zend_language_scanner.c" yy638: YYDEBUG(638, *YYCURSOR); ++YYCURSOR; @@ -6102,11 +6103,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(639, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1122 "Zend/zend_language_scanner.l" +#line 1123 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CONST); } -#line 6110 "Zend/zend_language_scanner.c" +#line 6111 "Zend/zend_language_scanner.c" yy640: YYDEBUG(640, *YYCURSOR); yych = *++YYCURSOR; @@ -6131,11 +6132,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(644, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1317 "Zend/zend_language_scanner.l" +#line 1318 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CLONE); } -#line 6139 "Zend/zend_language_scanner.c" +#line 6140 "Zend/zend_language_scanner.c" yy645: YYDEBUG(645, *YYCURSOR); yych = *++YYCURSOR; @@ -6149,11 +6150,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(647, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1251 "Zend/zend_language_scanner.l" +#line 1252 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CLASS); } -#line 6157 "Zend/zend_language_scanner.c" +#line 6158 "Zend/zend_language_scanner.c" yy648: YYDEBUG(648, *YYCURSOR); yych = *++YYCURSOR; @@ -6199,11 +6200,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(656, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1441 "Zend/zend_language_scanner.l" +#line 1442 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CALLABLE); } -#line 6207 "Zend/zend_language_scanner.c" +#line 6208 "Zend/zend_language_scanner.c" yy657: YYDEBUG(657, *YYCURSOR); ++YYCURSOR; @@ -6212,11 +6213,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(658, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1223 "Zend/zend_language_scanner.l" +#line 1224 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CASE); } -#line 6220 "Zend/zend_language_scanner.c" +#line 6221 "Zend/zend_language_scanner.c" yy659: YYDEBUG(659, *YYCURSOR); yych = *++YYCURSOR; @@ -6230,11 +6231,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(661, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1143 "Zend/zend_language_scanner.l" +#line 1144 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_CATCH); } -#line 6238 "Zend/zend_language_scanner.c" +#line 6239 "Zend/zend_language_scanner.c" yy662: YYDEBUG(662, *YYCURSOR); yych = *++YYCURSOR; @@ -6285,11 +6286,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(671, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1118 "Zend/zend_language_scanner.l" +#line 1119 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FUNCTION); } -#line 6293 "Zend/zend_language_scanner.c" +#line 6294 "Zend/zend_language_scanner.c" yy672: YYDEBUG(672, *YYCURSOR); ++YYCURSOR; @@ -6313,11 +6314,11 @@ int start_line = CG(zend_lineno); yy673: YYDEBUG(673, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1183 "Zend/zend_language_scanner.l" +#line 1184 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FOR); } -#line 6321 "Zend/zend_language_scanner.c" +#line 6322 "Zend/zend_language_scanner.c" yy674: YYDEBUG(674, *YYCURSOR); yych = *++YYCURSOR; @@ -6341,11 +6342,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(678, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1191 "Zend/zend_language_scanner.l" +#line 1192 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FOREACH); } -#line 6349 "Zend/zend_language_scanner.c" +#line 6350 "Zend/zend_language_scanner.c" yy679: YYDEBUG(679, *YYCURSOR); yych = *++YYCURSOR; @@ -6379,11 +6380,11 @@ int start_line = CG(zend_lineno); yy682: YYDEBUG(682, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1409 "Zend/zend_language_scanner.l" +#line 1410 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FINAL); } -#line 6387 "Zend/zend_language_scanner.c" +#line 6388 "Zend/zend_language_scanner.c" yy683: YYDEBUG(683, *YYCURSOR); yych = *++YYCURSOR; @@ -6397,11 +6398,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(685, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1147 "Zend/zend_language_scanner.l" +#line 1148 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_FINALLY); } -#line 6405 "Zend/zend_language_scanner.c" +#line 6406 "Zend/zend_language_scanner.c" yy686: YYDEBUG(686, *YYCURSOR); yych = *++YYCURSOR; @@ -6432,11 +6433,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(689, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1179 "Zend/zend_language_scanner.l" +#line 1180 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DO); } -#line 6440 "Zend/zend_language_scanner.c" +#line 6441 "Zend/zend_language_scanner.c" yy690: YYDEBUG(690, *YYCURSOR); ++YYCURSOR; @@ -6445,11 +6446,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(691, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1114 "Zend/zend_language_scanner.l" +#line 1115 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_EXIT); } -#line 6453 "Zend/zend_language_scanner.c" +#line 6454 "Zend/zend_language_scanner.c" yy692: YYDEBUG(692, *YYCURSOR); yych = *++YYCURSOR; @@ -6484,11 +6485,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(698, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1227 "Zend/zend_language_scanner.l" +#line 1228 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DEFAULT); } -#line 6492 "Zend/zend_language_scanner.c" +#line 6493 "Zend/zend_language_scanner.c" yy699: YYDEBUG(699, *YYCURSOR); yych = *++YYCURSOR; @@ -6512,11 +6513,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(703, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1199 "Zend/zend_language_scanner.l" +#line 1200 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_DECLARE); } -#line 6520 "Zend/zend_language_scanner.c" +#line 6521 "Zend/zend_language_scanner.c" yy704: YYDEBUG(704, *YYCURSOR); yych = *++YYCURSOR; @@ -6596,11 +6597,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(716, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1263 "Zend/zend_language_scanner.l" +#line 1264 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_EXTENDS); } -#line 6604 "Zend/zend_language_scanner.c" +#line 6605 "Zend/zend_language_scanner.c" yy717: YYDEBUG(717, *YYCURSOR); ++YYCURSOR; @@ -6609,11 +6610,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(718, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1110 "Zend/zend_language_scanner.l" +#line 1111 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_EXIT); } -#line 6617 "Zend/zend_language_scanner.c" +#line 6618 "Zend/zend_language_scanner.c" yy719: YYDEBUG(719, *YYCURSOR); yych = *++YYCURSOR; @@ -6627,11 +6628,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(721, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1353 "Zend/zend_language_scanner.l" +#line 1354 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_EVAL); } -#line 6635 "Zend/zend_language_scanner.c" +#line 6636 "Zend/zend_language_scanner.c" yy722: YYDEBUG(722, *YYCURSOR); yych = *++YYCURSOR; @@ -6701,11 +6702,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(732, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1175 "Zend/zend_language_scanner.l" +#line 1176 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ENDWHILE); } -#line 6709 "Zend/zend_language_scanner.c" +#line 6710 "Zend/zend_language_scanner.c" yy733: YYDEBUG(733, *YYCURSOR); yych = *++YYCURSOR; @@ -6734,11 +6735,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(738, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1219 "Zend/zend_language_scanner.l" +#line 1220 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ENDSWITCH); } -#line 6742 "Zend/zend_language_scanner.c" +#line 6743 "Zend/zend_language_scanner.c" yy739: YYDEBUG(739, *YYCURSOR); ++YYCURSOR; @@ -6747,11 +6748,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(740, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1163 "Zend/zend_language_scanner.l" +#line 1164 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ENDIF); } -#line 6755 "Zend/zend_language_scanner.c" +#line 6756 "Zend/zend_language_scanner.c" yy741: YYDEBUG(741, *YYCURSOR); yych = *++YYCURSOR; @@ -6780,11 +6781,11 @@ int start_line = CG(zend_lineno); yy743: YYDEBUG(743, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1187 "Zend/zend_language_scanner.l" +#line 1188 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ENDFOR); } -#line 6788 "Zend/zend_language_scanner.c" +#line 6789 "Zend/zend_language_scanner.c" yy744: YYDEBUG(744, *YYCURSOR); yych = *++YYCURSOR; @@ -6808,11 +6809,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(748, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1195 "Zend/zend_language_scanner.l" +#line 1196 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ENDFOREACH); } -#line 6816 "Zend/zend_language_scanner.c" +#line 6817 "Zend/zend_language_scanner.c" yy749: YYDEBUG(749, *YYCURSOR); yych = *++YYCURSOR; @@ -6846,11 +6847,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(755, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1203 "Zend/zend_language_scanner.l" +#line 1204 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ENDDECLARE); } -#line 6854 "Zend/zend_language_scanner.c" +#line 6855 "Zend/zend_language_scanner.c" yy756: YYDEBUG(756, *YYCURSOR); yych = *++YYCURSOR; @@ -6869,11 +6870,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(759, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1393 "Zend/zend_language_scanner.l" +#line 1394 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_EMPTY); } -#line 6877 "Zend/zend_language_scanner.c" +#line 6878 "Zend/zend_language_scanner.c" yy760: YYDEBUG(760, *YYCURSOR); yych = *++YYCURSOR; @@ -6902,11 +6903,11 @@ int start_line = CG(zend_lineno); yy762: YYDEBUG(762, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1167 "Zend/zend_language_scanner.l" +#line 1168 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ELSE); } -#line 6910 "Zend/zend_language_scanner.c" +#line 6911 "Zend/zend_language_scanner.c" yy763: YYDEBUG(763, *YYCURSOR); yych = *++YYCURSOR; @@ -6920,11 +6921,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(765, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1159 "Zend/zend_language_scanner.l" +#line 1160 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ELSEIF); } -#line 6928 "Zend/zend_language_scanner.c" +#line 6929 "Zend/zend_language_scanner.c" yy766: YYDEBUG(766, *YYCURSOR); yych = *++YYCURSOR; @@ -6938,11 +6939,11 @@ int start_line = CG(zend_lineno); } YYDEBUG(768, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1243 "Zend/zend_language_scanner.l" +#line 1244 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_ECHO); } -#line 6946 "Zend/zend_language_scanner.c" +#line 6947 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_LOOKING_FOR_PROPERTY: @@ -7015,12 +7016,12 @@ int start_line = CG(zend_lineno); yy772: YYDEBUG(772, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1276 "Zend/zend_language_scanner.l" +#line 1277 "Zend/zend_language_scanner.l" { HANDLE_NEWLINES(yytext, yyleng); RETURN_TOKEN(T_WHITESPACE); } -#line 7024 "Zend/zend_language_scanner.c" +#line 7025 "Zend/zend_language_scanner.c" yy773: YYDEBUG(773, *YYCURSOR); ++YYCURSOR; @@ -7028,13 +7029,13 @@ int start_line = CG(zend_lineno); yy774: YYDEBUG(774, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1291 "Zend/zend_language_scanner.l" +#line 1292 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(); goto restart; } -#line 7038 "Zend/zend_language_scanner.c" +#line 7039 "Zend/zend_language_scanner.c" yy775: YYDEBUG(775, *YYCURSOR); ++YYCURSOR; @@ -7043,13 +7044,13 @@ int start_line = CG(zend_lineno); yy776: YYDEBUG(776, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1285 "Zend/zend_language_scanner.l" +#line 1286 "Zend/zend_language_scanner.l" { yy_pop_state(); zend_copy_value(zendlval, yytext, yyleng); RETURN_TOKEN(T_STRING); } -#line 7053 "Zend/zend_language_scanner.c" +#line 7054 "Zend/zend_language_scanner.c" yy777: YYDEBUG(777, *YYCURSOR); yych = *++YYCURSOR; @@ -7070,11 +7071,11 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(781, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1281 "Zend/zend_language_scanner.l" +#line 1282 "Zend/zend_language_scanner.l" { RETURN_TOKEN(T_OBJECT_OPERATOR); } -#line 7078 "Zend/zend_language_scanner.c" +#line 7079 "Zend/zend_language_scanner.c" yy782: YYDEBUG(782, *YYCURSOR); ++YYCURSOR; @@ -7159,14 +7160,14 @@ int start_line = CG(zend_lineno); yy787: YYDEBUG(787, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1596 "Zend/zend_language_scanner.l" +#line 1597 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(); yy_push_state(ST_IN_SCRIPTING); goto restart; } -#line 7170 "Zend/zend_language_scanner.c" +#line 7171 "Zend/zend_language_scanner.c" yy788: YYDEBUG(788, *YYCURSOR); yych = *++YYCURSOR; @@ -7191,7 +7192,7 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(793, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1587 "Zend/zend_language_scanner.l" +#line 1588 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); zend_copy_value(zendlval, yytext, yyleng); @@ -7199,7 +7200,7 @@ int start_line = CG(zend_lineno); yy_push_state(ST_IN_SCRIPTING); RETURN_TOKEN(T_STRING_VARNAME); } -#line 7203 "Zend/zend_language_scanner.c" +#line 7204 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_NOWDOC: @@ -7210,7 +7211,7 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(797, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2315 "Zend/zend_language_scanner.l" +#line 2316 "Zend/zend_language_scanner.l" { int newline = 0; @@ -7266,7 +7267,7 @@ int start_line = CG(zend_lineno); HANDLE_NEWLINES(yytext, yyleng - newline); RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE); } -#line 7270 "Zend/zend_language_scanner.c" +#line 7271 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_VAR_OFFSET: { @@ -7373,7 +7374,7 @@ int start_line = CG(zend_lineno); yy801: YYDEBUG(801, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1704 "Zend/zend_language_scanner.l" +#line 1705 "Zend/zend_language_scanner.l" { /* Offset could be treated as a long */ if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) { char *end; @@ -7389,7 +7390,7 @@ int start_line = CG(zend_lineno); } RETURN_TOKEN(T_NUM_STRING); } -#line 7393 "Zend/zend_language_scanner.c" +#line 7394 "Zend/zend_language_scanner.c" yy802: YYDEBUG(802, *YYCURSOR); yych = *++YYCURSOR; @@ -7409,23 +7410,23 @@ int start_line = CG(zend_lineno); yy804: YYDEBUG(804, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1864 "Zend/zend_language_scanner.l" +#line 1865 "Zend/zend_language_scanner.l" { /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */ RETURN_TOKEN(yytext[0]); } -#line 7418 "Zend/zend_language_scanner.c" +#line 7419 "Zend/zend_language_scanner.c" yy805: YYDEBUG(805, *YYCURSOR); ++YYCURSOR; YYDEBUG(806, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1859 "Zend/zend_language_scanner.l" +#line 1860 "Zend/zend_language_scanner.l" { yy_pop_state(); RETURN_TOKEN(']'); } -#line 7429 "Zend/zend_language_scanner.c" +#line 7430 "Zend/zend_language_scanner.c" yy807: YYDEBUG(807, *YYCURSOR); yych = *++YYCURSOR; @@ -7435,7 +7436,7 @@ int start_line = CG(zend_lineno); ++YYCURSOR; YYDEBUG(809, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1869 "Zend/zend_language_scanner.l" +#line 1870 "Zend/zend_language_scanner.l" { /* Invalid rule to return a more explicit parse error with proper line number */ yyless(0); @@ -7443,7 +7444,7 @@ int start_line = CG(zend_lineno); ZVAL_NULL(zendlval); RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE); } -#line 7447 "Zend/zend_language_scanner.c" +#line 7448 "Zend/zend_language_scanner.c" yy810: YYDEBUG(810, *YYCURSOR); ++YYCURSOR; @@ -7452,18 +7453,18 @@ int start_line = CG(zend_lineno); yy811: YYDEBUG(811, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1877 "Zend/zend_language_scanner.l" +#line 1878 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); RETURN_TOKEN(T_STRING); } -#line 7461 "Zend/zend_language_scanner.c" +#line 7462 "Zend/zend_language_scanner.c" yy812: YYDEBUG(812, *YYCURSOR); ++YYCURSOR; YYDEBUG(813, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2372 "Zend/zend_language_scanner.l" +#line 2373 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { RETURN_TOKEN(END); @@ -7472,7 +7473,7 @@ int start_line = CG(zend_lineno); zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 7476 "Zend/zend_language_scanner.c" +#line 7477 "Zend/zend_language_scanner.c" yy814: YYDEBUG(814, *YYCURSOR); ++YYCURSOR; @@ -7508,12 +7509,12 @@ int start_line = CG(zend_lineno); yy818: YYDEBUG(818, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1854 "Zend/zend_language_scanner.l" +#line 1855 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); RETURN_TOKEN(T_VARIABLE); } -#line 7517 "Zend/zend_language_scanner.c" +#line 7518 "Zend/zend_language_scanner.c" yy819: YYDEBUG(819, *YYCURSOR); ++YYCURSOR; @@ -7553,12 +7554,12 @@ int start_line = CG(zend_lineno); yy826: YYDEBUG(826, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1720 "Zend/zend_language_scanner.l" +#line 1721 "Zend/zend_language_scanner.l" { /* Offset must be treated as a string */ ZVAL_STRINGL(zendlval, yytext, yyleng); RETURN_TOKEN(T_NUM_STRING); } -#line 7562 "Zend/zend_language_scanner.c" +#line 7563 "Zend/zend_language_scanner.c" yy827: YYDEBUG(827, *YYCURSOR); ++YYCURSOR; @@ -7581,6 +7582,6 @@ int start_line = CG(zend_lineno); goto yy826; } } -#line 2381 "Zend/zend_language_scanner.l" +#line 2382 "Zend/zend_language_scanner.l" } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index bc0b92eb1a018..058a8d717671f 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -178,6 +178,7 @@ void startup_scanner(void) { CG(parse_error) = 0; CG(doc_comment) = NULL; + CG(attributes) = NULL; zend_stack_init(&SCNG(state_stack), sizeof(int)); zend_ptr_stack_init(&SCNG(heredoc_label_stack)); } diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 6c1488ad0c610..2e342084f668c 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -70,6 +70,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->function_name = NULL; op_array->filename = zend_get_compiled_filename(); op_array->doc_comment = NULL; + op_array->attributes = NULL; op_array->arg_info = NULL; op_array->num_args = 0; @@ -282,6 +283,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (prop_info->doc_comment) { zend_string_release(prop_info->doc_comment); } + if (prop_info->attributes) { + zend_array_ptr_dtor(prop_info->attributes); + } } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->properties_info); @@ -296,6 +300,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (c->doc_comment) { zend_string_release(c->doc_comment); } + if (c->attributes) { + zend_array_ptr_dtor(c->attributes); + } } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->constants_table); @@ -306,6 +313,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (ce->info.user.doc_comment) { zend_string_release(ce->info.user.doc_comment); } + if (ce->info.user.attributes) { + zend_array_ptr_dtor(ce->info.user.attributes); + } _destroy_zend_class_traits_info(ce); @@ -342,6 +352,9 @@ ZEND_API void destroy_zend_class(zval *zv) if (c->doc_comment && c->ce == ce) { zend_string_release(c->doc_comment); } + if (c->attributes) { + zend_array_ptr_dtor(c->attributes); + } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->constants_table); } @@ -409,6 +422,9 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) if (op_array->doc_comment) { zend_string_release(op_array->doc_comment); } + if (op_array->attributes) { + zend_array_ptr_dtor(op_array->attributes); + } if (op_array->live_range) { efree(op_array->live_range); } diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 9545b53e33ea8..056ec2e83081b 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -404,6 +404,8 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define IS_RESOURCE_EX (IS_RESOURCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) #define IS_REFERENCE_EX (IS_REFERENCE | (( IS_TYPE_REFCOUNTED ) << Z_TYPE_FLAGS_SHIFT)) +#define IS_IMMUTABLE_ARRAY_EX (IS_ARRAY | (IS_TYPE_IMMUTABLE << Z_TYPE_FLAGS_SHIFT)) + #define IS_CONSTANT_EX (IS_CONSTANT | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) #define IS_CONSTANT_AST_EX (IS_CONSTANT_AST | ((IS_TYPE_CONSTANT | IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE) << Z_TYPE_FLAGS_SHIFT)) @@ -656,6 +658,12 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { Z_TYPE_INFO_P(__z) = IS_ARRAY_EX; \ } while (0) +#define ZVAL_IMMUTABLE_ARR(z, a) do { \ + zval *__z = (z); \ + Z_ARR_P(__z) = (a); \ + Z_TYPE_INFO_P(__z) = IS_IMMUTABLE_ARRAY_EX; \ + } while (0) + #define ZVAL_NEW_ARR(z) do { \ zval *__z = (z); \ zend_array *_arr = \ diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h index 6958d6139ff73..c099b0eaf399b 100644 --- a/Zend/zend_variables.h +++ b/Zend/zend_variables.h @@ -62,6 +62,15 @@ static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) } } +static zend_always_inline void zend_array_ptr_dtor(zend_array *array) +{ + if (!(GC_FLAGS(array) & IS_ARRAY_IMMUTABLE)) { + if (--GC_REFCOUNT(array) == 0) { + zend_array_destroy(array); + } + } +} + static zend_always_inline void _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC) { if (Z_REFCOUNTED_P(zvalue) || Z_IMMUTABLE_P(zvalue)) { diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 6ac4f0e35f645..88f70e1161d85 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -463,6 +463,14 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra SERIALIZE_PTR(op_array->live_range); SERIALIZE_PTR(op_array->scope); SERIALIZE_STR(op_array->doc_comment); + if (op_array->attributes && !IS_SERIALIZED(op_array->attributes)) { + HashTable *ht; + + SERIALIZE_PTR(op_array->attributes); + ht = op_array->attributes; + UNSERIALIZE_PTR(ht); + zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); + } SERIALIZE_PTR(op_array->try_catch_array); SERIALIZE_PTR(op_array->prototype); } @@ -502,6 +510,14 @@ static void zend_file_cache_serialize_prop_info(zval *zv, if (prop->doc_comment && !IS_SERIALIZED(prop->doc_comment)) { SERIALIZE_STR(prop->doc_comment); } + if (prop->attributes && !IS_SERIALIZED(prop->attributes)) { + HashTable *ht; + + SERIALIZE_PTR(prop->attributes); + ht = prop->attributes; + UNSERIALIZE_PTR(ht); + zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); + } } } @@ -524,6 +540,14 @@ static void zend_file_cache_serialize_class_constant(zval *z if (c->doc_comment && !IS_SERIALIZED(c->doc_comment)) { SERIALIZE_STR(c->doc_comment); } + if (c->attributes && !IS_SERIALIZED(c->attributes)) { + HashTable *ht; + + SERIALIZE_PTR(c->attributes); + ht = c->attributes; + UNSERIALIZE_PTR(ht); + zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); + } } } @@ -567,6 +591,14 @@ static void zend_file_cache_serialize_class(zval *zv, zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant); SERIALIZE_STR(ce->info.user.filename); SERIALIZE_STR(ce->info.user.doc_comment); + if (ce->info.user.attributes && !IS_SERIALIZED(ce->info.user.attributes)) { + HashTable *ht; + + SERIALIZE_PTR(ce->info.user.attributes); + ht = ce->info.user.attributes; + UNSERIALIZE_PTR(ht); + zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); + } zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info); if (ce->trait_aliases) { @@ -1035,6 +1067,14 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr UNSERIALIZE_PTR(op_array->live_range); UNSERIALIZE_PTR(op_array->scope); UNSERIALIZE_STR(op_array->doc_comment); + if (op_array->attributes && !IS_UNSERIALIZED(op_array->attributes)) { + HashTable *ht; + + UNSERIALIZE_PTR(op_array->attributes); + ht = op_array->attributes; + zend_file_cache_unserialize_hash(ht, + script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); + } UNSERIALIZE_PTR(op_array->try_catch_array); UNSERIALIZE_PTR(op_array->prototype); } @@ -1070,6 +1110,14 @@ static void zend_file_cache_unserialize_prop_info(zval *zv, if (prop->doc_comment && !IS_UNSERIALIZED(prop->doc_comment)) { UNSERIALIZE_STR(prop->doc_comment); } + if (prop->attributes && !IS_UNSERIALIZED(prop->attributes)) { + HashTable *ht; + + UNSERIALIZE_PTR(prop->attributes); + ht = prop->attributes; + zend_file_cache_unserialize_hash(ht, + script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); + } } } @@ -1090,6 +1138,14 @@ static void zend_file_cache_unserialize_class_constant(zval * if (c->doc_comment && !IS_UNSERIALIZED(c->doc_comment)) { UNSERIALIZE_STR(c->doc_comment); } + if (c->attributes && !IS_UNSERIALIZED(c->attributes)) { + HashTable *ht; + + UNSERIALIZE_PTR(c->attributes); + ht = c->attributes; + zend_file_cache_unserialize_hash(ht, + script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); + } } } @@ -1131,6 +1187,14 @@ static void zend_file_cache_unserialize_class(zval *zv, script, buf, zend_file_cache_unserialize_class_constant, NULL); UNSERIALIZE_STR(ce->info.user.filename); UNSERIALIZE_STR(ce->info.user.doc_comment); + if (ce->info.user.attributes && !IS_UNSERIALIZED(ce->info.user.attributes)) { + HashTable *ht; + + UNSERIALIZE_PTR(ce->info.user.attributes); + ht = ce->info.user.attributes; + zend_file_cache_unserialize_hash(ht, + script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); + } zend_file_cache_unserialize_hash(&ce->properties_info, script, buf, zend_file_cache_unserialize_prop_info, ZVAL_PTR_DTOR); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index aa3b8e82f3903..40f212ae7361c 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -640,6 +640,21 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } } + if (op_array->attributes) { + if (already_stored) { + op_array->attributes = zend_shared_alloc_get_xlat_entry(op_array->attributes); + ZEND_ASSERT(op_array->attributes != NULL); + } else { + zend_hash_persist(op_array->attributes, zend_persist_zval_static); + zend_accel_store(op_array->attributes, sizeof(HashTable)); + /* make immutable array */ + GC_REFCOUNT(op_array->attributes) = 2; + GC_TYPE_INFO(op_array->attributes) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8); + op_array->attributes->u.flags |= HASH_FLAG_STATIC_KEYS; + op_array->attributes->u.flags &= ~HASH_FLAG_APPLY_PROTECTION; + } + } + if (op_array->try_catch_array) { zend_accel_store(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); } @@ -713,6 +728,15 @@ static void zend_persist_property_info(zval *zv) prop->doc_comment = NULL; } } + if (prop->attributes) { + zend_hash_persist(prop->attributes, zend_persist_zval_static); + zend_accel_store(prop->attributes, sizeof(HashTable)); + /* make immutable array */ + GC_REFCOUNT(prop->attributes) = 2; + GC_TYPE_INFO(prop->attributes) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8); + prop->attributes->u.flags |= HASH_FLAG_STATIC_KEYS; + prop->attributes->u.flags &= ~HASH_FLAG_APPLY_PROTECTION; + } } static void zend_persist_class_constant(zval *zv) @@ -746,6 +770,15 @@ static void zend_persist_class_constant(zval *zv) c->doc_comment = NULL; } } + if (c->attributes) { + zend_hash_persist(c->attributes, zend_persist_zval_static); + zend_accel_store(c->attributes, sizeof(HashTable)); + /* make immutable array */ + GC_REFCOUNT(c->attributes) = 2; + GC_TYPE_INFO(c->attributes) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8); + c->attributes->u.flags |= HASH_FLAG_STATIC_KEYS; + c->attributes->u.flags &= ~HASH_FLAG_APPLY_PROTECTION; + } } static void zend_persist_class_entry(zval *zv) @@ -794,6 +827,15 @@ static void zend_persist_class_entry(zval *zv) ce->info.user.doc_comment = NULL; } } + if (ce->info.user.attributes) { + zend_hash_persist(ce->info.user.attributes, zend_persist_zval_static); + zend_accel_store(ce->info.user.attributes, sizeof(HashTable)); + /* make immutable array */ + GC_REFCOUNT(ce->info.user.attributes) = 2; + GC_TYPE_INFO(ce->info.user.attributes) = IS_ARRAY | (IS_ARRAY_IMMUTABLE << 8); + ce->info.user.attributes->u.flags |= HASH_FLAG_STATIC_KEYS; + ce->info.user.attributes->u.flags &= ~HASH_FLAG_APPLY_PROTECTION; + } zend_hash_persist(&ce->properties_info, zend_persist_property_info); if (ce->num_interfaces && ce->interfaces) { efree(ce->interfaces); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 22e74d6b36f12..21b4abab1af9a 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -244,6 +244,11 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) ADD_STRING(op_array->doc_comment); } + if (op_array->attributes) { + ADD_DUP_SIZE(op_array->attributes, sizeof(HashTable)); + zend_hash_persist_calc(op_array->attributes, zend_persist_zval_calc); + } + if (op_array->try_catch_array) { ADD_DUP_SIZE(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch); } @@ -291,6 +296,10 @@ static void zend_persist_property_info_calc(zval *zv) if (ZCG(accel_directives).save_comments && prop->doc_comment) { ADD_STRING(prop->doc_comment); } + if (prop->attributes) { + ADD_DUP_SIZE(prop->attributes, sizeof(HashTable)); + zend_hash_persist_calc(prop->attributes, zend_persist_zval_calc); + } } } @@ -305,6 +314,10 @@ static void zend_persist_class_constant_calc(zval *zv) if (ZCG(accel_directives).save_comments && c->doc_comment) { ADD_STRING(c->doc_comment); } + if (c->attributes) { + ADD_DUP_SIZE(c->attributes, sizeof(HashTable)); + zend_hash_persist_calc(c->attributes, zend_persist_zval_calc); + } } } @@ -341,6 +354,10 @@ static void zend_persist_class_entry_calc(zval *zv) if (ZCG(accel_directives).save_comments && ce->info.user.doc_comment) { ADD_STRING(ce->info.user.doc_comment); } + if (ce->info.user.attributes) { + ADD_DUP_SIZE(ce->info.user.attributes, sizeof(HashTable)); + zend_hash_persist_calc(ce->info.user.attributes, zend_persist_zval_calc); + } zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 186df87fd7363..9db607d33eeee 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1910,6 +1910,29 @@ ZEND_METHOD(reflection_function, getDocComment) } /* }}} */ +/* {{{ proto public array ReflectionFunction::getAttributes() + Returns the attributes of this function */ +ZEND_METHOD(reflection_function, getAttributes) +{ + reflection_object *intern; + zend_function *fptr; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + GET_REFLECTION_OBJECT_PTR(fptr); + if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.attributes) { + if (GC_FLAGS(fptr->op_array.attributes) & IS_ARRAY_IMMUTABLE) { + RETURN_IMMUTABLE_ARR(fptr->op_array.attributes); + } else { + GC_REFCOUNT(fptr->op_array.attributes)++; + RETURN_ARR(fptr->op_array.attributes); + } + } + RETURN_FALSE; +} +/* }}} */ + /* {{{ proto public array ReflectionFunction::getStaticVariables() Returns an associative array containing this function's static variables and their values */ ZEND_METHOD(reflection_function, getStaticVariables) @@ -3874,6 +3897,29 @@ ZEND_METHOD(reflection_class_constant, getDocComment) } /* }}} */ +/* {{{ proto public array ReflectionClassConstant::getAttributes() + Returns the attributes of this constant */ +ZEND_METHOD(reflection_class_constant, getAttributes) +{ + reflection_object *intern; + zend_class_constant *ref; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + GET_REFLECTION_OBJECT_PTR(ref); + if (ref->attributes) { + if (GC_FLAGS(ref->attributes) & IS_ARRAY_IMMUTABLE) { + RETURN_IMMUTABLE_ARR(ref->attributes); + } else { + GC_REFCOUNT(ref->attributes)++; + RETURN_ARR(ref->attributes); + } + } + RETURN_FALSE; +} +/* }}} */ + /* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */ ZEND_METHOD(reflection_class, export) @@ -4233,6 +4279,29 @@ ZEND_METHOD(reflection_class, getDocComment) } /* }}} */ +/* {{{ proto public array ReflectionClass::getAttributes() + Returns the attributes for this class */ +ZEND_METHOD(reflection_class, getAttributes) +{ + reflection_object *intern; + zend_class_entry *ce; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + GET_REFLECTION_OBJECT_PTR(ce); + if (ce->type == ZEND_USER_CLASS && ce->info.user.attributes) { + if (GC_FLAGS(ce->info.user.attributes) & IS_ARRAY_IMMUTABLE) { + RETURN_IMMUTABLE_ARR(ce->info.user.attributes); + } else { + GC_REFCOUNT(ce->info.user.attributes)++; + RETURN_ARR(ce->info.user.attributes); + } + } + RETURN_FALSE; +} +/* }}} */ + /* {{{ proto public ReflectionMethod ReflectionClass::getConstructor() Returns the class' constructor if there is one, NULL otherwise */ ZEND_METHOD(reflection_class, getConstructor) @@ -5785,6 +5854,29 @@ ZEND_METHOD(reflection_property, getDocComment) } /* }}} */ +/* {{{ proto public array ReflectionProperty::getAttributes() + Returns the attributes of this property */ +ZEND_METHOD(reflection_property, getAttributes) +{ + reflection_object *intern; + property_reference *ref; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + GET_REFLECTION_OBJECT_PTR(ref); + if (ref->prop.attributes) { + if (GC_FLAGS(ref->prop.attributes) & IS_ARRAY_IMMUTABLE) { + RETURN_IMMUTABLE_ARR(ref->prop.attributes); + } else { + GC_REFCOUNT(ref->prop.attributes)++; + RETURN_ARR(ref->prop.attributes); + } + } + RETURN_FALSE; +} +/* }}} */ + /* {{{ proto public int ReflectionProperty::setAccessible(bool visible) Sets whether non-public properties can be requested */ ZEND_METHOD(reflection_property, setAccessible) @@ -6382,6 +6474,7 @@ static const zend_function_entry reflection_function_abstract_functions[] = { ZEND_ME(reflection_function, getClosureThis, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getClosureScopeClass, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getDocComment, arginfo_reflection__void, 0) + ZEND_ME(reflection_function, getAttributes, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getEndLine, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getExtension, arginfo_reflection__void, 0) ZEND_ME(reflection_function, getExtensionName, arginfo_reflection__void, 0) @@ -6571,6 +6664,7 @@ static const zend_function_entry reflection_class_functions[] = { ZEND_ME(reflection_class, getStartLine, arginfo_reflection__void, 0) ZEND_ME(reflection_class, getEndLine, arginfo_reflection__void, 0) ZEND_ME(reflection_class, getDocComment, arginfo_reflection__void, 0) + ZEND_ME(reflection_class, getAttributes, arginfo_reflection__void, 0) ZEND_ME(reflection_class, getConstructor, arginfo_reflection__void, 0) ZEND_ME(reflection_class, hasMethod, arginfo_reflection_class_hasMethod, 0) ZEND_ME(reflection_class, getMethod, arginfo_reflection_class_getMethod, 0) @@ -6670,6 +6764,7 @@ static const zend_function_entry reflection_property_functions[] = { ZEND_ME(reflection_property, getModifiers, arginfo_reflection__void, 0) ZEND_ME(reflection_property, getDeclaringClass, arginfo_reflection__void, 0) ZEND_ME(reflection_property, getDocComment, arginfo_reflection__void, 0) + ZEND_ME(reflection_property, getAttributes, arginfo_reflection__void, 0) ZEND_ME(reflection_property, setAccessible, arginfo_reflection_property_setAccessible, 0) PHP_FE_END }; @@ -6698,6 +6793,7 @@ static const zend_function_entry reflection_class_constant_functions[] = { ZEND_ME(reflection_class_constant, getModifiers, arginfo_reflection__void, 0) ZEND_ME(reflection_class_constant, getDeclaringClass, arginfo_reflection__void, 0) ZEND_ME(reflection_class_constant, getDocComment, arginfo_reflection__void, 0) + ZEND_ME(reflection_class_constant, getAttributes, arginfo_reflection__void, 0) PHP_FE_END }; diff --git a/ext/reflection/tests/ReflectionClass_toString_001.phpt b/ext/reflection/tests/ReflectionClass_toString_001.phpt index 29d58420e375c..96dc6cf2ef48c 100644 --- a/ext/reflection/tests/ReflectionClass_toString_001.phpt +++ b/ext/reflection/tests/ReflectionClass_toString_001.phpt @@ -34,7 +34,7 @@ Class [ class ReflectionClass implements Reflector ] { Property [ public $name ] } - - Methods [52] { + - Methods [53] { Method [ final private method __clone ] { - Parameters [0] { @@ -114,6 +114,12 @@ Class [ class ReflectionClass implements Reflector ] { } } + Method [ public method getAttributes ] { + + - Parameters [0] { + } + } + Method [ public method getConstructor ] { - Parameters [0] { diff --git a/ext/standard/var.c b/ext/standard/var.c index 76d92a5fd3c68..db65191bedf51 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -75,6 +75,14 @@ static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *ke } /* }}} */ +static void php_var_dump_ast(zend_ast *ast) /* {{{ */ +{ + zend_string *str = zend_ast_export("", ast, ""); + php_printf("%s", ZSTR_VAL(str)); + zend_string_release(str); +} +/* }}} */ + PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ { HashTable *myht; @@ -182,6 +190,11 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ struc = Z_REFVAL_P(struc); goto again; break; + case IS_CONSTANT_AST: + php_printf("%sAST(", COMMON); + php_var_dump_ast(Z_ASTVAL_P(struc)); + PUTS(")\n"); + break; default: php_printf("%sUNKNOWN:0\n", COMMON); break; @@ -346,6 +359,11 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */ } struc = Z_REFVAL_P(struc); goto again; + case IS_CONSTANT_AST: + php_printf("%sAST(", COMMON); + php_var_dump_ast(Z_ASTVAL_P(struc)); + PUTS(")\n"); + break; default: php_printf("%sUNKNOWN:0\n", COMMON); break; From 03964f8f0623ae06bf1c7c6a68f022e587340265 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 21 Apr 2016 12:00:06 +0300 Subject: [PATCH 2/5] Use classes from ast-php to represent AST attributes. --- Zend/tests/attributes_001.phpt | 100 +++++++++++++++++++-- Zend/zend_ast.c | 151 ++++++++++++++++++++++++++++++++ Zend/zend_ast.h | 8 ++ Zend/zend_default_classes.c | 2 + ext/reflection/php_reflection.c | 40 +++------ ext/standard/var.c | 18 ---- 6 files changed, 265 insertions(+), 54 deletions(-) diff --git a/Zend/tests/attributes_001.phpt b/Zend/tests/attributes_001.phpt index 0bac9f2f57189..3b6a374412182 100644 --- a/Zend/tests/attributes_001.phpt +++ b/Zend/tests/attributes_001.phpt @@ -68,17 +68,101 @@ array(3) { } } array(4) { - ["a1"]=> + [0]=> bool(true) - ["a2"]=> - AST(1 + 'a') - ["a3"]=> + [1]=> + object(ast\Node)#4 (4) { + ["kind"]=> + int(520) + ["flags"]=> + int(1) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(1) + [1]=> + string(1) "a" + } + } + [2]=> array(2) { [0]=> - AST(1 + 'b') + object(ast\Node)#5 (4) { + ["kind"]=> + int(520) + ["flags"]=> + int(1) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(1) + [1]=> + string(1) "b" + } + } [1]=> - AST(2 + 'c') + object(ast\Node)#6 (4) { + ["kind"]=> + int(520) + ["flags"]=> + int(1) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(2) + [1]=> + string(1) "c" + } + } + } + [3]=> + object(ast\Node)#7 (4) { + ["kind"]=> + int(130) + ["flags"]=> + int(0) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + object(ast\Node)#8 (4) { + ["kind"]=> + int(525) + ["flags"]=> + int(0) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(1) + [1]=> + string(1) "a" + } + } + [1]=> + object(ast\Node)#9 (4) { + ["kind"]=> + int(525) + ["flags"]=> + int(0) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(2) + [1]=> + string(1) "b" + } + } + } } - ["a4"]=> - AST(['a' => 1, 'b' => 2]) } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index e8f020171c003..f5149f38e760e 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1720,3 +1720,154 @@ ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const c smart_str_0(&str); return str.s; } + +ZEND_API zend_class_entry *zend_ast_node_ce = NULL; +ZEND_API zend_class_entry *zend_ast_decl_ce = NULL; + +ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes) +{ + zval *val, tmp; + HashTable *ht, *ht2, *res_ht; + int convert_ast = 0; + + ZEND_HASH_FOREACH_VAL(attributes, val) { + if (Z_TYPE_P(val) == IS_CONSTANT_AST) { + convert_ast = 1; + break; + } else if (Z_TYPE_P(val) == IS_ARRAY) { + ht = Z_ARR_P(val); + ZEND_HASH_FOREACH_VAL(ht, val) { + if (Z_TYPE_P(val) == IS_CONSTANT_AST) { + convert_ast = 1; + break; + } + } ZEND_HASH_FOREACH_END(); + if (convert_ast) { + break; + } + } + } ZEND_HASH_FOREACH_END(); + + if (convert_ast) { + array_init_size(ret, zend_hash_num_elements(attributes)); + res_ht = Z_ARR_P(ret); + ZEND_HASH_FOREACH_VAL(attributes, val) { + if (Z_TYPE_P(val) == IS_CONSTANT_AST) { + zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val)); + zend_hash_next_index_insert_new(res_ht, &tmp); + } else if (Z_TYPE_P(val) == IS_ARRAY) { + ht = Z_ARR_P(val); + array_init_size(&tmp, zend_hash_num_elements(ht)); + val = zend_hash_next_index_insert_new(res_ht, &tmp); + ht2 = Z_ARR_P(val); + ZEND_HASH_FOREACH_VAL(ht, val) { + if (Z_TYPE_P(val) == IS_CONSTANT_AST) { + zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val)); + zend_hash_next_index_insert_new(ht2, &tmp); + } else { + if (Z_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + zend_hash_next_index_insert_new(ht2, val); + } + } ZEND_HASH_FOREACH_END(); + } else { + if (Z_REFCOUNTED_P(val)) { + Z_ADDREF_P(val); + } + zend_hash_next_index_insert_new(res_ht, val); + } + } ZEND_HASH_FOREACH_END(); + } else if (GC_FLAGS(attributes) & IS_ARRAY_IMMUTABLE) { + ZVAL_IMMUTABLE_ARR(ret, attributes); + } else { + GC_REFCOUNT(attributes)++; + ZVAL_ARR(ret, attributes); + } +} + +ZEND_API void zend_ast_convert_to_object(zval *ret, zend_ast *ast) +{ + uint32_t i, children; + zend_object *obj; + HashTable *ht; + zval tmp; + + if (ast->kind == ZEND_AST_ZVAL) { + ZVAL_COPY(ret, zend_ast_get_zval(ast)); + } else if ((ast->kind >> ZEND_AST_SPECIAL_SHIFT) & 1) { + zend_ast_decl *decl = (zend_ast_decl *)ast; + + ZEND_ASSERT(ast->kind != ZEND_AST_ZNODE); + + object_init_ex(ret, zend_ast_decl_ce); + obj = Z_OBJ_P(ret); + ZVAL_LONG(OBJ_PROP_NUM(obj, 0), decl->kind); + ZVAL_LONG(OBJ_PROP_NUM(obj, 1), decl->attr); + ZVAL_LONG(OBJ_PROP_NUM(obj, 2), decl->start_lineno); + children = 4; + array_init_size(OBJ_PROP_NUM(obj, 3), children); + ht = Z_ARR_P(OBJ_PROP_NUM(obj, 3)); + for (i = 0; i < children; i++) { + zend_ast_convert_to_object(&tmp, decl->child[i]); + zend_hash_index_add_new(ht, i, &tmp); + } + ZVAL_LONG(OBJ_PROP_NUM(obj, 4), decl->end_lineno); + if (decl->name) { + ZVAL_STR_COPY(OBJ_PROP_NUM(obj, 5), decl->name); + } + if (decl->doc_comment) { + ZVAL_STR_COPY(OBJ_PROP_NUM(obj, 6), decl->doc_comment); + } + if (decl->attributes) { + zend_ast_convert_attributes(OBJ_PROP_NUM(obj, 7), decl->attributes); + } + } else if (zend_ast_is_list(ast)) { + zend_ast_list *list = zend_ast_get_list(ast); + + object_init_ex(ret, zend_ast_node_ce); + obj = Z_OBJ_P(ret); + ZVAL_LONG(OBJ_PROP_NUM(obj, 0), list->kind); + ZVAL_LONG(OBJ_PROP_NUM(obj, 1), list->attr); + ZVAL_LONG(OBJ_PROP_NUM(obj, 2), list->lineno); + children = list->children; + array_init_size(OBJ_PROP_NUM(obj, 3), children); + ht = Z_ARR_P(OBJ_PROP_NUM(obj, 3)); + for (i = 0; i < children; i++) { + zend_ast_convert_to_object(&tmp, list->child[i]); + zend_hash_index_add_new(ht, i, &tmp); + } + } else { + object_init_ex(ret, zend_ast_node_ce); + obj = Z_OBJ_P(ret); + ZVAL_LONG(OBJ_PROP_NUM(obj, 0), ast->kind); + ZVAL_LONG(OBJ_PROP_NUM(obj, 1), ast->attr); + ZVAL_LONG(OBJ_PROP_NUM(obj, 2), ast->lineno); + children = zend_ast_get_num_children(ast); + array_init_size(OBJ_PROP_NUM(obj, 3), children); + ht = Z_ARR_P(OBJ_PROP_NUM(obj, 3)); + for (i = 0; i < children; i++) { + zend_ast_convert_to_object(&tmp, ast->child[i]); + zend_hash_index_add_new(ht, i, &tmp); + } + } +} + +void zend_register_ast_classes(void) +{ + zend_class_entry tmp_ce; + + INIT_CLASS_ENTRY(tmp_ce, "ast\\Node", NULL); + zend_ast_node_ce = zend_register_internal_class(&tmp_ce); + zend_declare_property_null(zend_ast_node_ce, "kind", sizeof("kind")-1, ZEND_ACC_PUBLIC); + zend_declare_property_null(zend_ast_node_ce, "flags", sizeof("flags")-1, ZEND_ACC_PUBLIC); + zend_declare_property_null(zend_ast_node_ce, "lineno", sizeof("lineno")-1, ZEND_ACC_PUBLIC); + zend_declare_property_null(zend_ast_node_ce, "children", sizeof("children")-1, ZEND_ACC_PUBLIC); + + INIT_CLASS_ENTRY(tmp_ce, "ast\\Node\\Decl", NULL); + zend_ast_decl_ce = zend_register_internal_class_ex(&tmp_ce, zend_ast_node_ce); + zend_declare_property_null(zend_ast_decl_ce, "endLineno", sizeof("endLineno")-1, ZEND_ACC_PUBLIC); + zend_declare_property_null(zend_ast_decl_ce, "name", sizeof("name")-1, ZEND_ACC_PUBLIC); + zend_declare_property_null(zend_ast_decl_ce, "docComment", sizeof("docComment")-1, ZEND_ACC_PUBLIC); + zend_declare_property_null(zend_ast_decl_ce, "attributes", sizeof("attributes")-1, ZEND_ACC_PUBLIC); +} diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 49128bf3a4cce..9fd2a298d4738 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -281,4 +281,12 @@ static zend_always_inline zend_ast *zend_ast_create_cast(uint32_t type, zend_ast return zend_ast_create_ex(ZEND_AST_CAST, type, op0); } +extern ZEND_API zend_class_entry *zend_ast_node_ce; +extern ZEND_API zend_class_entry *zend_ast_decl_ce; + +void zend_register_ast_classes(void); + +ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes); +ZEND_API void zend_ast_convert_to_object(zval *ret, zend_ast *ast); + #endif diff --git a/Zend/zend_default_classes.c b/Zend/zend_default_classes.c index 638d337ac17de..7f1dfacf31811 100644 --- a/Zend/zend_default_classes.c +++ b/Zend/zend_default_classes.c @@ -26,6 +26,7 @@ #include "zend_exceptions.h" #include "zend_closures.h" #include "zend_generators.h" +#include "zend_ast.h" ZEND_API void zend_register_default_classes(void) @@ -35,6 +36,7 @@ ZEND_API void zend_register_default_classes(void) zend_register_iterator_wrapper(); zend_register_closure_ce(); zend_register_generator_ce(); + zend_register_ast_classes(); } /* diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 9db607d33eeee..0195395d77f0d 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1922,14 +1922,10 @@ ZEND_METHOD(reflection_function, getAttributes) } GET_REFLECTION_OBJECT_PTR(fptr); if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.attributes) { - if (GC_FLAGS(fptr->op_array.attributes) & IS_ARRAY_IMMUTABLE) { - RETURN_IMMUTABLE_ARR(fptr->op_array.attributes); - } else { - GC_REFCOUNT(fptr->op_array.attributes)++; - RETURN_ARR(fptr->op_array.attributes); - } + zend_ast_convert_attributes(return_value, fptr->op_array.attributes); + } else { + RETVAL_FALSE; } - RETURN_FALSE; } /* }}} */ @@ -3909,14 +3905,10 @@ ZEND_METHOD(reflection_class_constant, getAttributes) } GET_REFLECTION_OBJECT_PTR(ref); if (ref->attributes) { - if (GC_FLAGS(ref->attributes) & IS_ARRAY_IMMUTABLE) { - RETURN_IMMUTABLE_ARR(ref->attributes); - } else { - GC_REFCOUNT(ref->attributes)++; - RETURN_ARR(ref->attributes); - } + zend_ast_convert_attributes(return_value, ref->attributes); + } else { + RETVAL_FALSE; } - RETURN_FALSE; } /* }}} */ @@ -4291,14 +4283,10 @@ ZEND_METHOD(reflection_class, getAttributes) } GET_REFLECTION_OBJECT_PTR(ce); if (ce->type == ZEND_USER_CLASS && ce->info.user.attributes) { - if (GC_FLAGS(ce->info.user.attributes) & IS_ARRAY_IMMUTABLE) { - RETURN_IMMUTABLE_ARR(ce->info.user.attributes); - } else { - GC_REFCOUNT(ce->info.user.attributes)++; - RETURN_ARR(ce->info.user.attributes); - } + zend_ast_convert_attributes(return_value, ce->info.user.attributes); + } else { + RETVAL_FALSE; } - RETURN_FALSE; } /* }}} */ @@ -5866,14 +5854,10 @@ ZEND_METHOD(reflection_property, getAttributes) } GET_REFLECTION_OBJECT_PTR(ref); if (ref->prop.attributes) { - if (GC_FLAGS(ref->prop.attributes) & IS_ARRAY_IMMUTABLE) { - RETURN_IMMUTABLE_ARR(ref->prop.attributes); - } else { - GC_REFCOUNT(ref->prop.attributes)++; - RETURN_ARR(ref->prop.attributes); - } + zend_ast_convert_attributes(return_value, ref->prop.attributes); + } else { + RETVAL_FALSE; } - RETURN_FALSE; } /* }}} */ diff --git a/ext/standard/var.c b/ext/standard/var.c index db65191bedf51..76d92a5fd3c68 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -75,14 +75,6 @@ static void php_object_property_dump(zval *zv, zend_ulong index, zend_string *ke } /* }}} */ -static void php_var_dump_ast(zend_ast *ast) /* {{{ */ -{ - zend_string *str = zend_ast_export("", ast, ""); - php_printf("%s", ZSTR_VAL(str)); - zend_string_release(str); -} -/* }}} */ - PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ { HashTable *myht; @@ -190,11 +182,6 @@ PHPAPI void php_var_dump(zval *struc, int level) /* {{{ */ struc = Z_REFVAL_P(struc); goto again; break; - case IS_CONSTANT_AST: - php_printf("%sAST(", COMMON); - php_var_dump_ast(Z_ASTVAL_P(struc)); - PUTS(")\n"); - break; default: php_printf("%sUNKNOWN:0\n", COMMON); break; @@ -359,11 +346,6 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */ } struc = Z_REFVAL_P(struc); goto again; - case IS_CONSTANT_AST: - php_printf("%sAST(", COMMON); - php_var_dump_ast(Z_ASTVAL_P(struc)); - PUTS(")\n"); - break; default: php_printf("%sUNKNOWN:0\n", COMMON); break; From 8dce8092baa66659f70f99ff22d47542673d0ec0 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 21 Apr 2016 13:03:19 +0300 Subject: [PATCH 3/5] Fixed missed attribute names --- Zend/tests/attributes_001.phpt | 8 ++++---- Zend/zend_ast.c | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Zend/tests/attributes_001.phpt b/Zend/tests/attributes_001.phpt index 3b6a374412182..46e950e4e2828 100644 --- a/Zend/tests/attributes_001.phpt +++ b/Zend/tests/attributes_001.phpt @@ -68,9 +68,9 @@ array(3) { } } array(4) { - [0]=> + ["a1"]=> bool(true) - [1]=> + ["a2"]=> object(ast\Node)#4 (4) { ["kind"]=> int(520) @@ -86,7 +86,7 @@ array(4) { string(1) "a" } } - [2]=> + ["a3"]=> array(2) { [0]=> object(ast\Node)#5 (4) { @@ -121,7 +121,7 @@ array(4) { } } } - [3]=> + ["a4"]=> object(ast\Node)#7 (4) { ["kind"]=> int(130) diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index f5149f38e760e..a79952e4827c9 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1728,6 +1728,7 @@ ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes) { zval *val, tmp; HashTable *ht, *ht2, *res_ht; + zend_string *key; int convert_ast = 0; ZEND_HASH_FOREACH_VAL(attributes, val) { @@ -1751,14 +1752,14 @@ ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes) if (convert_ast) { array_init_size(ret, zend_hash_num_elements(attributes)); res_ht = Z_ARR_P(ret); - ZEND_HASH_FOREACH_VAL(attributes, val) { + ZEND_HASH_FOREACH_STR_KEY_VAL(attributes, key, val) { if (Z_TYPE_P(val) == IS_CONSTANT_AST) { zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val)); - zend_hash_next_index_insert_new(res_ht, &tmp); + zend_hash_add_new(res_ht, key, &tmp); } else if (Z_TYPE_P(val) == IS_ARRAY) { ht = Z_ARR_P(val); array_init_size(&tmp, zend_hash_num_elements(ht)); - val = zend_hash_next_index_insert_new(res_ht, &tmp); + val = zend_hash_add_new(res_ht, key, &tmp); ht2 = Z_ARR_P(val); ZEND_HASH_FOREACH_VAL(ht, val) { if (Z_TYPE_P(val) == IS_CONSTANT_AST) { @@ -1775,7 +1776,7 @@ ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes) if (Z_REFCOUNTED_P(val)) { Z_ADDREF_P(val); } - zend_hash_next_index_insert_new(res_ht, val); + zend_hash_add_new(res_ht, key, val); } } ZEND_HASH_FOREACH_END(); } else if (GC_FLAGS(attributes) & IS_ARRAY_IMMUTABLE) { From 4f6f5f55733beef7859981a96319ba14ea439fbf Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 25 Apr 2016 16:28:41 +0300 Subject: [PATCH 4/5] - allowed attribute names with namespaces (e.g. <>) - changed Reflection*::getAttributes() to always return arrays (empty array for entity without attributes) - changed Reflection*::getAttributes() to always return arrays for attribute values (empty array for attributes without value, array with single element for attributes with single value, etc) - disabled attribute names started with "__" prefix (they are reserved for special purpose) --- Zend/tests/attributes_001.phpt | 149 ++++++++++++++++++++------------ Zend/tests/attributes_002.phpt | 39 +++++++++ Zend/zend_compile.c | 32 +++++++ Zend/zend_language_parser.y | 8 +- ext/reflection/php_reflection.c | 8 +- 5 files changed, 171 insertions(+), 65 deletions(-) create mode 100644 Zend/tests/attributes_002.phpt diff --git a/Zend/tests/attributes_001.phpt b/Zend/tests/attributes_001.phpt index 46e950e4e2828..1bf3ca9d91cbc 100644 --- a/Zend/tests/attributes_001.phpt +++ b/Zend/tests/attributes_001.phpt @@ -2,6 +2,12 @@ Basic attributes usage --FILE-- getAttributes()); + // Function attributes <> function foo() { @@ -36,29 +42,46 @@ var_dump($r->getAttributes()); function f2() {} $r = new ReflectionFunction("f2"); var_dump($r->getAttributes()); + +// Attributes with namespaces +<> +function f4() { +} +$r = new ReflectionFunction("f4"); +var_dump($r->getAttributes()); ?> --EXPECT-- +array(0) { +} array(1) { ["TestFunction"]=> - bool(true) + array(0) { + } } array(1) { ["TestClass"]=> - bool(true) + array(0) { + } } array(1) { ["TestConst"]=> - bool(true) + array(0) { + } } array(1) { ["TestProp"]=> - bool(true) + array(0) { + } } array(3) { ["a1"]=> - bool(true) + array(0) { + } ["a2"]=> - int(1) + array(1) { + [0]=> + int(1) + } ["a3"]=> array(2) { [0]=> @@ -69,21 +92,25 @@ array(3) { } array(4) { ["a1"]=> - bool(true) + array(0) { + } ["a2"]=> - object(ast\Node)#4 (4) { - ["kind"]=> - int(520) - ["flags"]=> - int(1) - ["lineno"]=> - int(0) - ["children"]=> - array(2) { - [0]=> + array(1) { + [0]=> + object(ast\Node)#4 (4) { + ["kind"]=> + int(520) + ["flags"]=> int(1) - [1]=> - string(1) "a" + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(1) + [1]=> + string(1) "a" + } } } ["a3"]=> @@ -122,47 +149,55 @@ array(4) { } } ["a4"]=> - object(ast\Node)#7 (4) { - ["kind"]=> - int(130) - ["flags"]=> - int(0) - ["lineno"]=> - int(0) - ["children"]=> - array(2) { - [0]=> - object(ast\Node)#8 (4) { - ["kind"]=> - int(525) - ["flags"]=> - int(0) - ["lineno"]=> - int(0) - ["children"]=> - array(2) { - [0]=> - int(1) - [1]=> - string(1) "a" + array(1) { + [0]=> + object(ast\Node)#7 (4) { + ["kind"]=> + int(130) + ["flags"]=> + int(0) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + object(ast\Node)#8 (4) { + ["kind"]=> + int(525) + ["flags"]=> + int(0) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(1) + [1]=> + string(1) "a" + } } - } - [1]=> - object(ast\Node)#9 (4) { - ["kind"]=> - int(525) - ["flags"]=> - int(0) - ["lineno"]=> - int(0) - ["children"]=> - array(2) { - [0]=> - int(2) - [1]=> - string(1) "b" + [1]=> + object(ast\Node)#9 (4) { + ["kind"]=> + int(525) + ["flags"]=> + int(0) + ["lineno"]=> + int(0) + ["children"]=> + array(2) { + [0]=> + int(2) + [1]=> + string(1) "b" + } } } } } } +array(1) { + ["Foo\Bar"]=> + array(0) { + } +} diff --git a/Zend/tests/attributes_002.phpt b/Zend/tests/attributes_002.phpt new file mode 100644 index 0000000000000..83d64bf0b70f1 --- /dev/null +++ b/Zend/tests/attributes_002.phpt @@ -0,0 +1,39 @@ +--TEST-- +Doctrine-like attributes usage +--FILE-- +name = $name; + } + } + + function GetClassAttributes($class_name) { + $reflClass = new \ReflectionClass($class_name); + $attrs = $reflClass->getAttributes(); + foreach ($attrs as $name => &$values) { + $name = "Doctrine\\" . $name; + $values = new $name(...$values); + } + return $attrs; + } +} + +namespace { + <> + class User {} + + var_dump(Doctrine\ORM\GetClassAttributes("User")); +} +?> +--EXPECT-- +array(1) { + ["ORM\Entity"]=> + object(Doctrine\ORM\Entity)#2 (1) { + ["name":"Doctrine\ORM\Entity":private]=> + string(4) "user" + } +} diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 388a76be9c230..e43f9ec6d5fa2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1826,10 +1826,16 @@ void zend_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */ zval *val, tmp; zend_string *key = zend_ast_get_str(name); +#if 1 /* SPECIAL_ATTRIBUTE */ + if (ZSTR_LEN(key) >= 2 && ZSTR_VAL(key)[0] == '_' && ZSTR_VAL(key)[1] == '_') { + zend_error_noreturn(E_COMPILE_ERROR, "Unknown special attribute %s", ZSTR_VAL(key)); + } +#endif if (!CG(attributes)) { ALLOC_HASHTABLE(CG(attributes)); zend_hash_init(CG(attributes), 8, NULL, ZVAL_PTR_DTOR, 0); } +#if 0 /* ATTRIBUTE_VALUES_ARRAYS */ if (value) { if (value->kind == ZEND_AST_ZVAL) { val = zend_ast_get_zval(value); @@ -1846,6 +1852,32 @@ void zend_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */ if (!zend_hash_add(CG(attributes), key, val)) { zend_error_noreturn(E_COMPILE_ERROR, "Redeclared attribute %s", ZSTR_VAL(key)); } +#else + ZVAL_NULL(&tmp); + val = zend_hash_add(CG(attributes), key, &tmp); + if (!val) { + zend_error_noreturn(E_COMPILE_ERROR, "Redeclared attribute %s", ZSTR_VAL(key)); + } + if (value) { + if (value->kind == ZEND_AST_ZVAL) { + zval *zv = zend_ast_get_zval(value); + + if (Z_TYPE_P(zv) == IS_ARRAY) { + ZVAL_COPY_VALUE(val, zv); + } else { + array_init(val); + zend_hash_next_index_insert_new(Z_ARRVAL_P(val), zv); + } + } else { + ZVAL_NEW_AST(&tmp, zend_ast_copy(value)); + zend_ast_destroy(value); + array_init(val); + zend_hash_next_index_insert_new(Z_ARRVAL_P(val), &tmp); + } + } else { + array_init(val); + } +#endif zend_string_release(key); } /* }}} */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 947ce66032aa6..225d22a129bd0 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -315,10 +315,10 @@ attribute_values: | attribute_values ',' expr { $$ = zend_add_attribute_value($1, $3); } attribute_list: - T_STRING { zend_add_attribute($1, NULL); } - | T_STRING '(' attribute_values ')' { zend_add_attribute($1, $3); } - | attribute_list ',' T_STRING { zend_add_attribute($3, NULL); } - | attribute_list ',' T_STRING '(' attribute_values ')' { zend_add_attribute($3, $5); } + namespace_name { zend_add_attribute($1, NULL); } + | namespace_name '(' attribute_values ')' { zend_add_attribute($1, $3); } + | attribute_list ',' namespace_name { zend_add_attribute($3, NULL); } + | attribute_list ',' namespace_name '(' attribute_values ')' { zend_add_attribute($3, $5); } ; attribute: diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 0195395d77f0d..2c86c9ca7c485 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1924,7 +1924,7 @@ ZEND_METHOD(reflection_function, getAttributes) if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.attributes) { zend_ast_convert_attributes(return_value, fptr->op_array.attributes); } else { - RETVAL_FALSE; + array_init(return_value); } } /* }}} */ @@ -3907,7 +3907,7 @@ ZEND_METHOD(reflection_class_constant, getAttributes) if (ref->attributes) { zend_ast_convert_attributes(return_value, ref->attributes); } else { - RETVAL_FALSE; + array_init(return_value); } } /* }}} */ @@ -4285,7 +4285,7 @@ ZEND_METHOD(reflection_class, getAttributes) if (ce->type == ZEND_USER_CLASS && ce->info.user.attributes) { zend_ast_convert_attributes(return_value, ce->info.user.attributes); } else { - RETVAL_FALSE; + array_init(return_value); } } /* }}} */ @@ -5856,7 +5856,7 @@ ZEND_METHOD(reflection_property, getAttributes) if (ref->prop.attributes) { zend_ast_convert_attributes(return_value, ref->prop.attributes); } else { - RETVAL_FALSE; + array_init(return_value); } } /* }}} */ From ffe5edd685ad373d2799fdfe98db6fbbeafe62fa Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 10 May 2016 13:29:47 +0300 Subject: [PATCH 5/5] Don't print uninitialized line numbers --- Zend/tests/attributes_001.phpt | 12 ++++++------ Zend/zend_ast.c | 8 ++++++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Zend/tests/attributes_001.phpt b/Zend/tests/attributes_001.phpt index 1bf3ca9d91cbc..e3d0236b6368c 100644 --- a/Zend/tests/attributes_001.phpt +++ b/Zend/tests/attributes_001.phpt @@ -103,7 +103,7 @@ array(4) { ["flags"]=> int(1) ["lineno"]=> - int(0) + NULL ["children"]=> array(2) { [0]=> @@ -122,7 +122,7 @@ array(4) { ["flags"]=> int(1) ["lineno"]=> - int(0) + NULL ["children"]=> array(2) { [0]=> @@ -138,7 +138,7 @@ array(4) { ["flags"]=> int(1) ["lineno"]=> - int(0) + NULL ["children"]=> array(2) { [0]=> @@ -157,7 +157,7 @@ array(4) { ["flags"]=> int(0) ["lineno"]=> - int(0) + NULL ["children"]=> array(2) { [0]=> @@ -167,7 +167,7 @@ array(4) { ["flags"]=> int(0) ["lineno"]=> - int(0) + NULL ["children"]=> array(2) { [0]=> @@ -183,7 +183,7 @@ array(4) { ["flags"]=> int(0) ["lineno"]=> - int(0) + NULL ["children"]=> array(2) { [0]=> diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index 50e28427a0227..5b086883e4449 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -1821,7 +1821,9 @@ ZEND_API void zend_ast_convert_to_object(zval *ret, zend_ast *ast) obj = Z_OBJ_P(ret); ZVAL_LONG(OBJ_PROP_NUM(obj, 0), list->kind); ZVAL_LONG(OBJ_PROP_NUM(obj, 1), list->attr); - ZVAL_LONG(OBJ_PROP_NUM(obj, 2), list->lineno); + /* PHP parser doesn't capture positions of all AST nodes */ + /* ZVAL_LONG(OBJ_PROP_NUM(obj, 2), list->lineno); */ + ZVAL_NULL(OBJ_PROP_NUM(obj, 2)); children = list->children; array_init_size(OBJ_PROP_NUM(obj, 3), children); ht = Z_ARR_P(OBJ_PROP_NUM(obj, 3)); @@ -1834,7 +1836,9 @@ ZEND_API void zend_ast_convert_to_object(zval *ret, zend_ast *ast) obj = Z_OBJ_P(ret); ZVAL_LONG(OBJ_PROP_NUM(obj, 0), ast->kind); ZVAL_LONG(OBJ_PROP_NUM(obj, 1), ast->attr); - ZVAL_LONG(OBJ_PROP_NUM(obj, 2), ast->lineno); + /* PHP parser doesn't capture positions of all AST nodes */ + /* ZVAL_LONG(OBJ_PROP_NUM(obj, 2), ast->lineno); */ + ZVAL_NULL(OBJ_PROP_NUM(obj, 2)); children = zend_ast_get_num_children(ast); array_init_size(OBJ_PROP_NUM(obj, 3), children); ht = Z_ARR_P(OBJ_PROP_NUM(obj, 3));