summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--Zend/tests/heredoc_001.phpt23
-rw-r--r--Zend/tests/heredoc_002.phpt23
-rw-r--r--Zend/tests/heredoc_003.phpt23
-rw-r--r--Zend/tests/heredoc_004.phpt23
-rw-r--r--Zend/tests/heredoc_005.phpt22
-rw-r--r--Zend/tests/heredoc_006.phpt23
-rw-r--r--Zend/tests/heredoc_007.phpt23
-rw-r--r--Zend/tests/heredoc_008.phpt17
-rw-r--r--Zend/tests/heredoc_009.phpt42
-rw-r--r--Zend/tests/heredoc_010.phpt32
-rw-r--r--Zend/tests/heredoc_011.phpt20
-rw-r--r--Zend/tests/nowdoc.inc11
-rw-r--r--Zend/tests/nowdoc_001.phpt24
-rw-r--r--Zend/tests/nowdoc_002.phpt23
-rw-r--r--Zend/tests/nowdoc_003.phpt23
-rw-r--r--Zend/tests/nowdoc_004.phpt23
-rw-r--r--Zend/tests/nowdoc_005.phpt23
-rw-r--r--Zend/tests/nowdoc_006.phpt23
-rw-r--r--Zend/tests/nowdoc_007.phpt23
-rw-r--r--Zend/tests/nowdoc_008.phpt17
-rw-r--r--Zend/tests/nowdoc_009.phpt40
-rw-r--r--Zend/tests/nowdoc_010.phpt33
-rw-r--r--Zend/tests/nowdoc_011.phpt20
-rw-r--r--Zend/tests/nowdoc_012.phpt25
-rw-r--r--Zend/tests/nowdoc_013.phpt26
-rw-r--r--Zend/tests/nowdoc_014.phpt25
-rw-r--r--Zend/tests/nowdoc_015.phpt74
-rw-r--r--Zend/zend_compile.c1
-rw-r--r--Zend/zend_highlight.c4
-rw-r--r--Zend/zend_language_parser.y3
-rw-r--r--Zend/zend_language_scanner.l101
32 files changed, 813 insertions, 1 deletions
diff --git a/NEWS b/NEWS
index 6e9959a9fb..1f63ddaa57 100644
--- a/NEWS
+++ b/NEWS
@@ -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">&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>
+</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">&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>
+</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 '"';