mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
. Added support for using static HEREDOCs to initialize static variables and class members or constants. (Matt)
. Improved syntax highlighting and consistency for variables in double-quoted strings and literal text in HEREDOCs and backticks. (Matt) . Optimized interpolated strings to use one less opcode. (Matt)
This commit is contained in:
parent
8b14236557
commit
478acfd8b4
5
NEWS
5
NEWS
@ -24,6 +24,10 @@ PHP NEWS
|
||||
. Added "jump label" operator (limited "goto"). (Dmitry, Sara)
|
||||
. Added NOWDOC syntax. (Gwynne Raskind, Stas, Dmitry)
|
||||
. Added HEREDOC syntax with double quotes. (Lars Strojny, Felipe)
|
||||
. Added support for using static HEREDOCs to initialize static variables and
|
||||
class members or constants. (Matt)
|
||||
. Improved syntax highlighting and consistency for variables in double-quoted
|
||||
strings and literal text in HEREDOCs and backticks. (Matt)
|
||||
. Added "?:" operator. (Marcus)
|
||||
. Added support for namespaces. (Dmitry, Stas, Gregory)
|
||||
. Added support for Late Static Binding. (Dmitry, Etienne Kneuss)
|
||||
@ -69,6 +73,7 @@ PHP NEWS
|
||||
second usage. (Dmitry)
|
||||
. Optimized ZEND_FETCH_CLASS + ZEND_ADD_INTERFACE into single
|
||||
ZEND_ADD_INTERFACE opcode (Dmitry)
|
||||
. Optimized interpolated strings to use one less opcode. (Matt)
|
||||
|
||||
- Improved php.ini handling: (Jani)
|
||||
. Added ".htaccess" style user-defined php.ini files support for CGI/FastCGI
|
||||
|
@ -20,6 +20,6 @@ highlight_string($code);
|
||||
?>
|
||||
--EXPECT--
|
||||
<code><span style="color: #000000">
|
||||
<br /><span style="color: #0000BB"><?php<br /> $x </span><span style="color: #007700">= <<<EOT<br /></span><span style="color: #0000BB">some string <br /></span><span style="color: #007700">EOT<br /> </span><span style="color: #0000BB">$y </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span>
|
||||
<br /><span style="color: #0000BB"><?php<br /> $x </span><span style="color: #007700">= <<<EOT<br /></span><span style="color: #DD0000">some string <br /></span><span style="color: #007700">EOT<br /> </span><span style="color: #0000BB">$y </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span>
|
||||
</span>
|
||||
</code>
|
||||
|
@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Heredocs can NOT be used as static scalars.
|
||||
STATIC heredocs CAN be used as static scalars.
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
@ -7,14 +7,14 @@ require_once 'nowdoc.inc';
|
||||
|
||||
class e {
|
||||
|
||||
const E = <<<THISMUSTERROR
|
||||
If you see this, something's wrong.
|
||||
THISMUSTERROR;
|
||||
const E = <<<THISMUSTNOTERROR
|
||||
If you DON'T see this, something's wrong.
|
||||
THISMUSTNOTERROR;
|
||||
|
||||
};
|
||||
|
||||
print e::E . "\n";
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Parse error: syntax error, unexpected T_START_HEREDOC in %sheredoc_011.php on line 8
|
||||
--EXPECT--
|
||||
If you DON'T see this, something's wrong.
|
||||
|
@ -21,6 +21,6 @@ highlight_string($code);
|
||||
?>
|
||||
--EXPECT--
|
||||
<code><span style="color: #000000">
|
||||
<span style="color: #0000BB"><?php<br /> $x </span><span style="color: #007700">= <<<'EOT'<br /></span><span style="color: #0000BB">some string <br /></span><span style="color: #007700">EOT<br /> </span><span style="color: #0000BB">$y </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span>
|
||||
<span style="color: #0000BB"><?php<br /> $x </span><span style="color: #007700">= <<<'EOT'<br /></span><span style="color: #DD0000">some string <br /></span><span style="color: #007700">EOT<br /> </span><span style="color: #0000BB">$y </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span>
|
||||
</span>
|
||||
</code>
|
||||
|
@ -1,5 +1,5 @@
|
||||
--TEST--
|
||||
Highliting empty nowdoc
|
||||
Highlighting empty nowdoc
|
||||
--INI--
|
||||
highlight.string = #DD0000
|
||||
highlight.comment = #FF8000
|
||||
@ -20,6 +20,6 @@ highlight_string($code);
|
||||
?>
|
||||
--EXPECT--
|
||||
<code><span style="color: #000000">
|
||||
<span style="color: #0000BB"><?php<br /> $x </span><span style="color: #007700">= <<<'EOT'<br /></span><span style="color: #0000BB"></span><span style="color: #007700">EOT<br /> </span><span style="color: #0000BB">$y </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span>
|
||||
<span style="color: #0000BB"><?php<br /> $x </span><span style="color: #007700">= <<<'EOT'<br />EOT<br /> </span><span style="color: #0000BB">$y </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?></span>
|
||||
</span>
|
||||
</code>
|
||||
|
@ -1022,19 +1022,6 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS
|
||||
}
|
||||
|
||||
|
||||
void zend_do_init_string(znode *result TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
opline->opcode = ZEND_INIT_STRING;
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
*result = opline->result;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
}
|
||||
|
||||
|
||||
void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline;
|
||||
@ -1054,45 +1041,34 @@ void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC)
|
||||
efree(Z_STRVAL(op2->u.constant));
|
||||
return;
|
||||
}
|
||||
opline->op1 = *op1;
|
||||
|
||||
if (op1) {
|
||||
opline->op1 = *op1;
|
||||
opline->result = *op1;
|
||||
} else {
|
||||
SET_UNUSED(opline->op1);
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
}
|
||||
opline->op2 = *op2;
|
||||
opline->op2.op_type = IS_CONST;
|
||||
opline->result = opline->op1;
|
||||
*result = opline->result;
|
||||
}
|
||||
|
||||
|
||||
void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline;
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
if (op1->op_type == IS_CONST) {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_INIT_STRING;
|
||||
opline->opcode = ZEND_ADD_VAR;
|
||||
|
||||
if (op1) {
|
||||
opline->op1 = *op1;
|
||||
opline->result = *op1;
|
||||
} else {
|
||||
SET_UNUSED(opline->op1);
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
*result = opline->result;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
if (Z_STRLEN(op1->u.constant)>0) {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_ADD_STRING;
|
||||
opline->result = *result;
|
||||
opline->op1 = *result;
|
||||
opline->op2 = *op1;
|
||||
opline->result = opline->op1;
|
||||
} else {
|
||||
zval_dtor(&op1->u.constant);
|
||||
}
|
||||
} else {
|
||||
*result = *op1;
|
||||
}
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_ADD_VAR;
|
||||
opline->result = *result;
|
||||
opline->op1 = *result;
|
||||
opline->op2 = *op2;
|
||||
*result = opline->result;
|
||||
}
|
||||
@ -3949,6 +3925,7 @@ void zend_do_shell_exec(znode *result, znode *cmd TSRMLS_DC)
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
switch (cmd->op_type) {
|
||||
case IS_CONST:
|
||||
case IS_TMP_VAR:
|
||||
opline->opcode = ZEND_SEND_VAL;
|
||||
break;
|
||||
@ -4925,7 +4902,6 @@ again:
|
||||
retval = T_ECHO;
|
||||
break;
|
||||
case T_END_HEREDOC:
|
||||
case T_END_NOWDOC:
|
||||
efree(Z_STRVAL(zendlval->u.constant));
|
||||
break;
|
||||
}
|
||||
|
@ -414,7 +414,6 @@ void zend_check_writable_variable(znode *variable);
|
||||
|
||||
void zend_do_free(znode *op1 TSRMLS_DC);
|
||||
|
||||
void zend_do_init_string(znode *result TSRMLS_DC);
|
||||
void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC);
|
||||
void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
|
||||
|
||||
|
@ -93,7 +93,6 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
int token_type;
|
||||
char *last_color = syntax_highlighter_ini->highlight_html;
|
||||
char *next_color;
|
||||
int in_string=0;
|
||||
|
||||
zend_printf("<code>");
|
||||
zend_printf("<span style=\"color: %s\">\n", last_color);
|
||||
@ -115,22 +114,18 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
case T_CLOSE_TAG:
|
||||
next_color = syntax_highlighter_ini->highlight_default;
|
||||
break;
|
||||
case '"':
|
||||
case T_ENCAPSED_AND_WHITESPACE:
|
||||
case T_CONSTANT_ENCAPSED_STRING:
|
||||
next_color = syntax_highlighter_ini->highlight_string;
|
||||
break;
|
||||
case '"':
|
||||
next_color = syntax_highlighter_ini->highlight_string;
|
||||
in_string = !in_string;
|
||||
break;
|
||||
case T_WHITESPACE:
|
||||
zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); /* no color needed */
|
||||
token.type = 0;
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
if (in_string) {
|
||||
next_color = syntax_highlighter_ini->highlight_string;
|
||||
} else if (token.type == 0) {
|
||||
if (token.type == 0) {
|
||||
next_color = syntax_highlighter_ini->highlight_keyword;
|
||||
} else {
|
||||
next_color = syntax_highlighter_ini->highlight_default;
|
||||
@ -149,7 +144,6 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
}
|
||||
switch (token_type) {
|
||||
case T_END_HEREDOC:
|
||||
case T_END_NOWDOC:
|
||||
zend_html_puts(token.value.str.val, token.value.str.len TSRMLS_CC);
|
||||
break;
|
||||
default:
|
||||
@ -159,8 +153,6 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
|
||||
if (token.type == IS_STRING) {
|
||||
switch (token_type) {
|
||||
case EOF:
|
||||
goto done;
|
||||
case T_OPEN_TAG:
|
||||
case T_OPEN_TAG_WITH_ECHO:
|
||||
case T_CLOSE_TAG:
|
||||
@ -172,7 +164,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
efree(token.value.str.val);
|
||||
break;
|
||||
}
|
||||
} else if (token_type == T_END_HEREDOC || token_type == T_END_NOWDOC) {
|
||||
} else if (token_type == T_END_HEREDOC) {
|
||||
efree(token.value.str.val);
|
||||
}
|
||||
token.type = 0;
|
||||
@ -190,7 +182,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
}
|
||||
zend_html_puts(LANG_SCNG(yy_text), (LANG_SCNG(yy_limit) - LANG_SCNG(yy_text)) TSRMLS_CC);
|
||||
}
|
||||
done:
|
||||
|
||||
if (last_color != syntax_highlighter_ini->highlight_html) {
|
||||
zend_printf("</span>\n");
|
||||
}
|
||||
@ -217,12 +209,8 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
case T_DOC_COMMENT:
|
||||
token.type = 0;
|
||||
continue;
|
||||
|
||||
case EOF:
|
||||
return;
|
||||
|
||||
case T_END_HEREDOC:
|
||||
case T_END_NOWDOC:
|
||||
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
|
||||
efree(token.value.str.val);
|
||||
/* read the following character, either newline or ; */
|
||||
|
@ -23,7 +23,7 @@
|
||||
/*
|
||||
* LALR shift/reduce conflicts and how they are resolved:
|
||||
*
|
||||
* - 2 shift/reduce conflicts due to the dangeling elseif/else ambiguity. Solved by shift.
|
||||
* - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -147,8 +147,6 @@
|
||||
%token T_NAMESPACE
|
||||
%token T_NS_C
|
||||
%token T_DIR
|
||||
%token T_START_NOWDOC
|
||||
%token T_END_NOWDOC
|
||||
|
||||
%% /* Rules */
|
||||
|
||||
@ -641,7 +639,7 @@ expr_without_variable:
|
||||
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
|
||||
| scalar { $$ = $1; }
|
||||
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
|
||||
| '`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
|
||||
| '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
|
||||
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
|
||||
| function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); }
|
||||
parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
|
||||
@ -736,6 +734,12 @@ exit_expr:
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
backticks_expr:
|
||||
/* empty */ { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
| T_ENCAPSED_AND_WHITESPACE { $$ = $1; }
|
||||
| encaps_list { $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
ctor_arguments:
|
||||
/* empty */ { Z_LVAL($$.u.constant)=0; }
|
||||
@ -754,7 +758,8 @@ common_scalar:
|
||||
| T_METHOD_C { $$ = $1; }
|
||||
| T_FUNC_C { $$ = $1; }
|
||||
| T_NS_C { $$ = $1; }
|
||||
| T_START_NOWDOC T_ENCAPSED_AND_WHITESPACE T_END_NOWDOC { $$ = $2; }
|
||||
| T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
|
||||
| T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
|
||||
;
|
||||
|
||||
|
||||
@ -944,8 +949,8 @@ non_empty_array_pair_list:
|
||||
encaps_list:
|
||||
encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
|
||||
| encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
|
||||
| /* empty */ { zend_do_init_string(&$$ TSRMLS_CC); }
|
||||
|
||||
| encaps_var { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, NULL, &$1 TSRMLS_CC); }
|
||||
| T_ENCAPSED_AND_WHITESPACE encaps_var { zend_do_add_string(&$$, NULL, &$1 TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$$, &$2 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -919,7 +919,7 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{DOUBLE_QUOTES_LITERAL_DOLL
|
||||
BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR})
|
||||
HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({HEREDOC_NEWLINE}+({HEREDOC_NON_LABEL}|{HEREDOC_LABEL_NO_NEWLINE})))
|
||||
|
||||
NOWDOC_CHARS ({NEWLINE}*(([^a-zA-Z_\x7f-\xff\n\r][^\n\r]*)|({LABEL}[^a-zA-Z0-9_\x7f-\xff;\n\r][^\n\r]*)|({LABEL}[;][^\n\r]+)))
|
||||
NOWDOC_CHARS ([^\n\r]|{NEWLINE}+([^a-zA-Z_\x7f-\xff\n\r]|({LABEL}([^a-zA-Z0-9_\x7f-\xff;\n\r]|(";"[^\n\r])))))
|
||||
|
||||
/* compute yyleng before each rule */
|
||||
<!*> := yyleng = YYCURSOR - SCNG(yy_text);
|
||||
@ -1896,7 +1896,7 @@ inline_char_handler:
|
||||
}
|
||||
|
||||
|
||||
<ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|["]{LABEL}["]){NEWLINE} {
|
||||
<ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|([']{LABEL}['])|(["]{LABEL}["])){NEWLINE} {
|
||||
char *s;
|
||||
int bprefix = (yytext[0] != '<') ? 1 : 0;
|
||||
|
||||
@ -1908,12 +1908,35 @@ inline_char_handler:
|
||||
CG(heredoc_len)--;
|
||||
}
|
||||
|
||||
if (*s == '"') {
|
||||
if (*s == '\'') {
|
||||
s++;
|
||||
CG(heredoc_len) -= 2;
|
||||
|
||||
BEGIN(ST_NOWDOC);
|
||||
} else {
|
||||
if (*s == '"') {
|
||||
s++;
|
||||
CG(heredoc_len) -= 2;
|
||||
}
|
||||
|
||||
BEGIN(ST_HEREDOC);
|
||||
}
|
||||
|
||||
CG(heredoc) = estrndup(s, CG(heredoc_len));
|
||||
BEGIN(ST_START_HEREDOC);
|
||||
|
||||
/* Check for ending label on the next line */
|
||||
if (CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, CG(heredoc_len))) {
|
||||
char *end = YYCURSOR + CG(heredoc_len);
|
||||
|
||||
if (*end == ';') {
|
||||
end++;
|
||||
}
|
||||
|
||||
if (*end == '\n' || *end == '\r') {
|
||||
BEGIN(ST_END_HEREDOC);
|
||||
}
|
||||
}
|
||||
|
||||
return T_START_HEREDOC;
|
||||
}
|
||||
|
||||
@ -1924,34 +1947,6 @@ inline_char_handler:
|
||||
}
|
||||
|
||||
|
||||
<ST_START_HEREDOC>{ANY_CHAR} {
|
||||
yyless(0);
|
||||
BEGIN(ST_HEREDOC);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
<ST_START_HEREDOC>{LABEL}";"?[\n\r] {
|
||||
int label_len = yyleng - 1;
|
||||
|
||||
if (yytext[label_len-1]==';') {
|
||||
label_len--;
|
||||
}
|
||||
|
||||
yyless(label_len);
|
||||
|
||||
if (label_len==CG(heredoc_len) && !memcmp(yytext, CG(heredoc), label_len)) {
|
||||
zendlval->value.str.val = CG(heredoc);
|
||||
zendlval->value.str.len = label_len;
|
||||
CG(heredoc)=NULL;
|
||||
CG(heredoc_len)=0;
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_END_HEREDOC;
|
||||
} else {
|
||||
BEGIN(ST_HEREDOC);
|
||||
yymore();
|
||||
}
|
||||
}
|
||||
|
||||
/* Match everything up to and including a possible ending label, so if the label
|
||||
* doesn't match, it's kept with the rest of the string
|
||||
*
|
||||
@ -1979,12 +1974,9 @@ inline_char_handler:
|
||||
len--; /* Windows newline */
|
||||
}
|
||||
|
||||
/* Go back before last label char, to match in ST_END_HEREDOC state */
|
||||
yyless(yyleng - 2);
|
||||
|
||||
/* Subtract the remaining label length. yyleng must include newline
|
||||
* before label, for zend_highlight/strip, tokenizer, etc. */
|
||||
yyleng -= CG(heredoc_len) - 1;
|
||||
/* Go back before label, to match in ST_END_HEREDOC state. yytext will include
|
||||
* newline before label, for zend_highlight/strip, tokenizer, etc. */
|
||||
yyless(yyleng - CG(heredoc_len) - 1); /* 1 for newline after label */
|
||||
|
||||
CG(increment_lineno) = 1; /* For newline before label */
|
||||
BEGIN(ST_END_HEREDOC);
|
||||
@ -1999,8 +1991,11 @@ inline_char_handler:
|
||||
}
|
||||
|
||||
<ST_END_HEREDOC>{ANY_CHAR} {
|
||||
SCNG(yy_text) = (unsigned char *)(Z_STRVAL_P(zendlval) = CG(heredoc));
|
||||
SCNG(yy_leng) = Z_STRLEN_P(zendlval) = CG(heredoc_len);
|
||||
YYCURSOR += CG(heredoc_len) - 1;
|
||||
yyleng = CG(heredoc_len);
|
||||
|
||||
Z_STRVAL_P(zendlval) = CG(heredoc);
|
||||
Z_STRLEN_P(zendlval) = CG(heredoc_len);
|
||||
CG(heredoc) = NULL;
|
||||
CG(heredoc_len) = 0;
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
@ -2065,52 +2060,7 @@ inline_char_handler:
|
||||
}
|
||||
|
||||
|
||||
/* BEGIN nowdoc */
|
||||
|
||||
<ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}[']{LABEL}[']{NEWLINE} {
|
||||
int bprefix = (yytext[0] != '<') ? 1 : 0;
|
||||
char *s;
|
||||
CG(zend_lineno)++;
|
||||
/* 3 is <<<, 2 is quotes, 1 is newline */
|
||||
CG(heredoc_len) = yyleng-bprefix-3-2-1-(yytext[yyleng-2]=='\r'?1:0);
|
||||
s = yytext+bprefix+3;
|
||||
while ((*s == ' ') || (*s == '\t')) {
|
||||
s++;
|
||||
CG(heredoc_len)--;
|
||||
}
|
||||
s++; /* first quote */
|
||||
CG(heredoc) = estrndup(s, CG(heredoc_len));
|
||||
BEGIN(ST_START_NOWDOC);
|
||||
return T_START_NOWDOC;
|
||||
}
|
||||
|
||||
<ST_START_NOWDOC>{ANY_CHAR} {
|
||||
yyless(0);
|
||||
BEGIN(ST_NOWDOC);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
<ST_START_NOWDOC>{LABEL}";"?[\r\n] {
|
||||
int label_len = yyleng - 1;
|
||||
|
||||
if (yytext[label_len-1]==';') {
|
||||
label_len--;
|
||||
}
|
||||
|
||||
if (label_len==CG(heredoc_len) && !memcmp(yytext, CG(heredoc), label_len)) {
|
||||
yyless(label_len-1);
|
||||
yyleng = 0;
|
||||
BEGIN(ST_END_NOWDOC);
|
||||
ZVAL_EMPTY_STRING(zendlval);
|
||||
return T_ENCAPSED_AND_WHITESPACE;
|
||||
} else {
|
||||
BEGIN(ST_NOWDOC);
|
||||
yyless(label_len);
|
||||
yymore();
|
||||
}
|
||||
}
|
||||
|
||||
<ST_NOWDOC>{NOWDOC_CHARS}*{NEWLINE}+{LABEL}";"?[\n\r] {
|
||||
<ST_NOWDOC>({NOWDOC_CHARS}+{NEWLINE}+|{NEWLINE}+){LABEL}";"?[\n\r] {
|
||||
char *end = yytext + yyleng - 1;
|
||||
|
||||
if (end[-1] == ';') {
|
||||
@ -2131,19 +2081,16 @@ inline_char_handler:
|
||||
len--; /* Windows newline */
|
||||
}
|
||||
|
||||
/* Go back before last label char, to match in ST_END_NOWDOC state */
|
||||
yyless(yyleng - 2);
|
||||
|
||||
/* Subtract the remaining label length. yyleng must include newline
|
||||
* before label, for zend_highlight/strip, tokenizer, etc. */
|
||||
yyleng -= CG(heredoc_len) - 1;
|
||||
/* Go back before label, to match in ST_END_HEREDOC state. yytext will include
|
||||
* newline before label, for zend_highlight/strip, tokenizer, etc. */
|
||||
yyless(yyleng - CG(heredoc_len) - 1); /* 1 for newline after label */
|
||||
|
||||
CG(increment_lineno) = 1; /* For newline before label */
|
||||
BEGIN(ST_END_NOWDOC);
|
||||
BEGIN(ST_END_HEREDOC);
|
||||
|
||||
HANDLE_NEWLINES(yytext, len);
|
||||
zend_copy_value(zendlval, yytext, len);
|
||||
zendlval->type = IS_STRING;
|
||||
HANDLE_NEWLINES(yytext, len);
|
||||
return T_ENCAPSED_AND_WHITESPACE;
|
||||
} else {
|
||||
/* Go back to end of label, so the next match works correctly in case of
|
||||
@ -2153,16 +2100,6 @@ inline_char_handler:
|
||||
}
|
||||
}
|
||||
|
||||
<ST_END_NOWDOC>{ANY_CHAR} {
|
||||
SCNG(yy_text) = (unsigned char*)(Z_STRVAL_P(zendlval) = CG(heredoc));
|
||||
SCNG(yy_leng) = Z_STRLEN_P(zendlval) = CG(heredoc_len);
|
||||
CG(heredoc) = NULL;
|
||||
CG(heredoc_len) = 0;
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
return T_END_NOWDOC;
|
||||
}
|
||||
|
||||
/* END nowdoc */
|
||||
|
||||
<ST_DOUBLE_QUOTES>["] {
|
||||
BEGIN(ST_IN_SCRIPTING);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Generated by re2c 0.13.5 on Fri Jul 25 07:14:28 2008 */
|
||||
/* Generated by re2c 0.13.5 on Sat Jul 26 18:30:43 2008 */
|
||||
#line 3 "Zend/zend_language_scanner_defs.h"
|
||||
|
||||
enum YYCONDTYPE {
|
||||
@ -13,9 +13,6 @@ enum YYCONDTYPE {
|
||||
yycST_ONE_LINE_COMMENT,
|
||||
yycST_COMMENT,
|
||||
yycST_DOC_COMMENT,
|
||||
yycST_START_HEREDOC,
|
||||
yycST_END_HEREDOC,
|
||||
yycST_START_NOWDOC,
|
||||
yycST_NOWDOC,
|
||||
yycST_END_NOWDOC,
|
||||
};
|
||||
|
@ -1776,38 +1776,64 @@ ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP, CONST)
|
||||
ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_char_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
add_char_to_string(str, str, &opline->op2.u.constant);
|
||||
|
||||
add_char_to_string(&EX_T(opline->result.u.var).tmp_var,
|
||||
GET_OP1_ZVAL_PTR(BP_VAR_NA),
|
||||
&opline->op2.u.constant);
|
||||
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP, CONST)
|
||||
ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
add_string_to_string(str, str, &opline->op2.u.constant);
|
||||
|
||||
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
|
||||
GET_OP1_ZVAL_PTR(BP_VAR_NA),
|
||||
&opline->op2.u.constant);
|
||||
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP, TMP|VAR|CV)
|
||||
ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1, free_op2;
|
||||
zend_free_op free_op2;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (OP1_TYPE == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
@ -1815,9 +1841,8 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP, TMP|VAR|CV)
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
|
||||
GET_OP1_ZVAL_PTR(BP_VAR_NA),
|
||||
var);
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
|
@ -5890,11 +5890,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC
|
||||
static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_char_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
add_char_to_string(str, str, &opline->op2.u.constant);
|
||||
|
||||
add_char_to_string(&EX_T(opline->result.u.var).tmp_var,
|
||||
_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
|
||||
&opline->op2.u.constant);
|
||||
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -5902,11 +5910,19 @@ static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL
|
||||
static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
add_string_to_string(str, str, &opline->op2.u.constant);
|
||||
|
||||
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
|
||||
_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
|
||||
&opline->op2.u.constant);
|
||||
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
@ -6337,11 +6353,21 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER
|
||||
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1, free_op2;
|
||||
zend_free_op free_op2;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
@ -6349,9 +6375,8 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
|
||||
_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
|
||||
var);
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
@ -6794,11 +6819,21 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER
|
||||
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1, free_op2;
|
||||
zend_free_op free_op2;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
@ -6806,9 +6841,8 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
|
||||
_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
|
||||
var);
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
@ -7344,11 +7378,21 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_
|
||||
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1;
|
||||
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (IS_TMP_VAR == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
@ -7356,9 +7400,8 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_A
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
|
||||
_get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
|
||||
var);
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
@ -17682,6 +17725,46 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_char_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
add_char_to_string(str, str, &opline->op2.u.constant);
|
||||
|
||||
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
add_string_to_string(str, str, &opline->op2.u.constant);
|
||||
|
||||
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
@ -18786,6 +18869,47 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op2;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
if (use_copy) {
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
/* original comment, possibly problematic:
|
||||
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
||||
* (Zeev): I don't think it's problematic, we only use variables
|
||||
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
||||
* string offsets or overloaded objects
|
||||
*/
|
||||
zval_dtor(free_op2.var);
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
@ -19819,6 +19943,47 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
zend_free_op free_op2;
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
if (use_copy) {
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
/* original comment, possibly problematic:
|
||||
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
||||
* (Zeev): I don't think it's problematic, we only use variables
|
||||
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
||||
* string offsets or overloaded objects
|
||||
*/
|
||||
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
@ -21123,6 +21288,46 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
|
||||
zval *str = &EX_T(opline->result.u.var).tmp_var;
|
||||
zval *var = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
|
||||
zval var_copy;
|
||||
int use_copy = 0;
|
||||
|
||||
if (IS_UNUSED == IS_UNUSED) {
|
||||
/* Initialize for erealloc in add_string_to_string */
|
||||
Z_STRVAL_P(str) = NULL;
|
||||
Z_STRLEN_P(str) = 0;
|
||||
Z_TYPE_P(str) = IS_STRING;
|
||||
|
||||
INIT_PZVAL(str);
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(var) != IS_STRING) {
|
||||
zend_make_printable_zval(var, &var_copy, &use_copy);
|
||||
|
||||
if (use_copy) {
|
||||
var = &var_copy;
|
||||
}
|
||||
}
|
||||
add_string_to_string(str, str, var);
|
||||
|
||||
if (use_copy) {
|
||||
zval_dtor(var);
|
||||
}
|
||||
/* original comment, possibly problematic:
|
||||
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
||||
* (Zeev): I don't think it's problematic, we only use variables
|
||||
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
||||
* string offsets or overloaded objects
|
||||
*/
|
||||
|
||||
ZEND_VM_NEXT_OPCODE();
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_op *opline = EX(opline);
|
||||
@ -31371,7 +31576,7 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
@ -31396,7 +31601,7 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
@ -31422,10 +31627,10 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER,
|
||||
ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
|
@ -132,7 +132,7 @@ static void tokenize(zval *return_value TSRMLS_DC)
|
||||
MAKE_STD_ZVAL(keyword);
|
||||
array_init(keyword);
|
||||
add_next_index_long(keyword, token_type);
|
||||
if (token_type == T_END_HEREDOC || token_type == T_END_NOWDOC) {
|
||||
if (token_type == T_END_HEREDOC) {
|
||||
if (CG(increment_lineno)) {
|
||||
token_line = ++CG(zend_lineno);
|
||||
CG(increment_lineno) = 0;
|
||||
|
@ -151,8 +151,6 @@ void tokenizer_register_constants(INIT_FUNC_ARGS) {
|
||||
REGISTER_LONG_CONSTANT("T_NAMESPACE", T_NAMESPACE, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_NS_C", T_NS_C, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_DIR", T_DIR, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_START_NOWDOC", T_START_NOWDOC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_END_NOWDOC", T_END_NOWDOC, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("T_DOUBLE_COLON", T_PAAMAYIM_NEKUDOTAYIM, CONST_CS | CONST_PERSISTENT);
|
||||
}
|
||||
|
||||
@ -282,8 +280,6 @@ char *get_token_type_name(int token_type)
|
||||
case T_NAMESPACE: return "T_NAMESPACE";
|
||||
case T_NS_C: return "T_NS_C";
|
||||
case T_DIR: return "T_DIR";
|
||||
case T_START_NOWDOC: return "T_START_NOWDOC";
|
||||
case T_END_NOWDOC: return "T_END_NOWDOC";
|
||||
|
||||
}
|
||||
return "UNKNOWN";
|
||||
|
@ -13,6 +13,6 @@ highlight.html=#000000
|
||||
?>
|
||||
--EXPECT--
|
||||
<code><span style="color: #000000">
|
||||
<span style="color: #0000BB"><?php </span><span style="color: #007700">echo </span><span style="color: #DD0000">"foo[] $a \n"</span><span style="color: #007700">; </span><span style="color: #0000BB">?></span>
|
||||
<span style="color: #0000BB"><?php </span><span style="color: #007700">echo </span><span style="color: #DD0000">"foo[] </span><span style="color: #0000BB">$a</span><span style="color: #DD0000"> \n"</span><span style="color: #007700">; </span><span style="color: #0000BB">?></span>
|
||||
</span>
|
||||
</code>
|
||||
|
Loading…
Reference in New Issue
Block a user