diff options
32 files changed, 813 insertions, 1 deletions
@@ -2,6 +2,7 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 20??, PHP 5.3.0 - Added and improved PHP syntax and semantics: + . Added NOWDOC. (Gwynne Raskind, Stas, Dmitry) . Added "?:" operator. (Marcus) . Added support for namespaces. (Dmitry, Stas, Gregory) . Added support for Late Static Binding. (Dmitry, Etienne Kneuss) diff --git a/Zend/tests/heredoc_001.phpt b/Zend/tests/heredoc_001.phpt new file mode 100644 index 0000000000..d42b3df2e4 --- /dev/null +++ b/Zend/tests/heredoc_001.phpt @@ -0,0 +1,23 @@ +--TEST-- +basic heredoc syntax +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +This is a heredoc test. + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +This is another heredoc test. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is a heredoc test. +This is another heredoc test. diff --git a/Zend/tests/heredoc_002.phpt b/Zend/tests/heredoc_002.phpt new file mode 100644 index 0000000000..481ada996c --- /dev/null +++ b/Zend/tests/heredoc_002.phpt @@ -0,0 +1,23 @@ +--TEST-- +basic binary heredoc syntax +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print b<<<ENDOFHEREDOC +This is a heredoc test. + +ENDOFHEREDOC; + +$x = b<<<ENDOFHEREDOC +This is another heredoc test. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is a heredoc test. +This is another heredoc test. diff --git a/Zend/tests/heredoc_003.phpt b/Zend/tests/heredoc_003.phpt new file mode 100644 index 0000000000..fb34f515c6 --- /dev/null +++ b/Zend/tests/heredoc_003.phpt @@ -0,0 +1,23 @@ +--TEST-- +simple variable replacement test (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +This is heredoc test #$a. + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +This is heredoc test #$b. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is heredoc test #1. +This is heredoc test #2. diff --git a/Zend/tests/heredoc_004.phpt b/Zend/tests/heredoc_004.phpt new file mode 100644 index 0000000000..29334b8dab --- /dev/null +++ b/Zend/tests/heredoc_004.phpt @@ -0,0 +1,23 @@ +--TEST-- +braces variable replacement test (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +This is heredoc test #{$a}. + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +This is heredoc test #{$b}. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is heredoc test #1. +This is heredoc test #2. diff --git a/Zend/tests/heredoc_005.phpt b/Zend/tests/heredoc_005.phpt new file mode 100644 index 0000000000..8ab3a65f1b --- /dev/null +++ b/Zend/tests/heredoc_005.phpt @@ -0,0 +1,22 @@ +--TEST-- +unbraced complex variable replacement test (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +This is heredoc test #s $a, $b, $c['c'], and $d->d. + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +This is heredoc test #s $a, $b, $c['c'], and $d->d. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECTF-- +Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in %sheredoc_005.php on line 6 diff --git a/Zend/tests/heredoc_006.phpt b/Zend/tests/heredoc_006.phpt new file mode 100644 index 0000000000..d40ae1e02e --- /dev/null +++ b/Zend/tests/heredoc_006.phpt @@ -0,0 +1,23 @@ +--TEST-- +braced complex variable replacement test (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +This is heredoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}. + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +This is heredoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is heredoc test #s 1, 2, 3, and 4. +This is heredoc test #s 1, 2, 3, and 4. diff --git a/Zend/tests/heredoc_007.phpt b/Zend/tests/heredoc_007.phpt new file mode 100644 index 0000000000..b823b556fa --- /dev/null +++ b/Zend/tests/heredoc_007.phpt @@ -0,0 +1,23 @@ +--TEST-- +braced and unbraced complex variable replacement test (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +This is heredoc test #s $a, {$b}, {$c['c']}, and {$d->d}. + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +This is heredoc test #s $a, {$b}, {$c['c']}, and {$d->d}. + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is heredoc test #s 1, 2, 3, and 4. +This is heredoc test #s 1, 2, 3, and 4. diff --git a/Zend/tests/heredoc_008.phpt b/Zend/tests/heredoc_008.phpt new file mode 100644 index 0000000000..8feda035a6 --- /dev/null +++ b/Zend/tests/heredoc_008.phpt @@ -0,0 +1,17 @@ +--TEST-- +empty doc test (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- diff --git a/Zend/tests/heredoc_009.phpt b/Zend/tests/heredoc_009.phpt new file mode 100644 index 0000000000..38f5d282f0 --- /dev/null +++ b/Zend/tests/heredoc_009.phpt @@ -0,0 +1,42 @@ +--TEST-- +Torture the T_END_HEREDOC rules (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<ENDOFHEREDOC +ENDOFHEREDOC ; + ENDOFHEREDOC; +ENDOFHEREDOC + ENDOFHEREDOC +$ENDOFHEREDOC; + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +ENDOFHEREDOC ; + ENDOFHEREDOC; +ENDOFHEREDOC + ENDOFHEREDOC +$ENDOFHEREDOC; + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECTF-- +Notice: Undefined variable: ENDOFHEREDOC in %s on line %d +ENDOFHEREDOC ; + ENDOFHEREDOC; +ENDOFHEREDOC + ENDOFHEREDOC +; + +Notice: Undefined variable: ENDOFHEREDOC in %s on line %d +ENDOFHEREDOC ; + ENDOFHEREDOC; +ENDOFHEREDOC + ENDOFHEREDOC +; diff --git a/Zend/tests/heredoc_010.phpt b/Zend/tests/heredoc_010.phpt new file mode 100644 index 0000000000..5aa0433bcf --- /dev/null +++ b/Zend/tests/heredoc_010.phpt @@ -0,0 +1,32 @@ +--TEST-- +Torture the T_END_HEREDOC rules with variable expansions (heredoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; +$fooledYou = ''; + +print <<<ENDOFHEREDOC +{$fooledYou}ENDOFHEREDOC{$fooledYou} +ENDOFHEREDOC{$fooledYou} +{$fooledYou}ENDOFHEREDOC + +ENDOFHEREDOC; + +$x = <<<ENDOFHEREDOC +{$fooledYou}ENDOFHEREDOC{$fooledYou} +ENDOFHEREDOC{$fooledYou} +{$fooledYou}ENDOFHEREDOC + +ENDOFHEREDOC; + +print "{$x}"; + +?> +--EXPECT-- +ENDOFHEREDOC +ENDOFHEREDOC +ENDOFHEREDOC +ENDOFHEREDOC +ENDOFHEREDOC +ENDOFHEREDOC diff --git a/Zend/tests/heredoc_011.phpt b/Zend/tests/heredoc_011.phpt new file mode 100644 index 0000000000..6a1d5a00db --- /dev/null +++ b/Zend/tests/heredoc_011.phpt @@ -0,0 +1,20 @@ +--TEST-- +Heredocs can NOT be used as static scalars. +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +class e { + + const E = <<<THISMUSTERROR +If you see this, something's wrong. +THISMUSTERROR; + +}; + +print e::E . "\n"; + +?> +--EXPECTF-- +Parse error: syntax error, unexpected T_START_HEREDOC in %sheredoc_011.php on line 8 diff --git a/Zend/tests/nowdoc.inc b/Zend/tests/nowdoc.inc new file mode 100644 index 0000000000..98f9fbaacf --- /dev/null +++ b/Zend/tests/nowdoc.inc @@ -0,0 +1,11 @@ +<?php + +// Common definitions for heredoc/nowdoc tests. +$a = 1; +$b = 2; +$c = array( 'c' => 3, ); +class d { public function __construct() { $this->d = 4; } }; +$d = new d; + +?> + diff --git a/Zend/tests/nowdoc_001.phpt b/Zend/tests/nowdoc_001.phpt new file mode 100644 index 0000000000..3b9e3ef54e --- /dev/null +++ b/Zend/tests/nowdoc_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +basic nowdoc syntax +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +This is a nowdoc test. + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +This is another nowdoc test. +With another line in it. +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is a nowdoc test. +This is another nowdoc test. +With another line in it. diff --git a/Zend/tests/nowdoc_002.phpt b/Zend/tests/nowdoc_002.phpt new file mode 100644 index 0000000000..3b17da814f --- /dev/null +++ b/Zend/tests/nowdoc_002.phpt @@ -0,0 +1,23 @@ +--TEST-- +basic binary nowdoc syntax +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print b<<<'ENDOFNOWDOC' +This is a nowdoc test. + +ENDOFNOWDOC; + +$x = b<<<'ENDOFNOWDOC' +This is another nowdoc test. + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is a nowdoc test. +This is another nowdoc test. diff --git a/Zend/tests/nowdoc_003.phpt b/Zend/tests/nowdoc_003.phpt new file mode 100644 index 0000000000..4282ab912f --- /dev/null +++ b/Zend/tests/nowdoc_003.phpt @@ -0,0 +1,23 @@ +--TEST-- +simple variable replacement test (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +This is nowdoc test #$a. + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +This is nowdoc test #$b. + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is nowdoc test #$a. +This is nowdoc test #$b. diff --git a/Zend/tests/nowdoc_004.phpt b/Zend/tests/nowdoc_004.phpt new file mode 100644 index 0000000000..0e5b927788 --- /dev/null +++ b/Zend/tests/nowdoc_004.phpt @@ -0,0 +1,23 @@ +--TEST-- +braces variable replacement test (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +This is nowdoc test #{$a}. + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +This is nowdoc test #{$b}. + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is nowdoc test #{$a}. +This is nowdoc test #{$b}. diff --git a/Zend/tests/nowdoc_005.phpt b/Zend/tests/nowdoc_005.phpt new file mode 100644 index 0000000000..65e33d744d --- /dev/null +++ b/Zend/tests/nowdoc_005.phpt @@ -0,0 +1,23 @@ +--TEST-- +unbraced complex variable replacement test (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +This is nowdoc test #s $a, $b, $c['c'], and $d->d. + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +This is nowdoc test #s $a, $b, $c['c'], and $d->d. + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is nowdoc test #s $a, $b, $c['c'], and $d->d. +This is nowdoc test #s $a, $b, $c['c'], and $d->d. diff --git a/Zend/tests/nowdoc_006.phpt b/Zend/tests/nowdoc_006.phpt new file mode 100644 index 0000000000..9d99973a14 --- /dev/null +++ b/Zend/tests/nowdoc_006.phpt @@ -0,0 +1,23 @@ +--TEST-- +braced complex variable replacement test (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}. + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}. + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}. +This is nowdoc test #s {$a}, {$b}, {$c['c']}, and {$d->d}. diff --git a/Zend/tests/nowdoc_007.phpt b/Zend/tests/nowdoc_007.phpt new file mode 100644 index 0000000000..d9e941106f --- /dev/null +++ b/Zend/tests/nowdoc_007.phpt @@ -0,0 +1,23 @@ +--TEST-- +braced and unbraced complex variable replacement test (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}. + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}. + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}. +This is nowdoc test #s $a, {$b}, {$c['c']}, and {$d->d}. diff --git a/Zend/tests/nowdoc_008.phpt b/Zend/tests/nowdoc_008.phpt new file mode 100644 index 0000000000..486f0022f6 --- /dev/null +++ b/Zend/tests/nowdoc_008.phpt @@ -0,0 +1,17 @@ +--TEST-- +empty doc test (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- diff --git a/Zend/tests/nowdoc_009.phpt b/Zend/tests/nowdoc_009.phpt new file mode 100644 index 0000000000..ec8b78f010 --- /dev/null +++ b/Zend/tests/nowdoc_009.phpt @@ -0,0 +1,40 @@ +--TEST-- +Torture the T_END_NOWDOC rules (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +print <<<'ENDOFNOWDOC' +ENDOFNOWDOC ; + ENDOFNOWDOC; +ENDOFNOWDOC + ENDOFNOWDOC +$ENDOFNOWDOC; + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +ENDOFNOWDOC ; + ENDOFNOWDOC; +ENDOFNOWDOC + ENDOFNOWDOC +$ENDOFNOWDOC; + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +ENDOFNOWDOC ; + ENDOFNOWDOC; +ENDOFNOWDOC + ENDOFNOWDOC +$ENDOFNOWDOC; +ENDOFNOWDOC ; + ENDOFNOWDOC; +ENDOFNOWDOC + ENDOFNOWDOC +$ENDOFNOWDOC; + diff --git a/Zend/tests/nowdoc_010.phpt b/Zend/tests/nowdoc_010.phpt new file mode 100644 index 0000000000..6f288151ce --- /dev/null +++ b/Zend/tests/nowdoc_010.phpt @@ -0,0 +1,33 @@ +--TEST-- +Torture the T_END_NOWDOC rules with variable expansions (nowdoc) +--FILE-- +<?php + +require_once 'nowdoc.inc'; +$fooledYou = ''; + +print <<<'ENDOFNOWDOC' +{$fooledYou}ENDOFNOWDOC{$fooledYou} +ENDOFNOWDOC{$fooledYou} +{$fooledYou}ENDOFNOWDOC + +ENDOFNOWDOC; + +$x = <<<'ENDOFNOWDOC' +{$fooledYou}ENDOFNOWDOC{$fooledYou} +ENDOFNOWDOC{$fooledYou} +{$fooledYou}ENDOFNOWDOC + +ENDOFNOWDOC; + +print "{$x}"; + +?> +--EXPECT-- +{$fooledYou}ENDOFNOWDOC{$fooledYou} +ENDOFNOWDOC{$fooledYou} +{$fooledYou}ENDOFNOWDOC +{$fooledYou}ENDOFNOWDOC{$fooledYou} +ENDOFNOWDOC{$fooledYou} +{$fooledYou}ENDOFNOWDOC + diff --git a/Zend/tests/nowdoc_011.phpt b/Zend/tests/nowdoc_011.phpt new file mode 100644 index 0000000000..84bcdb6916 --- /dev/null +++ b/Zend/tests/nowdoc_011.phpt @@ -0,0 +1,20 @@ +--TEST-- +Nowdocs CAN be used as static scalars. +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +class e { + + const E = <<<'THISMUSTNOTERROR' +If you DON'T see this, something's wrong. +THISMUSTNOTERROR; + +}; + +print e::E . "\n"; + +?> +--EXPECTF-- +If you DON'T see this, something's wrong. diff --git a/Zend/tests/nowdoc_012.phpt b/Zend/tests/nowdoc_012.phpt new file mode 100644 index 0000000000..0bcb92e4b8 --- /dev/null +++ b/Zend/tests/nowdoc_012.phpt @@ -0,0 +1,25 @@ +--TEST-- +Test false labels +--FILE-- +<?php + +require_once 'nowdoc.inc'; + +$x = <<<'ENDOFNOWDOC' +This is a nowdoc test. +NOTREALLYEND; +Another line +NOTENDEITHER; +ENDOFNOWDOCWILLBESOON +Now let's finish it +ENDOFNOWDOC; +print "{$x}\n"; + +?> +--EXPECT-- +This is a nowdoc test. +NOTREALLYEND; +Another line +NOTENDEITHER; +ENDOFNOWDOCWILLBESOON +Now let's finish it diff --git a/Zend/tests/nowdoc_013.phpt b/Zend/tests/nowdoc_013.phpt new file mode 100644 index 0000000000..574d3d29a8 --- /dev/null +++ b/Zend/tests/nowdoc_013.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test whitespace following end of nowdoc +--INI-- +highlight.string = #DD0000 +highlight.comment = #FF8000 +highlight.keyword = #007700 +highlight.bg = #FFFFFF +highlight.default = #0000BB +highlight.html = #000000 +--FILE-- +<?php +$code = <<<'EOF' +<?php + $x = <<<'EOT' +some string +EOT + $y = 2; +?> +EOF; +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> +</code> diff --git a/Zend/tests/nowdoc_014.phpt b/Zend/tests/nowdoc_014.phpt new file mode 100644 index 0000000000..120a96f46a --- /dev/null +++ b/Zend/tests/nowdoc_014.phpt @@ -0,0 +1,25 @@ +--TEST-- +Highliting empty nowdoc +--INI-- +highlight.string = #DD0000 +highlight.comment = #FF8000 +highlight.keyword = #007700 +highlight.bg = #FFFFFF +highlight.default = #0000BB +highlight.html = #000000 +--FILE-- +<?php +$code = <<<'EOF' +<?php + $x = <<<'EOT' +EOT + $y = 2; +?> +EOF; +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> +</code> diff --git a/Zend/tests/nowdoc_015.phpt b/Zend/tests/nowdoc_015.phpt new file mode 100644 index 0000000000..9eb83bd063 --- /dev/null +++ b/Zend/tests/nowdoc_015.phpt @@ -0,0 +1,74 @@ +--TEST-- +Test nowdoc and line numbering +--FILE-- +<?php +function error_handler($num, $msg, $file, $line, $vars) { + echo $line,"\n"; +} +set_error_handler('error_handler'); +trigger_error("line", E_USER_ERROR); +$x = <<<EOF +EOF; +var_dump($x); +trigger_error("line", E_USER_ERROR); +$x = <<<'EOF' +EOF; +var_dump($x); +trigger_error("line", E_USER_ERROR); +$x = <<<EOF +test +EOF; +var_dump($x); +trigger_error("line", E_USER_ERROR); +$x = <<<'EOF' +test +EOF; +var_dump($x); +trigger_error("line", E_USER_ERROR); +$x = <<<EOF +test1 +test2 + +test3 + + +EOF; +var_dump($x); +trigger_error("line", E_USER_ERROR); +$x = <<<'EOF' +test1 +test2 + +test3 + + +EOF; +var_dump($x); +trigger_error("line", E_USER_ERROR); +echo "ok\n"; +?> +--EXPECT-- +6 +string(0) "" +10 +string(0) "" +14 +string(4) "test" +19 +string(4) "test" +24 +string(20) "test1 +test2 + +test3 + +" +34 +string(20) "test1 +test2 + +test3 + +" +44 +ok diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d69b23987b..c2e3578dd3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4642,6 +4642,7 @@ again: retval = T_ECHO; break; case T_END_HEREDOC: + case T_END_NOWDOC: efree(Z_STRVAL(zendlval->u.constant)); break; case EOF: diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c index c227e0aad5..f21ed23557 100644 --- a/Zend/zend_highlight.c +++ b/Zend/zend_highlight.c @@ -150,6 +150,7 @@ 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: @@ -172,7 +173,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) { + } else if (token_type == T_END_HEREDOC || token_type == T_END_NOWDOC) { efree(token.value.str.val); } token.type = 0; @@ -222,6 +223,7 @@ ZEND_API void zend_strip(TSRMLS_D) 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 ; */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 8ae76d46cf..9c6baca7ef 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -146,6 +146,8 @@ %token T_NAMESPACE %token T_NS_C %token T_DIR +%token T_START_NOWDOC +%token T_END_NOWDOC %% /* Rules */ @@ -721,6 +723,7 @@ 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; } ; diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 1f88f3b451..1bb58db3b1 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -39,6 +39,9 @@ %x ST_HEREDOC %x ST_START_HEREDOC %x ST_END_HEREDOC +%x ST_NOWDOC +%x ST_START_NOWDOC +%x ST_END_NOWDOC %x ST_LOOKING_FOR_PROPERTY %x ST_LOOKING_FOR_VARNAME %x ST_VAR_OFFSET @@ -965,6 +968,8 @@ 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]+))) + %option noyylineno %option noyywrap %% @@ -2065,6 +2070,102 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({ } +%{ +/* 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); +} + +<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 { + yyless(label_len); + yymore(); + BEGIN(ST_NOWDOC); + } +} + +<ST_NOWDOC>{NOWDOC_CHARS}*{NEWLINE}+{LABEL}";"?[\n\r] { + char *end = yytext + yyleng - 1; + + if (end[-1] == ';') { + end--; + yyleng--; + } + + if (yyleng > CG(heredoc_len) && !memcmp(end - CG(heredoc_len), CG(heredoc), CG(heredoc_len))) { + int len = yyleng - CG(heredoc_len) - 2; /* 2 for newline before and after label */ + + if (len > 0 && yytext[len - 1] == '\r' && yytext[len] == '\n') { + len--; + } + + /* 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; + + CG(increment_lineno) = 1; /* For newline before label */ + BEGIN(ST_END_NOWDOC); + + HANDLE_NEWLINES(yytext, len); + zend_copy_value(zendlval, yytext, len); + zendlval->type = IS_STRING; + return T_ENCAPSED_AND_WHITESPACE; + } else { + /* Go back to end of label, so the next match works correctly in case of + * a variable or another label at the beginning of the next line */ + yyless(yyleng - 1); + yymore(); + } +} + +<ST_END_NOWDOC>{ANY_CHAR} { + Z_STRVAL_P(zendlval) = CG(heredoc); + Z_STRLEN_P(zendlval) = CG(heredoc_len); + yytext = CG(heredoc); + yyleng = 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); return '"'; |