summaryrefslogtreecommitdiff
path: root/Zend/zend_language_scanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_language_scanner.l')
-rw-r--r--Zend/zend_language_scanner.l171
1 files changed, 111 insertions, 60 deletions
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index 7e60f5cf05..4fb4202264 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -297,30 +297,25 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state)
RESET_DOC_COMMENT();
}
-ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
+ZEND_API zend_result zend_lex_tstring(zval *zv, unsigned char *ident)
{
- zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
- /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
- file_handle->opened_path = NULL;
- if (file_handle->free_filename) {
- file_handle->filename = NULL;
+ unsigned char *end = ident;
+ while ((*end >= 'a' && *end <= 'z') || (*end >= 'A' && *end <= 'Z') || *end == '_') {
+ end++;
}
-}
-ZEND_API zend_result zend_lex_tstring(zval *zv, zend_lexer_ident_ref ident_ref)
-{
- char *ident = (char *) SCNG(yy_start) + ident_ref.offset;
- size_t length = ident_ref.len;
- if (length == sizeof("<?=")-1 && memcmp(ident, "<?=", sizeof("<?=")-1) == 0) {
+ size_t length = end - ident;
+ if (length == 0) {
+ ZEND_ASSERT(ident[0] == '<' && ident[1] == '?' && ident[2] == '=');
zend_throw_exception(zend_ce_parse_error, "Cannot use \"<?=\" as an identifier", 0);
return FAILURE;
}
if (SCNG(on_event)) {
- SCNG(on_event)(ON_FEEDBACK, T_STRING, 0, ident, length, SCNG(on_event_context));
+ SCNG(on_event)(ON_FEEDBACK, T_STRING, 0, (char *) ident, length, SCNG(on_event_context));
}
- ZVAL_STRINGL(zv, ident, length);
+ ZVAL_STRINGL(zv, (char *) ident, length);
return SUCCESS;
}
@@ -537,17 +532,13 @@ ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle)
if (zend_stream_fixup(file_handle, &buf, &size) == FAILURE) {
/* Still add it to open_files to make destroy_file_handle work */
zend_llist_add_element(&CG(open_files), file_handle);
+ file_handle->in_list = 1;
return FAILURE;
}
ZEND_ASSERT(!EG(exception) && "stream_fixup() should have failed");
zend_llist_add_element(&CG(open_files), file_handle);
- if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) {
- zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files));
- size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle;
- fh->handle.stream.handle = (void*)(((char*)fh) + diff);
- file_handle->handle.stream.handle = fh->handle.stream.handle;
- }
+ file_handle->in_list = 1;
/* Reset the scanner for scanning the new file */
SCNG(yy_in) = file_handle;
@@ -585,7 +576,7 @@ ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle)
if (file_handle->opened_path) {
compiled_filename = zend_string_copy(file_handle->opened_path);
} else {
- compiled_filename = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
+ compiled_filename = zend_string_copy(file_handle->filename);
}
zend_set_compiled_filename(compiled_filename);
@@ -601,7 +592,7 @@ END_EXTERN_C()
static zend_op_array *zend_compile(int type)
{
zend_op_array *op_array = NULL;
- zend_bool original_in_compilation = CG(in_compilation);
+ bool original_in_compilation = CG(in_compilation);
CG(in_compilation) = 1;
CG(ast) = NULL;
@@ -631,6 +622,7 @@ static zend_op_array *zend_compile(int type)
zend_emit_final_return(type == ZEND_USER_FUNCTION);
op_array->line_start = 1;
op_array->line_end = last_lineno;
+ zend_init_static_variables_map_ptr(op_array);
pass_two(op_array);
zend_oparray_context_end(&original_oparray_context);
zend_file_context_end(&original_file_context);
@@ -655,9 +647,9 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
if (open_file_for_scanning(file_handle)==FAILURE) {
if (!EG(exception)) {
if (type==ZEND_REQUIRE) {
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, ZSTR_VAL(file_handle->filename));
} else {
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, ZSTR_VAL(file_handle->filename));
}
}
} else {
@@ -669,9 +661,9 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
}
ZEND_API zend_ast *zend_compile_string_to_ast(
- zend_string *code, zend_arena **ast_arena, const char *filename) {
+ zend_string *code, zend_arena **ast_arena, zend_string *filename) {
zval code_zv;
- zend_bool original_in_compilation;
+ bool original_in_compilation;
zend_lex_state original_lex_state;
zend_ast *ast;
@@ -715,7 +707,7 @@ zend_op_array *compile_filename(int type, zval *filename)
ZVAL_STR(&tmp, zval_get_string(filename));
filename = &tmp;
}
- zend_stream_init_filename(&file_handle, Z_STRVAL_P(filename));
+ zend_stream_init_filename_ex(&file_handle, Z_STR_P(filename));
retval = zend_compile_file(&file_handle, type);
if (retval && file_handle.handle.stream.handle) {
@@ -737,11 +729,10 @@ zend_op_array *compile_filename(int type, zval *filename)
return retval;
}
-ZEND_API void zend_prepare_string_for_scanning(zval *str, const char *filename)
+ZEND_API void zend_prepare_string_for_scanning(zval *str, zend_string *filename)
{
char *buf;
size_t size, old_len;
- zend_string *new_compiled_filename;
/* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */
old_len = Z_STRLEN_P(str);
@@ -773,10 +764,7 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, const char *filename)
}
yy_scan_buffer(buf, size);
-
- new_compiled_filename = zend_string_init(filename, strlen(filename), 0);
- zend_set_compiled_filename(new_compiled_filename);
- zend_string_release_ex(new_compiled_filename, 0);
+ zend_set_compiled_filename(filename);
CG(zend_lineno) = 1;
CG(increment_lineno) = 0;
RESET_DOC_COMMENT();
@@ -809,6 +797,7 @@ zend_op_array *compile_string(zend_string *source_string, const char *filename)
zend_lex_state original_lex_state;
zend_op_array *op_array = NULL;
zval tmp;
+ zend_string *filename_str;
if (ZSTR_LEN(source_string) == 0) {
return NULL;
@@ -817,7 +806,9 @@ zend_op_array *compile_string(zend_string *source_string, const char *filename)
ZVAL_STR_COPY(&tmp, source_string);
zend_save_lexical_state(&original_lex_state);
- zend_prepare_string_for_scanning(&tmp, filename);
+ filename_str = zend_string_init(filename, strlen(filename), 0);
+ zend_prepare_string_for_scanning(&tmp, filename_str);
+ zend_string_release(filename_str);
BEGIN(ST_IN_SCRIPTING);
op_array = zend_compile(ZEND_EVAL_CODE);
@@ -838,6 +829,7 @@ zend_result highlight_file(const char *filename, zend_syntax_highlighter_ini *sy
zend_save_lexical_state(&original_lex_state);
if (open_file_for_scanning(&file_handle)==FAILURE) {
zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename);
+ zend_destroy_file_handle(&file_handle);
zend_restore_lexical_state(&original_lex_state);
return FAILURE;
}
@@ -851,17 +843,15 @@ zend_result highlight_file(const char *filename, zend_syntax_highlighter_ini *sy
return SUCCESS;
}
-void highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, const char *str_name)
+void highlight_string(zend_string *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, const char *filename)
{
zend_lex_state original_lex_state;
- zval tmp;
-
- if (UNEXPECTED(Z_TYPE_P(str) != IS_STRING)) {
- ZVAL_STR(&tmp, zval_get_string_func(str));
- str = &tmp;
- }
+ zval str_zv;
+ zend_string *filename_str = zend_string_init(filename, strlen(filename), 0);
+ ZVAL_STR_COPY(&str_zv, str);
zend_save_lexical_state(&original_lex_state);
- zend_prepare_string_for_scanning(str, str_name);
+ zend_prepare_string_for_scanning(&str_zv, filename_str);
+ zend_string_release(filename_str);
BEGIN(INITIAL);
zend_highlight(syntax_highlighter_ini);
if (SCNG(script_filtered)) {
@@ -869,9 +859,7 @@ void highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter
SCNG(script_filtered) = NULL;
}
zend_restore_lexical_state(&original_lex_state);
- if (UNEXPECTED(str == &tmp)) {
- zval_ptr_dtor(&tmp);
- }
+ zval_ptr_dtor(&str_zv);
}
ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding)
@@ -1023,7 +1011,7 @@ static zend_result zend_scan_escape_string(zval *zendlval, char *str, int len, c
/* cache where we started so we can parse after validating */
char *start = s + 1;
size_t len = 0;
- zend_bool valid = 1;
+ bool valid = 1;
unsigned long codepoint;
if (*start != '{') {
@@ -1163,9 +1151,9 @@ static const char *next_newline(const char *str, const char *end, size_t *newlin
return NULL;
}
-static zend_bool strip_multiline_string_indentation(
- zval *zendlval, int indentation, zend_bool using_spaces,
- zend_bool newline_at_start, zend_bool newline_at_end)
+static bool strip_multiline_string_indentation(
+ zval *zendlval, int indentation, bool using_spaces,
+ bool newline_at_start, bool newline_at_end)
{
const char *str = Z_STRVAL_P(zendlval), *end = str + Z_STRLEN_P(zendlval);
char *copy = Z_STRVAL_P(zendlval);
@@ -1372,6 +1360,7 @@ DNUM ({LNUM}?"."{LNUM})|({LNUM}"."{LNUM}?)
EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})
HNUM "0x"[0-9a-fA-F]+(_[0-9a-fA-F]+)*
BNUM "0b"[01]+(_[01]+)*
+ONUM "0o"[0-7]+(_[0-7]+)*
LABEL [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*
WHITESPACE [ \n\r\t]+
TABS_AND_SPACES [ \t]*
@@ -1549,6 +1538,19 @@ NEWLINE ("\r"|"\n"|"\r\n")
RETURN_TOKEN_WITH_IDENT(T_TRAIT);
}
+/*
+ * The enum keyword must be followed by whitespace and another identifier.
+ * This avoids the BC break of using enum in classes, namespaces, functions and constants.
+ */
+<ST_IN_SCRIPTING>"enum"{WHITESPACE}("extends"|"implements") {
+ yyless(4);
+ RETURN_TOKEN_WITH_STR(T_STRING, 0);
+}
+<ST_IN_SCRIPTING>"enum"{WHITESPACE}[a-zA-Z_\x80-\xff] {
+ yyless(4);
+ RETURN_TOKEN_WITH_IDENT(T_ENUM);
+}
+
<ST_IN_SCRIPTING>"extends" {
RETURN_TOKEN_WITH_IDENT(T_EXTENDS);
}
@@ -1918,7 +1920,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
/* The +/- 2 skips "0b" */
size_t len = yyleng - 2;
char *end, *bin = yytext + 2;
- zend_bool contains_underscores;
+ bool contains_underscores;
/* Skip any leading 0s */
while (len > 0 && (*bin == '0' || *bin == '_')) {
@@ -1956,11 +1958,61 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
}
+<ST_IN_SCRIPTING>{ONUM} {
+ /* The +/- 2 skips "0o" */
+ size_t len = yyleng - 2;
+ char *end, *octal = yytext + 2;
+ bool contains_underscores = (memchr(octal, '_', len) != NULL);
+
+ /* Skip any leading 0s */
+ while (len > 0 && (*octal == '0' || *octal == '_')) {
+ ++octal;
+ --len;
+ }
+
+ if (len == 0) {
+ ZVAL_LONG(zendlval, 0);
+ RETURN_TOKEN_WITH_VAL(T_LNUMBER);
+ }
+
+ if (contains_underscores) {
+ octal = estrndup(octal, len);
+ strip_underscores(octal, &len);
+ }
+
+ errno = 0;
+
+ ZVAL_LONG(zendlval, ZEND_STRTOL(octal, &end, 8));
+
+ ZEND_ASSERT(end == octal + len);
+
+ if (!errno) {
+ if (contains_underscores) {
+ efree(octal);
+ }
+ RETURN_TOKEN_WITH_VAL(T_LNUMBER);
+ }
+
+ /* Overflow */
+ ZEND_ASSERT(errno == ERANGE);
+ /* Reset errno */
+ errno = 0;
+
+ /* zend_oct_strtod skips leading '0' */
+ ZVAL_DOUBLE(zendlval, zend_oct_strtod(octal, (const char **)&end));
+ ZEND_ASSERT(!errno);
+ ZEND_ASSERT(end == octal + len);
+ if (contains_underscores) {
+ efree(octal);
+ }
+ RETURN_TOKEN_WITH_VAL(T_DNUMBER);
+}
+
<ST_IN_SCRIPTING>{LNUM} {
size_t len = yyleng;
char *end, *lnum = yytext;
- zend_bool is_octal = lnum[0] == '0';
- zend_bool contains_underscores = (memchr(lnum, '_', len) != NULL);
+ bool is_octal = lnum[0] == '0';
+ bool contains_underscores = (memchr(lnum, '_', len) != NULL);
if (contains_underscores) {
lnum = estrndup(lnum, len);
@@ -2023,7 +2075,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
/* The +/- 2 skips "0x" */
size_t len = yyleng - 2;
char *end, *hex = yytext + 2;
- zend_bool contains_underscores;
+ bool contains_underscores;
/* Skip any leading 0s */
while (len > 0 && (*hex == '0' || *hex == '_')) {
@@ -2077,7 +2129,7 @@ string:
RETURN_TOKEN_WITH_VAL(T_NUM_STRING);
}
-<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
+<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM}|{ONUM} { /* Offset must be treated as a string */
if (yyleng == 1) {
ZVAL_INTERNED_STR(zendlval, ZSTR_CHAR((zend_uchar)*(yytext)));
} else {
@@ -2090,7 +2142,7 @@ string:
const char *end;
size_t len = yyleng;
char *dnum = yytext;
- zend_bool contains_underscores = (memchr(dnum, '_', len) != NULL);
+ bool contains_underscores = (memchr(dnum, '_', len) != NULL);
if (contains_underscores) {
dnum = estrndup(dnum, len);
@@ -2528,7 +2580,7 @@ skip_escape_conversion:
unsigned char *saved_cursor;
int bprefix = (yytext[0] != '<') ? 1 : 0, spacing = 0, indentation = 0;
zend_heredoc_label *heredoc_label = emalloc(sizeof(zend_heredoc_label));
- zend_bool is_heredoc = 1;
+ bool is_heredoc = 1;
CG(zend_lineno)++;
heredoc_label->length = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
@@ -2909,7 +2961,7 @@ heredoc_scan_done:
ZVAL_STRINGL(zendlval, yytext, yyleng - newline);
if (!SCNG(heredoc_scan_ahead) && !EG(exception) && PARSER_MODE()) {
- zend_bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r';
+ bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r';
zend_string *copy = Z_STR_P(zendlval);
if (!strip_multiline_string_indentation(
@@ -3010,7 +3062,7 @@ nowdoc_scan_done:
ZVAL_STRINGL(zendlval, yytext, yyleng - newline);
if (!EG(exception) && spacing != -1 && PARSER_MODE()) {
- zend_bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r';
+ bool newline_at_start = *(yytext - 1) == '\n' || *(yytext - 1) == '\r';
if (!strip_multiline_string_indentation(
zendlval, indentation, spacing == HEREDOC_USING_SPACES,
newline_at_start, newline != 0)) {
@@ -3050,8 +3102,7 @@ emit_token:
emit_token_with_ident:
if (PARSER_MODE()) {
- elem->ident.offset = SCNG(yy_text) - SCNG(yy_start);
- elem->ident.len = SCNG(yy_leng);
+ elem->ident = SCNG(yy_text);
}
if (SCNG(on_event)) {
SCNG(on_event)(ON_TOKEN, token, start_line, yytext, yyleng, SCNG(on_event_context));