The final nowdoc patches are attached.
I'm going to commit them on Thursday in case of no objections.

Thanks. Dmitry.

Stanislav Malyshev wrote:
Hi all!

I remember the topic of 'nowdocs' (if you don't remember what it is, read on) was already discussed, but nothing really happened about it. For those who just recently woke up from cryogenic sleep :), "nowdocs" are heredocs extension that does not interpret the content (think single quotes instead of double quotes). Should look something like:
$foo = <<<'END'
blah$fooblah
END
unline regular heredocs, $foo would be left as-is. I think now it's good to add it to 5.3 (and I like 'FOO' syntax best of all variants).

Any objections to this?
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.39
diff -u -p -d -r1.647.2.27.2.41.2.39 zend_compile.c
--- Zend/zend_compile.c 29 Jan 2008 00:07:26 -0000      1.647.2.27.2.41.2.39
+++ Zend/zend_compile.c 30 Jan 2008 12:13:07 -0000
@@ -4641,6 +4641,7 @@ again:
                        retval = T_ECHO;
                        break;
                case T_END_HEREDOC:
+               case T_END_NOWDOC:
                        efree(Z_STRVAL(zendlval->u.constant));
                        break;
                case EOF:
Index: Zend/zend_highlight.c
===================================================================
RCS file: /repository/ZendEngine2/zend_highlight.c,v
retrieving revision 1.49.2.3.2.2.2.1
diff -u -p -d -r1.49.2.3.2.2.2.1 zend_highlight.c
--- Zend/zend_highlight.c       31 Dec 2007 07:17:04 -0000      1.49.2.3.2.2.2.1
+++ Zend/zend_highlight.c       30 Jan 2008 12:13:07 -0000
@@ -150,6 +150,7 @@ ZEND_API void zend_highlight(zend_syntax
                }
                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
                                        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 ; */
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.8.2.13
diff -u -p -d -r1.160.2.4.2.8.2.13 zend_language_parser.y
--- Zend/zend_language_parser.y 28 Dec 2007 13:22:00 -0000      
1.160.2.4.2.8.2.13
+++ Zend/zend_language_parser.y 30 Jan 2008 12:13:07 -0000
@@ -145,6 +145,8 @@
 %token T_PAAMAYIM_NEKUDOTAYIM
 %token T_NAMESPACE
 %token T_NS_C
+%token T_START_NOWDOC
+%token T_END_NOWDOC
 
 %% /* Rules */
 
@@ -719,6 +721,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; }
 ;
 
 
Index: Zend/zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.131.2.11.2.13.2.4
diff -u -p -d -r1.131.2.11.2.13.2.4 zend_language_scanner.l
--- Zend/zend_language_scanner.l        21 Jan 2008 19:39:55 -0000      
1.131.2.11.2.13.2.4
+++ Zend/zend_language_scanner.l        30 Jan 2008 12:13:07 -0000
@@ -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
@@ -963,6 +966,8 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"
 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
 %%
@@ -2036,6 +2041,101 @@ HEREDOC_CHARS       ("{"*([^$\n\r\\{]|("
 }
 
 
+%{
+/* 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);
+               ZVAL_STRINGL(zendlval, yytext, len, 1);
+               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 '"';
Index: Zend/tests/nowdoc.inc
===================================================================
RCS file: Zend/tests/nowdoc.inc
diff -N Zend/tests/nowdoc.inc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc.inc       30 Jan 2008 12:13:07 -0000
@@ -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;
+
+?>
+
Index: Zend/tests/nowdoc_001.phpt
===================================================================
RCS file: Zend/tests/nowdoc_001.phpt
diff -N Zend/tests/nowdoc_001.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_001.phpt  30 Jan 2008 12:13:07 -0000
@@ -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.
Index: Zend/tests/nowdoc_002.phpt
===================================================================
RCS file: Zend/tests/nowdoc_002.phpt
diff -N Zend/tests/nowdoc_002.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_002.phpt  30 Jan 2008 12:13:07 -0000
@@ -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.
Index: Zend/tests/nowdoc_003.phpt
===================================================================
RCS file: Zend/tests/nowdoc_003.phpt
diff -N Zend/tests/nowdoc_003.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_003.phpt  30 Jan 2008 12:13:07 -0000
@@ -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.
Index: Zend/tests/nowdoc_004.phpt
===================================================================
RCS file: Zend/tests/nowdoc_004.phpt
diff -N Zend/tests/nowdoc_004.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_004.phpt  30 Jan 2008 12:13:07 -0000
@@ -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}.
Index: Zend/tests/nowdoc_005.phpt
===================================================================
RCS file: Zend/tests/nowdoc_005.phpt
diff -N Zend/tests/nowdoc_005.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_005.phpt  30 Jan 2008 12:13:07 -0000
@@ -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.
Index: Zend/tests/nowdoc_006.phpt
===================================================================
RCS file: Zend/tests/nowdoc_006.phpt
diff -N Zend/tests/nowdoc_006.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_006.phpt  30 Jan 2008 12:13:07 -0000
@@ -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}.
Index: Zend/tests/nowdoc_007.phpt
===================================================================
RCS file: Zend/tests/nowdoc_007.phpt
diff -N Zend/tests/nowdoc_007.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_007.phpt  30 Jan 2008 12:13:07 -0000
@@ -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}.
Index: Zend/tests/nowdoc_008.phpt
===================================================================
RCS file: Zend/tests/nowdoc_008.phpt
diff -N Zend/tests/nowdoc_008.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_008.phpt  30 Jan 2008 12:13:07 -0000
@@ -0,0 +1,17 @@
+--TEST--
+empty doc test (nowdoc)
+--FILE--
+<?php
+
+require_once 'nowdoc.inc';
+
+print <<<'ENDOFNOWDOC'
+ENDOFNOWDOC;
+
+$x = <<<'ENDOFNOWDOC'
+ENDOFNOWDOC;
+
+print "{$x}";
+
+?>
+--EXPECT--
Index: Zend/tests/nowdoc_009.phpt
===================================================================
RCS file: Zend/tests/nowdoc_009.phpt
diff -N Zend/tests/nowdoc_009.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_009.phpt  30 Jan 2008 12:13:07 -0000
@@ -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;
+
Index: Zend/tests/nowdoc_010.phpt
===================================================================
RCS file: Zend/tests/nowdoc_010.phpt
diff -N Zend/tests/nowdoc_010.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_010.phpt  30 Jan 2008 12:13:07 -0000
@@ -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
+
Index: Zend/tests/nowdoc_011.phpt
===================================================================
RCS file: Zend/tests/nowdoc_011.phpt
diff -N Zend/tests/nowdoc_011.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_011.phpt  30 Jan 2008 12:13:07 -0000
@@ -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.
Index: Zend/tests/nowdoc_012.phpt
===================================================================
RCS file: Zend/tests/nowdoc_012.phpt
diff -N Zend/tests/nowdoc_012.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_012.phpt  30 Jan 2008 12:13:07 -0000
@@ -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
Index: Zend/tests/nowdoc_013.phpt
===================================================================
RCS file: Zend/tests/nowdoc_013.phpt
diff -N Zend/tests/nowdoc_013.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_013.phpt  30 Jan 2008 12:13:07 -0000
@@ -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>
Index: Zend/tests/nowdoc_014.phpt
===================================================================
RCS file: Zend/tests/nowdoc_014.phpt
diff -N Zend/tests/nowdoc_014.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_014.phpt  30 Jan 2008 12:13:07 -0000
@@ -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>
Index: Zend/tests/nowdoc_015.phpt
===================================================================
RCS file: Zend/tests/nowdoc_015.phpt
diff -N Zend/tests/nowdoc_015.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_015.phpt  30 Jan 2008 12:13:07 -0000
@@ -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
Index: ext/tokenizer/tokenizer.c
===================================================================
RCS file: /repository/php-src/ext/tokenizer/tokenizer.c,v
retrieving revision 1.31.2.5.2.7.2.2
diff -u -p -d -r1.31.2.5.2.7.2.2 tokenizer.c
--- ext/tokenizer/tokenizer.c   31 Dec 2007 07:17:16 -0000      1.31.2.5.2.7.2.2
+++ ext/tokenizer/tokenizer.c   30 Jan 2008 12:13:07 -0000
@@ -178,7 +178,7 @@ static void tokenize(zval *return_value 
                        MAKE_STD_ZVAL(keyword);
                        array_init(keyword);
                        add_next_index_long(keyword, token_type);
-                       if (token_type == T_END_HEREDOC) {
+                       if (token_type == T_END_HEREDOC || token_type == 
T_END_NOWDOC) {
                                if (CG(increment_lineno)) {
                                        token_line = ++CG(zend_lineno);
                                        CG(increment_lineno) = 0;
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.799
diff -u -p -d -r1.799 zend_compile.c
--- Zend/zend_compile.c 29 Jan 2008 00:06:42 -0000      1.799
+++ Zend/zend_compile.c 30 Jan 2008 13:14:17 -0000
@@ -5010,6 +5010,7 @@ again:
                        retval = T_ECHO;
                        break;
                case T_END_HEREDOC:
+               case T_END_NOWDOC:
                        efree(Z_STRVAL(zendlval->u.constant));
                        break;
        }
Index: Zend/zend_highlight.c
===================================================================
RCS file: /repository/ZendEngine2/zend_highlight.c,v
retrieving revision 1.61
diff -u -p -d -r1.61 zend_highlight.c
--- Zend/zend_highlight.c       31 Dec 2007 07:12:07 -0000      1.61
+++ Zend/zend_highlight.c       30 Jan 2008 13:14:17 -0000
@@ -134,6 +134,7 @@ ZEND_API void zend_highlight(zend_syntax
                }
                switch (token_type) {
                        case T_END_HEREDOC:
+                       case T_END_NOWDOC:
                                zend_html_puts(Z_STRVAL(token), Z_STRLEN(token) 
TSRMLS_CC);
                                break;
                        default:
@@ -155,7 +156,7 @@ ZEND_API void zend_highlight(zend_syntax
                                        efree(Z_UNIVAL(token).v);
                                        break;
                        }
-               } else if (token_type == T_END_HEREDOC) {
+               } else if (token_type == T_END_HEREDOC || token_type == 
T_END_NOWDOC) {
                        efree(Z_UNIVAL(token).v);
                }
                Z_TYPE(token) = 0;
@@ -207,6 +208,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(Z_STRVAL(token));
                                /* read the following character, either newline 
or ; */
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.199
diff -u -p -d -r1.199 zend_language_parser.y
--- Zend/zend_language_parser.y 31 Dec 2007 07:12:07 -0000      1.199
+++ Zend/zend_language_parser.y 30 Jan 2008 13:14:17 -0000
@@ -148,6 +148,8 @@
 %token T_BINARY_HEREDOC
 %token T_NAMESPACE
 %token T_NS_C
+%token T_START_NOWDOC
+%token T_END_NOWDOC
 
 %% /* Rules */
 
@@ -725,6 +727,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; }
 ;
 
 
Index: Zend/zend_language_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_language_scanner.l,v
retrieving revision 1.176
diff -u -p -d -r1.176 zend_language_scanner.l
--- Zend/zend_language_scanner.l        24 Jan 2008 18:08:06 -0000      1.176
+++ Zend/zend_language_scanner.l        30 Jan 2008 13:14:17 -0000
@@ -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
@@ -1409,6 +1412,8 @@ DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"
 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
 %%
@@ -2560,6 +2565,109 @@ HEREDOC_CHARS       ("{"*([^$\n\r\\{]|("
 }
 
 
+%{
+/* 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);
+}
+
+<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 {
+               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);
+               if (!zend_copy_scanner_string(zendlval, yytext, len, 
CG(literal_type), SCNG(output_conv) TSRMLS_CC)) {
+                       return 0;
+               }
+               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 '"';
Index: Zend/tests/nowdoc.inc
===================================================================
RCS file: Zend/tests/nowdoc.inc
diff -N Zend/tests/nowdoc.inc
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc.inc       30 Jan 2008 13:14:17 -0000
@@ -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;
+
+?>
+
Index: Zend/tests/nowdoc_001.phpt
===================================================================
RCS file: Zend/tests/nowdoc_001.phpt
diff -N Zend/tests/nowdoc_001.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_001.phpt  30 Jan 2008 13:14:17 -0000
@@ -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.
Index: Zend/tests/nowdoc_002.phpt
===================================================================
RCS file: Zend/tests/nowdoc_002.phpt
diff -N Zend/tests/nowdoc_002.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_002.phpt  30 Jan 2008 13:14:17 -0000
@@ -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.
Index: Zend/tests/nowdoc_003.phpt
===================================================================
RCS file: Zend/tests/nowdoc_003.phpt
diff -N Zend/tests/nowdoc_003.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_003.phpt  30 Jan 2008 13:14:17 -0000
@@ -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.
Index: Zend/tests/nowdoc_004.phpt
===================================================================
RCS file: Zend/tests/nowdoc_004.phpt
diff -N Zend/tests/nowdoc_004.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_004.phpt  30 Jan 2008 13:14:17 -0000
@@ -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}.
Index: Zend/tests/nowdoc_005.phpt
===================================================================
RCS file: Zend/tests/nowdoc_005.phpt
diff -N Zend/tests/nowdoc_005.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_005.phpt  30 Jan 2008 13:14:17 -0000
@@ -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.
Index: Zend/tests/nowdoc_006.phpt
===================================================================
RCS file: Zend/tests/nowdoc_006.phpt
diff -N Zend/tests/nowdoc_006.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_006.phpt  30 Jan 2008 13:14:17 -0000
@@ -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}.
Index: Zend/tests/nowdoc_007.phpt
===================================================================
RCS file: Zend/tests/nowdoc_007.phpt
diff -N Zend/tests/nowdoc_007.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_007.phpt  30 Jan 2008 13:14:17 -0000
@@ -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}.
Index: Zend/tests/nowdoc_008.phpt
===================================================================
RCS file: Zend/tests/nowdoc_008.phpt
diff -N Zend/tests/nowdoc_008.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_008.phpt  30 Jan 2008 13:14:17 -0000
@@ -0,0 +1,17 @@
+--TEST--
+empty doc test (nowdoc)
+--FILE--
+<?php
+
+require_once 'nowdoc.inc';
+
+print <<<'ENDOFNOWDOC'
+ENDOFNOWDOC;
+
+$x = <<<'ENDOFNOWDOC'
+ENDOFNOWDOC;
+
+print "{$x}";
+
+?>
+--EXPECT--
Index: Zend/tests/nowdoc_009.phpt
===================================================================
RCS file: Zend/tests/nowdoc_009.phpt
diff -N Zend/tests/nowdoc_009.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_009.phpt  30 Jan 2008 13:14:17 -0000
@@ -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;
+
Index: Zend/tests/nowdoc_010.phpt
===================================================================
RCS file: Zend/tests/nowdoc_010.phpt
diff -N Zend/tests/nowdoc_010.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_010.phpt  30 Jan 2008 13:14:17 -0000
@@ -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
+
Index: Zend/tests/nowdoc_011.phpt
===================================================================
RCS file: Zend/tests/nowdoc_011.phpt
diff -N Zend/tests/nowdoc_011.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_011.phpt  30 Jan 2008 13:14:17 -0000
@@ -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.
Index: Zend/tests/nowdoc_012.phpt
===================================================================
RCS file: Zend/tests/nowdoc_012.phpt
diff -N Zend/tests/nowdoc_012.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_012.phpt  30 Jan 2008 13:14:17 -0000
@@ -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
Index: Zend/tests/nowdoc_013.phpt
===================================================================
RCS file: Zend/tests/nowdoc_013.phpt
diff -N Zend/tests/nowdoc_013.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_013.phpt  30 Jan 2008 13:14:17 -0000
@@ -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>
Index: Zend/tests/nowdoc_014.phpt
===================================================================
RCS file: Zend/tests/nowdoc_014.phpt
diff -N Zend/tests/nowdoc_014.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_014.phpt  30 Jan 2008 13:14:17 -0000
@@ -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>
Index: Zend/tests/nowdoc_015.phpt
===================================================================
RCS file: Zend/tests/nowdoc_015.phpt
diff -N Zend/tests/nowdoc_015.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ Zend/tests/nowdoc_015.phpt  30 Jan 2008 13:14:17 -0000
@@ -0,0 +1,99 @@
+--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
+--UEXPECT--
+6
+unicode(0) ""
+10
+unicode(0) ""
+14
+unicode(4) "test"
+19
+unicode(4) "test"
+24
+unicode(20) "test1
+test2
+
+test3
+
+"
+34
+unicode(20) "test1
+test2
+
+test3
+
+"
+44
+ok
Index: ext/tokenizer/tokenizer.c
===================================================================
RCS file: /repository/php-src/ext/tokenizer/tokenizer.c,v
retrieving revision 1.45
diff -u -p -d -r1.45 tokenizer.c
--- ext/tokenizer/tokenizer.c   31 Dec 2007 07:12:17 -0000      1.45
+++ ext/tokenizer/tokenizer.c   30 Jan 2008 13:14:18 -0000
@@ -180,7 +180,7 @@ static void tokenize(zval *return_value 
                        MAKE_STD_ZVAL(keyword);
                        array_init(keyword);
                        add_next_index_long(keyword, token_type);
-                       if (token_type == T_END_HEREDOC) {
+                       if (token_type == T_END_HEREDOC || token_type == 
T_END_NOWDOC) {
                                if (CG(increment_lineno)) {
                                        token_line = ++CG(zend_lineno);
                                        CG(increment_lineno) = 0;

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to