. 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:31:38 +00:00
parent 2d49dc63e6
commit ef5f3cfdf2
15 changed files with 4084 additions and 4651 deletions

View File

@ -19,6 +19,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: parse error in %sheredoc_011.php on line %d
--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

@ -1078,20 +1078,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));
opline->extended_value = CG(literal_type);
*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;
@ -1111,45 +1097,35 @@ void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC) /* {{{
efree(Z_UNIVAL(op2->u.constant).v);
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;
opline->extended_value = CG(literal_type);
*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;
opline->extended_value = CG(literal_type);
*result = opline->result;
@ -4168,6 +4144,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;
@ -5153,7 +5130,6 @@ again:
retval = T_ECHO;
break;
case T_END_HEREDOC:
case T_END_NOWDOC:
efree(Z_STRVAL(zendlval->u.constant));
break;
}

View File

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

@ -77,7 +77,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;
CG(literal_type) = IS_STRING;
zend_printf("<code>");
@ -100,22 +99,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 */
Z_TYPE(token) = 0;
continue;
break;
default:
if (in_string) {
next_color = syntax_highlighter_ini->highlight_string;
} else if (Z_TYPE(token) == 0) {
if (Z_TYPE(token) == 0) {
next_color = syntax_highlighter_ini->highlight_keyword;
} else {
next_color = syntax_highlighter_ini->highlight_default;
@ -134,7 +129,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(Z_STRVAL(token), Z_STRLEN(token) TSRMLS_CC);
break;
default:
@ -156,7 +150,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
efree(Z_UNIVAL(token).v);
break;
}
} else if (token_type == T_END_HEREDOC || token_type == T_END_NOWDOC) {
} else if (token_type == T_END_HEREDOC) {
efree(Z_UNIVAL(token).v);
}
Z_TYPE(token) = 0;
@ -204,11 +198,7 @@ ZEND_API void zend_strip(TSRMLS_D) /* {{{ */
Z_TYPE(token) = 0;
continue;
case EOF:
return;
case T_END_HEREDOC:
case T_END_NOWDOC:
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
efree(Z_STRVAL(token));
/* 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.
*
*/
@ -149,8 +149,6 @@
%token T_NAMESPACE
%token T_NS_C
%token T_DIR
%token T_START_NOWDOC
%token T_END_NOWDOC
%% /* Rules */
@ -645,7 +643,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; }
| '`' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '`' { zend_do_shell_exec(&$$, &$3 TSRMLS_CC); }
| '`' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } backticks_expr '`' { zend_do_shell_exec(&$$, &$3 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; }
@ -739,6 +737,12 @@ exit_expr:
| '(' expr ')' { $$ = $2; }
;
backticks_expr:
/* empty */ { ZVAL_EMPTY_TEXT(&$$.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; }
@ -757,7 +761,13 @@ 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; }
| start_heredoc T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
| start_heredoc T_END_HEREDOC { if (CG(literal_type) == IS_UNICODE) { ZVAL_EMPTY_UNICODE(&$$.u.constant); } else { ZVAL_EMPTY_STRING(&$$.u.constant); } INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; }
;
start_heredoc:
T_START_HEREDOC { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; }
| T_BINARY_HEREDOC { CG(literal_type) = IS_STRING; }
;
@ -782,9 +792,8 @@ scalar:
| class_constant { $$ = $1; }
| common_scalar { $$ = $1; }
| '"' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '"' { $$ = $3; }
| T_START_HEREDOC { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; }
| T_BINARY_DOUBLE { CG(literal_type) = IS_STRING; } encaps_list '"' { $$ = $3; }
| T_BINARY_HEREDOC { CG(literal_type) = IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; }
| start_heredoc encaps_list T_END_HEREDOC { $$ = $2; }
;
@ -947,8 +956,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

@ -1420,7 +1420,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);
@ -2423,45 +2423,48 @@ inline_char_handler:
return T_BINARY_DOUBLE;
}
<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;
CG(zend_lineno)++;
CG(heredoc_len) = yyleng-4-1-(yytext[yyleng-2]=='\r'?1:0);
s = yytext+4;
CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
s = yytext+bprefix+3;
while ((*s == ' ') || (*s == '\t')) {
s++;
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);
return T_BINARY_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);
<ST_IN_SCRIPTING>"<<<"{TABS_AND_SPACES}({LABEL}|["]{LABEL}["]){NEWLINE} {
char *s;
if (*end == ';') {
end++;
}
CG(zend_lineno)++;
CG(heredoc_len) = yyleng-3-1-(yytext[yyleng-2]=='\r'?1:0);
s = yytext+3;
while ((*s == ' ') || (*s == '\t')) {
s++;
CG(heredoc_len)--;
if (*end == '\n' || *end == '\r') {
BEGIN(ST_END_HEREDOC);
}
}
if (*s == '"') {
s++;
CG(heredoc_len) -= 2;
}
CG(heredoc) = estrndup(s, CG(heredoc_len));
BEGIN(ST_START_HEREDOC);
return T_START_HEREDOC;
return bprefix ? T_BINARY_HEREDOC : T_START_HEREDOC;
}
@ -2471,34 +2474,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)) {
Z_STRVAL_P(zendlval) = CG(heredoc);
Z_STRLEN_P(zendlval) = 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
*
@ -2526,12 +2501,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);
@ -2551,8 +2523,11 @@ inline_char_handler:
}
<ST_END_HEREDOC>{ANY_CHAR} {
SCNG(yy_text) = 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);
@ -2644,58 +2619,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));
CG(literal_type) = bprefix?IS_STRING:ZEND_STR_TYPE;
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);
if (CG(literal_type) == IS_UNICODE) {
ZVAL_EMPTY_UNICODE(zendlval);
} else {
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] == ';') {
@ -2716,20 +2640,17 @@ 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);
if (!zend_copy_scanner_string(zendlval, yytext, len, CG(literal_type), SCNG(output_conv) TSRMLS_CC)) {
return 0;
}
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
@ -2739,16 +2660,6 @@ inline_char_handler:
}
}
<ST_END_NOWDOC>{ANY_CHAR} {
SCNG(yy_text) = 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.6.dev on Tue Jul 8 16:24:44 2008 */
/* Generated by re2c 0.13.5 on Sat Jul 26 19:05:04 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

@ -1824,38 +1824,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
@ -1867,8 +1893,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

@ -6110,11 +6110,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
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();
}
@ -6122,11 +6130,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
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();
}
@ -6560,11 +6576,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
@ -6576,8 +6602,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);
}
@ -7023,11 +7049,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
@ -7039,8 +7075,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);
}
@ -7580,11 +7616,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
@ -7596,8 +7642,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);
}
@ -18313,6 +18359,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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
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);
@ -19469,6 +19555,51 @@ 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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
} else {
zend_make_string_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);
@ -20554,6 +20685,51 @@ 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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
} else {
zend_make_string_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);
@ -21909,6 +22085,50 @@ 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_UNIVAL_P(str).v = NULL;
Z_UNILEN_P(str) = 0;
Z_TYPE_P(str) = opline->extended_value;
INIT_PZVAL(str);
}
if (Z_TYPE_P(var) != opline->extended_value) {
if (opline->extended_value == IS_UNICODE) {
zend_make_unicode_zval(var, &var_copy, &use_copy);
} else {
zend_make_string_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);
@ -32575,7 +32795,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,
@ -32600,7 +32820,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,
@ -32626,10 +32846,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

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

@ -12,6 +12,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>