. 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:
Dmitry Stogov 2008-07-26 15:30:28 +00:00
parent 8b14236557
commit 478acfd8b4
17 changed files with 3947 additions and 4381 deletions

5
NEWS
View File

@ -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

View File

@ -20,6 +20,6 @@ highlight_string($code);
?>
--EXPECT--
<code><span style="color: #000000">
<br /><span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;EOT<br /></span><span style="color: #0000BB">some&nbsp;string&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
<br /><span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;EOT<br /></span><span style="color: #DD0000">some&nbsp;string&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code>

View File

@ -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.

View File

@ -21,6 +21,6 @@ highlight_string($code);
?>
--EXPECT--
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOT'<br /></span><span style="color: #0000BB">some&nbsp;string&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
<span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOT'<br /></span><span style="color: #DD0000">some&nbsp;string&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code>

View File

@ -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">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOT'<br /></span><span style="color: #0000BB"></span><span style="color: #007700">EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
<span style="color: #0000BB">&lt;?php<br />&nbsp;&nbsp;$x&nbsp;</span><span style="color: #007700">=&nbsp;&lt;&lt;&lt;'EOT'<br />EOT<br />&nbsp;&nbsp;</span><span style="color: #0000BB">$y&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</code>

View File

@ -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;
}

View File

@ -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);

View File

@ -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 ; */

View File

@ -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

View File

@ -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);

View File

@ -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,
};

View File

@ -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);
}

View File

@ -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,

View File

@ -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;

View File

@ -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";

View File

@ -13,6 +13,6 @@ highlight.html=#000000
?>
--EXPECT--
<code><span style="color: #000000">
<span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">echo&nbsp;</span><span style="color: #DD0000">"foo[]&nbsp;$a&nbsp;\n"</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">?&gt;</span>
<span style="color: #0000BB">&lt;?php&nbsp;</span><span style="color: #007700">echo&nbsp;</span><span style="color: #DD0000">"foo[]&nbsp;</span><span style="color: #0000BB">$a</span><span style="color: #DD0000">&nbsp;\n"</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">?&gt;</span>
</span>
</code>