Index: zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.749
diff -u -r1.749 zend_compile.c
--- zend_compile.c	18 May 2007 13:12:47 -0000	1.749
+++ zend_compile.c	23 May 2007 09:27:59 -0000
@@ -975,16 +975,16 @@
 }
 
 
-void zend_do_init_string(znode *result TSRMLS_DC)
+void zend_do_init_string(znode *result, znode *op1 TSRMLS_DC)
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
 	opline->opcode = ZEND_INIT_STRING;
 	opline->result.op_type = IS_TMP_VAR;
 	opline->result.u.var = get_temporary_variable(CG(active_op_array));
+	opline->op1 = *op1;
 	opline->extended_value = CG(literal_type);
 	*result = opline->result;
-	SET_UNUSED(opline->op1);
 	SET_UNUSED(opline->op2);
 }
 
@@ -1018,35 +1018,11 @@
 
 void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC)
 {
-	zend_op *opline;
-
-	if (op1->op_type == IS_CONST) {
-		opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-		opline->opcode = ZEND_INIT_STRING;
-		opline->result.op_type = IS_TMP_VAR;
-		opline->result.u.var = get_temporary_variable(CG(active_op_array));
-		*result = opline->result;
-		SET_UNUSED(opline->op1);
-		SET_UNUSED(opline->op2);
-
-		if (Z_STRLEN(op1->u.constant)>0) {
-			opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-			opline->opcode = ZEND_ADD_STRING;
-			opline->result = *result;
-			opline->op1 = *result;
-			opline->op2 = *op1;
-			opline->result = opline->op1;
-		} else {
-			zval_dtor(&op1->u.constant);
-		}
-	} else {
-		*result = *op1;
-	}
+	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-	opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 	opline->opcode = ZEND_ADD_VAR;
-	opline->result = *result;
-	opline->op1 = *result;
+	opline->result = *op1;
+	opline->op1 = *op1;
 	opline->op2 = *op2;
 	opline->extended_value = CG(literal_type);
 	*result = opline->result;
Index: zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.357
diff -u -r1.357 zend_compile.h
--- zend_compile.h	18 May 2007 13:12:47 -0000	1.357
+++ zend_compile.h	23 May 2007 09:22:30 -0000
@@ -403,7 +403,7 @@
 
 void zend_do_free(znode *op1 TSRMLS_DC);
 
-void zend_do_init_string(znode *result TSRMLS_DC);
+void zend_do_init_string(znode *result, znode *op1 TSRMLS_DC);
 void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
 
Index: zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.183
diff -u -r1.183 zend_language_parser.y
--- zend_language_parser.y	18 May 2007 20:48:19 -0000	1.183
+++ zend_language_parser.y	23 May 2007 09:08:20 -0000
@@ -23,7 +23,8 @@
 /*
  * LALR shift/reduce conflicts and how they are resolved:
  *
- * - 2 shift/reduce conflicts due to the dangeling elseif/else ambiguity.  Solved by shift.
+ * - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift.
+ * - 1 shift/reduce conflict due to T_ENCAPSED_AND_WHITESPACE after start of heredoc. Solved by shift.
  *
  */
 
@@ -47,7 +48,7 @@
 %}
 
 %pure_parser
-%expect 2
+%expect 3
 
 %left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
 %left ','
@@ -625,10 +626,15 @@
 	|	'@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
 	|	scalar				{ $$ = $1; }
 	|	T_ARRAY '(' array_pair_list ')' { $$ = $3; }
-	|	'`' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '`' { zend_do_shell_exec(&$$, &$3 TSRMLS_CC); }
+	|	'`' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } backticks_list { zend_do_shell_exec(&$$, &$3 TSRMLS_CC); }
 	|	T_PRINT expr  { zend_do_print(&$$, &$2 TSRMLS_CC); }
 ;
 
+backticks_list:
+		'`' { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); ZVAL_EMPTY_TEXT(&$$.u.constant); zend_do_init_string(&$$, &$$ TSRMLS_CC); }
+	|	encaps_list '`' { $$ = $1; }
+;
+
 function_call:
 		T_STRING	'(' { $2.u.opline_num = zend_do_begin_function_call(&$1 TSRMLS_CC); }
 				function_call_parameter_list
@@ -689,6 +695,7 @@
 		T_LNUMBER 					{ $$ = $1; }
 	|	T_DNUMBER 					{ $$ = $1; }
 	|	T_CONSTANT_ENCAPSED_STRING	{ $$ = $1; }
+	|	static_heredoc				{ $$ = $1; }
 	|	T_LINE 						{ $$ = $1; }
 	|	T_FILE 						{ $$ = $1; }
 	|	T_CLASS_C					{ $$ = $1; }
@@ -696,6 +703,16 @@
 	|	T_FUNC_C					{ $$ = $1; }
 ;
 
+static_heredoc:
+		start_heredoc T_END_HEREDOC	{ $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); if (CG(literal_type) == IS_UNICODE) { ZVAL_EMPTY_UNICODE(&$$.u.constant); } else { ZVAL_EMPTY_STRING(&$$.u.constant); } }
+	|	start_heredoc T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; }
+;
+
+start_heredoc:
+		T_START_HEREDOC  { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; }
+	|	T_BINARY_HEREDOC { CG(literal_type) = IS_STRING; }
+;
+
 
 static_scalar: /* compile-time evaluated scalars */
 		common_scalar		{ $$ = $1; }
@@ -716,9 +733,8 @@
 	|	class_constant	{ $$ = $1; }
 	|	common_scalar			{ $$ = $1; }
 	|	'"' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '"' { $$ = $3; }
-	|	T_START_HEREDOC { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; }
 	|	T_BINARY_DOUBLE { CG(literal_type) = IS_STRING; } encaps_list '"' { $$ = $3; }
-	|	T_BINARY_HEREDOC { CG(literal_type) = IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; }
+	|	start_heredoc encaps_list T_END_HEREDOC { $$ = $2; }
 ;
 
 
@@ -878,8 +894,8 @@
 encaps_list:
 		encaps_list encaps_var { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);  zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
 	|	encaps_list T_ENCAPSED_AND_WHITESPACE	{ zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
-	|	/* empty */			{ zend_do_init_string(&$$ TSRMLS_CC); }
-
+	|	encaps_var			{ zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);  zend_do_init_string(&$$, &$1 TSRMLS_CC); }
+	|	T_ENCAPSED_AND_WHITESPACE			{ zend_do_init_string(&$$, &$1 TSRMLS_CC); }
 ;
 
 
Index: zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.168
diff -u -r1.168 zend_vm_def.h
--- zend_vm_def.h	18 May 2007 13:12:47 -0000	1.168
+++ zend_vm_def.h	23 May 2007 09:20:00 -0000
@@ -1618,21 +1618,31 @@
 
 ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
 {
-	zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
+	zend_op *opline = EX(opline);
+	zend_free_op free_op1;
+	zval *tmp = &EX_T(opline->result.u.var).tmp_var;
+	zval *op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+	zval op1_copy;
+	int use_copy = 0;
+
+	if (Z_TYPE_P(op1) != opline->extended_value) {
+		if (opline->extended_value == IS_UNICODE) {
+			zend_make_unicode_zval(op1, &op1_copy, &use_copy);
+		} else {
+			zend_make_string_zval(op1, &op1_copy, &use_copy);
+		}
+	}
 
-	if (EX(opline)->extended_value == IS_UNICODE) {
-		Z_USTRVAL_P(tmp) = eumalloc(1);
-		Z_USTRVAL_P(tmp)[0] = 0;
-		Z_USTRLEN_P(tmp) = 0;
-		Z_TYPE_P(tmp) = IS_UNICODE;
-	} else {
-		Z_STRVAL_P(tmp) = emalloc(1);
-		Z_STRVAL_P(tmp)[0] = 0;
-		Z_STRLEN_P(tmp) = 0;
-		Z_TYPE_P(tmp) = IS_STRING;
+	if (use_copy) {
+		*tmp = op1_copy;
+	} else {
+		*tmp = *op1;
+		zval_copy_ctor(tmp);
 	}
 	tmp->refcount = 1;
 	tmp->is_ref = 0;
+
+	FREE_OP1();
 	ZEND_VM_NEXT_OPCODE();
 }
 
