Index: zend_compile.c =================================================================== RCS file: /repository/ZendEngine2/zend_compile.c,v retrieving revision 1.647.2.27.2.34 diff -u -r1.647.2.27.2.34 zend_compile.c --- zend_compile.c 4 Apr 2007 00:42:42 -0000 1.647.2.27.2.34 +++ zend_compile.c 11 Apr 2007 09:30:00 -0000 @@ -4123,12 +4123,12 @@ { int retval; -again: if (CG(increment_lineno)) { CG(zend_lineno)++; CG(increment_lineno) = 0; } +again: Z_TYPE(zendlval->u.constant) = IS_LONG; retval = lex_scan(&zendlval->u.constant TSRMLS_CC); switch (retval) { @@ -4139,8 +4139,7 @@ goto again; case T_CLOSE_TAG: - if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1]=='\n' - || (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-2]=='\r' && LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1])) { + if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') { CG(increment_lineno) = 1; } retval = ';'; /* implicit ; */ Index: zend_language_parser.y =================================================================== RCS file: /repository/ZendEngine2/zend_language_parser.y,v retrieving revision 1.160.2.4.2.4 diff -u -r1.160.2.4.2.4 zend_language_parser.y --- zend_language_parser.y 4 Apr 2007 00:42:42 -0000 1.160.2.4.2.4 +++ zend_language_parser.y 11 Apr 2007 08:45:02 -0000 @@ -24,8 +24,6 @@ * LALR shift/reduce conflicts and how they are resolved: * * - 2 shift/reduce conflicts due to the dangeling elseif/else ambiguity. Solved by shift. - * - 1 shift/reduce conflict due to arrays within encapsulated strings. Solved by shift. - * - 1 shift/reduce conflict due to objects within encapsulated strings. Solved by shift. * */ @@ -49,7 +47,7 @@ %} %pure_parser -%expect 4 +%expect 2 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE %left ',' @@ -709,7 +707,6 @@ | class_constant { $$ = $1; } | common_scalar { $$ = $1; } | '"' encaps_list '"' { $$ = $2; } - | '\'' encaps_list '\'' { $$ = $2; } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; zend_do_end_heredoc(TSRMLS_C); } ; @@ -874,11 +871,6 @@ | encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); } | encaps_list T_CHARACTER { zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); } | encaps_list T_BAD_CHARACTER { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); } - | encaps_list '[' { Z_LVAL($2.u.constant) = (long) '['; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); } - | encaps_list ']' { Z_LVAL($2.u.constant) = (long) ']'; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); } - | encaps_list '{' { Z_LVAL($2.u.constant) = (long) '{'; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); } - | encaps_list '}' { Z_LVAL($2.u.constant) = (long) '}'; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); } - | encaps_list T_OBJECT_OPERATOR { znode tmp; Z_LVAL($2.u.constant) = (long) '-'; zend_do_add_char(&tmp, &$1, &$2 TSRMLS_CC); Z_LVAL($2.u.constant) = (long) '>'; zend_do_add_char(&$$, &tmp, &$2 TSRMLS_CC); } | /* empty */ { zend_do_init_string(&$$ TSRMLS_CC); } ; Index: zend_language_scanner.l =================================================================== RCS file: /repository/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.131.2.11.2.9 diff -u -r1.131.2.11.2.9 zend_language_scanner.l --- zend_language_scanner.l 24 Feb 2007 02:17:23 -0000 1.131.2.11.2.9 +++ zend_language_scanner.l 12 Apr 2007 09:20:03 -0000 @@ -35,11 +35,13 @@ %x ST_IN_SCRIPTING %x ST_DOUBLE_QUOTES -%x ST_SINGLE_QUOTE %x ST_BACKQUOTE %x ST_HEREDOC +%x ST_START_HEREDOC +%x ST_END_HEREDOC %x ST_LOOKING_FOR_PROPERTY %x ST_LOOKING_FOR_VARNAME +%x ST_VAR_OFFSET %x ST_COMMENT %x ST_DOC_COMMENT %x ST_ONE_LINE_COMMENT @@ -96,9 +98,7 @@ char *p = (s), *boundary = p+(l); \ \ while (pvalue.str.val = (char *)estrndup(yytext, yyleng); \ zendlval->value.str.len = yyleng; #endif /* ZEND_MULTIBYTE */ + +int zend_scan_escape_string(zval *zendlval, char quote_type, int type TSRMLS_DC) +{ + register char *s, *t; + char *end; + + if (type == T_CONSTANT_ENCAPSED_STRING) { + int bprefix = (yytext[0] != '"') ? 1 : 0; + + zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2); + zendlval->value.str.len = yyleng-bprefix-2; + } else { + zendlval->value.str.val = estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + } + + zendlval->type = IS_STRING; + + /* convert escape sequences */ + s = t = zendlval->value.str.val; + end = s+zendlval->value.str.len; + while (s=end) { + continue; + } + switch(*s) { + case 'n': + *t++ = '\n'; + zendlval->value.str.len--; + break; + case 'r': + *t++ = '\r'; + zendlval->value.str.len--; + break; + case 't': + *t++ = '\t'; + zendlval->value.str.len--; + break; + case '"': + case '`': + if (*s != quote_type) { + *t++ = '\\'; + *t++ = *s; + break; + } + case '\\': + case '$': + *t++ = *s; + zendlval->value.str.len--; + break; + case 'x': + case 'X': + if (ZEND_IS_HEX(*(s+1))) { + char hex_buf[3] = { 0, 0, 0 }; + + zendlval->value.str.len--; /* for the 'x' */ + + hex_buf[0] = *(++s); + zendlval->value.str.len--; + if (ZEND_IS_HEX(*(s+1))) { + hex_buf[1] = *(++s); + zendlval->value.str.len--; + } + *t++ = (char) strtol(hex_buf, NULL, 16); + } else { + *t++ = '\\'; + *t++ = *s; + } + break; + default: + /* check for an octal */ + if (ZEND_IS_OCT(*s)) { + char octal_buf[4] = { 0, 0, 0, 0 }; + + octal_buf[0] = *s; + zendlval->value.str.len--; + if (ZEND_IS_OCT(*(s+1))) { + octal_buf[1] = *(++s); + zendlval->value.str.len--; + if (ZEND_IS_OCT(*(s+1))) { + octal_buf[2] = *(++s); + zendlval->value.str.len--; + } + } + *t++ = (char) strtol(octal_buf, NULL, 8); + } else { + *t++ = '\\'; + *t++ = *s; + } + break; + } + } else { + *t++ = *s; + } + + if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) { + CG(zend_lineno)++; + } + s++; + } + *t = 0; + +#ifdef ZEND_MULTIBYTE + if (SCNG(output_filter)) { + s = zendlval->value.str.val; + SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), s, zendlval->value.str.len TSRMLS_CC); + efree(s); + } +#endif /* ZEND_MULTIBYTE */ + + return type; +} + %} LNUM [0-9]+ @@ -799,11 +914,23 @@ WHITESPACE [ \n\r\t]+ TABS_AND_SPACES [ \t]* TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@] -ENCAPSED_TOKENS [\[\]{}$] -ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+ ANY_CHAR (.|[\n]) NEWLINE ("\r"|"\n"|"\r\n") +DOUBLE_QUOTES_LITERAL_DOLLAR ("$"+([^a-zA-Z_\x7f-\xff$"\\{]|("\\"{ANY_CHAR}))) +BACKQUOTE_LITERAL_DOLLAR ("$"+([^a-zA-Z_\x7f-\xff$`\\{]|("\\"{ANY_CHAR}))) +HEREDOC_LITERAL_DOLLAR ("$"+([^a-zA-Z_\x7f-\xff$\n\r\\{]|("\\"[^\n\r]))) + +HEREDOC_NEWLINE ((({LABEL}";"?((("{"+|"$"+)"\\"?)|"\\"))|(("{"*|"$"*)"\\"?)){NEWLINE}) + +HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR (("{"+[^$\n\r\\{])|("{"*"\\"[^\n\r])|{HEREDOC_LITERAL_DOLLAR}) +HEREDOC_NON_LABEL ([^a-zA-Z_\x7f-\xff$\n\r\\{]|{HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR}) +HEREDOC_LABEL_NO_NEWLINE ({LABEL}([^a-zA-Z0-9_\x7f-\xff;$\n\r\\{]|(";"[^$\n\r\\{])|(";"?{HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR}))) + +DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{DOUBLE_QUOTES_LITERAL_DOLLAR}) +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}))) + %option noyylineno %option noyywrap %% @@ -948,11 +1075,15 @@ return T_IMPLEMENTS; } -"->" { +"->" { yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); return T_OBJECT_OPERATOR; } +"->" { + return T_OBJECT_OPERATOR; +} + {LABEL} { yy_pop_state(TSRMLS_C); zend_copy_value(zendlval, yytext, yyleng); @@ -1278,7 +1409,26 @@ } } -{LNUM}|{HNUM} { /* treat numbers (almost) as strings inside encapsulated strings */ + +["] { + BEGIN(ST_IN_SCRIPTING); + return '\"'; +} + + +[`] { + BEGIN(ST_IN_SCRIPTING); + return '`'; +} + + +{ANY_CHAR} { + zendlval->value.lval = (long) yytext[0]; + HANDLE_NEWLINE(yytext[0]); + return T_CHARACTER; +} + +{LNUM}|{HNUM} { /* treat numbers (almost) as strings inside encapsulated strings */ zendlval->value.str.val = (char *)estrndup(yytext, yyleng); zendlval->value.str.len = yyleng; zendlval->type = IS_STRING; @@ -1441,19 +1591,56 @@ return T_OPEN_TAG; } -"$"{LABEL} { +"$"{LABEL} { + zend_copy_value(zendlval, (yytext+1), (yyleng-1)); + zendlval->type = IS_STRING; + return T_VARIABLE; +} + +"$"{LABEL}"->"[a-zA-Z_\x7f-\xff] { + yyless(yyleng - 3); + yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); + + zend_copy_value(zendlval, (yytext+1), (yyleng-1)); + zendlval->type = IS_STRING; + return T_VARIABLE; +} + +"$"{LABEL}"[" { + yyless(yyleng - 1); + yy_push_state(ST_VAR_OFFSET TSRMLS_CC); + zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } +"[" { + return '['; +} + +"]" { + yy_pop_state(TSRMLS_C); + return ']'; +} + +{TOKENS}|[{}] { + /* Bad token, but will allow a more explicit parse error */ + return yytext[0]; +} + +[ \n\r\t'"`\\#] { + yyless(0); + yy_pop_state(TSRMLS_C); +} + {LABEL} { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -{LABEL} { +{LABEL} { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; @@ -1577,106 +1764,19 @@ } -("b"?["]([^$"\\]|("\\".))*["]) { - register char *s, *t; - char *end; - int bprefix = (*yytext == 'b') ? 1 : 0; - - zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2); - zendlval->value.str.len = yyleng-bprefix-2; - zendlval->type = IS_STRING; - HANDLE_NEWLINES(yytext, yyleng); - - /* convert escape sequences */ - s = t = zendlval->value.str.val; - end = s+zendlval->value.str.len; - while (s=end) { - continue; - } - switch(*s) { - case 'n': - *t++ = '\n'; - zendlval->value.str.len--; - break; - case 'r': - *t++ = '\r'; - zendlval->value.str.len--; - break; - case 't': - *t++ = '\t'; - zendlval->value.str.len--; - break; - case '\\': - case '$': - case '"': - *t++ = *s; - zendlval->value.str.len--; - break; - default: - /* check for an octal */ - if (ZEND_IS_OCT(*s)) { - char octal_buf[4] = { 0, 0, 0, 0 }; - - octal_buf[0] = *s; - zendlval->value.str.len--; - if ((s+1)value.str.len--; - if ((s+1)value.str.len--; - } - } - *t++ = (char) strtol(octal_buf, NULL, 8); - } else if (*s=='x' && (s+1)value.str.len--; /* for the 'x' */ - - hex_buf[0] = *(++s); - zendlval->value.str.len--; - if ((s+1)value.str.len--; - } - *t++ = (char) strtol(hex_buf, NULL, 16); - } else { - *t++ = '\\'; - *t++ = *s; - } - break; - } - s++; - } else { - *t++ = *s++; - } - } - *t = 0; - -#ifdef ZEND_MULTIBYTE - if (SCNG(output_filter)) { - s = zendlval->value.str.val; - SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), s, zendlval->value.str.len TSRMLS_CC); - efree(s); - } -#endif /* ZEND_MULTIBYTE */ - - return T_CONSTANT_ENCAPSED_STRING; +(b?["]{DOUBLE_QUOTES_CHARS}*("{"*|"$"*)["]) { + return zend_scan_escape_string(zendlval, '"', T_CONSTANT_ENCAPSED_STRING TSRMLS_CC); } -("b"?[']([^'\\]|("\\".))*[']) { +(b?[']([^'\\]|("\\"{ANY_CHAR}))*[']) { register char *s, *t; char *end; - int bprefix = (*yytext == 'b') ? 1 : 0; + int bprefix = (yytext[0] != '\'') ? 1 : 0; zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2); zendlval->value.str.len = yyleng-bprefix-2; zendlval->type = IS_STRING; - HANDLE_NEWLINES(yytext, yyleng); /* convert escape sequences */ s = t = zendlval->value.str.val; @@ -1698,10 +1798,14 @@ *t++ = *s; break; } - s++; } else { - *t++ = *s++; + *t++ = *s; } + + if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) { + CG(zend_lineno)++; + } + s++; } *t = 0; @@ -1725,7 +1829,7 @@ "b"?"<<<"{TABS_AND_SPACES}{LABEL}{NEWLINE} { char *s; - int bprefix = (*yytext == 'b') ? 1 : 0; + int bprefix = (yytext[0] != '<') ? 1 : 0; CG(zend_lineno)++; CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0); @@ -1735,7 +1839,7 @@ CG(heredoc_len)--; } CG(heredoc) = estrndup(s, CG(heredoc_len)); - BEGIN(ST_HEREDOC); + BEGIN(ST_START_HEREDOC); return T_START_HEREDOC; } @@ -1746,112 +1850,73 @@ } -b?['] { - BEGIN(ST_SINGLE_QUOTE); - return '\''; +{ANY_CHAR} { + yyless(0); + BEGIN(ST_HEREDOC); } - -^{LABEL}(";")?{NEWLINE} { - int label_len; - - if (yytext[yyleng-2]=='\r') { - label_len = yyleng-2; - } else { - label_len = yyleng-1; - } +{LABEL}";"?[\n\r] { + int label_len = yyleng - 1; if (yytext[label_len-1]==';') { label_len--; } if (label_len==CG(heredoc_len) && !memcmp(yytext, CG(heredoc), label_len)) { - zendlval->value.str.val = estrndup(yytext, label_len); /* unput destroys yytext */ + zendlval->value.str.val = CG(heredoc); zendlval->value.str.len = label_len; - yyless(yyleng - (yyleng - label_len)); - efree(CG(heredoc)); + yyless(label_len); CG(heredoc)=NULL; CG(heredoc_len)=0; BEGIN(ST_IN_SCRIPTING); return T_END_HEREDOC; } else { - CG(zend_lineno)++; - zend_copy_value(zendlval, yytext, yyleng); - zendlval->type = IS_STRING; - return T_STRING; + yyless(label_len - 1); + yymore(); + BEGIN(ST_HEREDOC); } } +{HEREDOC_CHARS}*{HEREDOC_NEWLINE}+{LABEL}";"?[\n\r] { + char *end = yytext + yyleng - 1; -{ESCAPED_AND_WHITESPACE} { - HANDLE_NEWLINES(yytext, yyleng); - zendlval->value.str.val = (char *) estrndup(yytext, yyleng); - zendlval->value.str.len = yyleng; - zendlval->type = IS_STRING; - return T_ENCAPSED_AND_WHITESPACE; -} - -([^'\\]|\\[^'\\])+ { - HANDLE_NEWLINES(yytext, yyleng); - zend_copy_value(zendlval, yytext, yyleng); - zendlval->type = IS_STRING; - return T_ENCAPSED_AND_WHITESPACE; -} - - -[`]+ { - zend_copy_value(zendlval, yytext, yyleng); - zendlval->type = IS_STRING; - return T_ENCAPSED_AND_WHITESPACE; -} - - -["]+ { - zend_copy_value(zendlval, yytext, yyleng); - zendlval->type = IS_STRING; - return T_ENCAPSED_AND_WHITESPACE; -} - + if (end[-1] == ';') { + end--; + yyleng--; + } -"$"[^a-zA-Z_\x7f-\xff{] { - zendlval->value.lval = (long) yytext[0]; - if (yyleng == 2) { - yyless(1); + if (yyleng > CG(heredoc_len) && !memcmp(end - CG(heredoc_len), CG(heredoc), CG(heredoc_len))) { + yyless(yyleng - 2); + yyleng -= CG(heredoc_len) - 1; + BEGIN(ST_END_HEREDOC); + return zend_scan_escape_string(zendlval, 0, T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); + } else { + yyless(yyleng - 2); + yymore(); } - return T_CHARACTER; } - -{ENCAPSED_TOKENS} { - zendlval->value.lval = (long) yytext[0]; - return yytext[0]; +{ANY_CHAR} { + zendlval->value.str.val = CG(heredoc); + zendlval->value.str.len = CG(heredoc_len); + /* OK to change yytext like this? */ + yytext = zendlval->value.str.val; + yyleng = zendlval->value.str.len; + CG(heredoc) = NULL; + CG(heredoc_len) = 0; + BEGIN(ST_IN_SCRIPTING); + return T_END_HEREDOC; } -"\\{" { - zendlval->value.str.val = estrndup("\\{", sizeof("\\{") - 1); - zendlval->value.str.len = sizeof("\\{") - 1; - zendlval->type = IS_STRING; - return T_STRING; -} "{$" { - zendlval->value.lval = (long) yytext[0]; + zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -"\\'" { - zendlval->value.lval = (long) '\''; - return T_CHARACTER; -} - -"\\\\" { - zendlval->value.lval = (long)'\\'; - return T_CHARACTER; -} - "\\\"" { zendlval->value.lval = (long) '"'; return T_CHARACTER; @@ -1887,8 +1952,11 @@ zendlval->value.lval = (long) '\\'; break; case '$': - zendlval->value.lval = (long) yytext[1]; + zendlval->value.lval = (long) '$'; break; + case '\n': + case '\r': + CG(zend_lineno)++; default: zendlval->value.str.val = estrndup(yytext, yyleng); zendlval->value.str.len = yyleng; @@ -1900,36 +1968,55 @@ } -["'`]+ { - zendlval->value.str.val = (char *) estrndup(yytext, yyleng); - zendlval->value.str.len = yyleng; - zendlval->type = IS_STRING; - return T_ENCAPSED_AND_WHITESPACE; +[{$]["] { + yyless(1); + zendlval->value.lval = (long) yytext[0]; + return T_CHARACTER; } +[{$][`] { + yyless(1); + zendlval->value.lval = (long) yytext[0]; + return T_CHARACTER; +} -["] { - BEGIN(ST_IN_SCRIPTING); - return '\"'; +"{{"|"$$" { + yyless(1); + zendlval->value.lval = (long) yytext[0]; + return T_CHARACTER; } -[`] { - BEGIN(ST_IN_SCRIPTING); - return '`'; +{DOUBLE_QUOTES_CHARS}+ { + return zend_scan_escape_string(zendlval, '"', T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); } +{DOUBLE_QUOTES_CHARS}*("{"{2,}|"$"{2,}|(("{"+|"$"+)["])) { + yyless(yyleng - 1); + return zend_scan_escape_string(zendlval, '"', T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); +} -['] { - BEGIN(ST_IN_SCRIPTING); - return '\''; + +{BACKQUOTE_CHARS}+ { + return zend_scan_escape_string(zendlval, '`', T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); } +{BACKQUOTE_CHARS}*("{"{2,}|"$"{2,}|(("{"+|"$"+)[`])) { + yyless(yyleng - 1); + return zend_scan_escape_string(zendlval, '`', T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); +} -<> { - return 0; + +{HEREDOC_CHARS}*({HEREDOC_NEWLINE}+({LABEL}";"?)?)? { + return zend_scan_escape_string(zendlval, 0, T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); +} + +{HEREDOC_CHARS}*({HEREDOC_NEWLINE}+({LABEL}";"?)?)?("{"{2,}|"$"{2,}) { + yyless(yyleng - 1); + return zend_scan_escape_string(zendlval, 0, T_ENCAPSED_AND_WHITESPACE TSRMLS_CC); } + <> { zend_error(E_COMPILE_WARNING,"Unterminated comment starting line %d", CG(comment_start_line)); return 0; @@ -1937,6 +2024,6 @@ -{ANY_CHAR} { +{ANY_CHAR} { zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); } Index: zend_vm_def.h =================================================================== RCS file: /repository/ZendEngine2/zend_vm_def.h,v retrieving revision 1.59.2.29.2.42 diff -u -r1.59.2.29.2.42 zend_vm_def.h --- zend_vm_def.h 5 Apr 2007 23:48:42 -0000 1.59.2.29.2.42 +++ zend_vm_def.h 12 Apr 2007 09:40:01 -0000 @@ -1619,11 +1619,14 @@ zend_free_op free_op1, free_op2; zval *var = GET_OP2_ZVAL_PTR(BP_VAR_R); zval var_copy; - int use_copy; + int use_copy = 0; - zend_make_printable_zval(var, &var_copy, &use_copy); - if (use_copy) { - var = &var_copy; + if (Z_TYPE_P(var) != IS_STRING) { + zend_make_printable_zval(var, &var_copy, &use_copy); + + if (use_copy) { + var = &var_copy; + } } add_string_to_string( &EX_T(opline->result.u.var).tmp_var, GET_OP1_ZVAL_PTR(BP_VAR_NA),