Index: zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.40
diff -u -r1.647.2.27.2.40 zend_compile.c
--- zend_compile.c	18 May 2007 13:12:03 -0000	1.647.2.27.2.40
+++ zend_compile.c	23 May 2007 09:28:00 -0000
@@ -928,15 +928,15 @@
 }
 
 
-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;
 	*result = opline->result;
-	SET_UNUSED(opline->op1);
 	SET_UNUSED(opline->op2);
 }
 
@@ -970,35 +970,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;
 	*result = opline->result;
 }
Index: zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.12
diff -u -r1.316.2.8.2.12 zend_compile.h
--- zend_compile.h	18 May 2007 13:12:04 -0000	1.316.2.8.2.12
+++ zend_compile.h	23 May 2007 09:22:31 -0000
@@ -391,7 +391,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.160.2.4.2.6
diff -u -r1.160.2.4.2.6 zend_language_parser.y
--- zend_language_parser.y	18 May 2007 18:36:04 -0000	1.160.2.4.2.6
+++ 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 ','
@@ -616,10 +617,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; }
-	|	'`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
+	|	'`' backticks_list { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
 	|	T_PRINT expr  { zend_do_print(&$$, &$2 TSRMLS_CC); }
 ;
 
+backticks_list:
+		'`' { $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); ZVAL_EMPTY_STRING(&$$.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
@@ -680,6 +686,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; }
@@ -687,6 +694,11 @@
 	|	T_FUNC_C					{ $$ = $1; }
 ;
 
+static_heredoc:
+		T_START_HEREDOC T_END_HEREDOC	{ $$.op_type = IS_CONST; INIT_PZVAL(&$$.u.constant); ZVAL_EMPTY_STRING(&$$.u.constant); }
+	|	T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC	{ $$ = $2; }
+;
+
 
 static_scalar: /* compile-time evaluated scalars */
 		common_scalar		{ $$ = $1; }
@@ -867,8 +879,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.59.2.29.2.45
diff -u -r1.59.2.29.2.45 zend_vm_def.h
--- zend_vm_def.h	18 May 2007 13:12:04 -0000	1.59.2.29.2.45
+++ zend_vm_def.h	23 May 2007 09:20:00 -0000
@@ -1578,14 +1578,27 @@
 
 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) != IS_STRING) {
+		zend_make_printable_zval(op1, &op1_copy, &use_copy);
+	}
 
-	tmp->value.str.val = emalloc(1);
-	tmp->value.str.val[0] = 0;
-	tmp->value.str.len = 0;
+	if (use_copy) {
+		*tmp = op1_copy;
+	} else {
+		*tmp = *op1;
+		zval_copy_ctor(tmp);
+	}
 	tmp->refcount = 1;
-	tmp->type = IS_STRING;
 	tmp->is_ref = 0;
+
+	FREE_OP1();
 	ZEND_VM_NEXT_OPCODE();
 }
 
