Skip to content

Commit 80d2409

Browse files
committed
Improved compilation of heredocs and interpolated strings. (Matt, Dmitry)
1 parent 6d41d02 commit 80d2409

File tree

9 files changed

+378
-308
lines changed

9 files changed

+378
-308
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2007, PHP 5.2.3
4+
- Improved compilation of heredocs and interpolated strings. (Matt, Dmitry)
45
- Optimized out a couple of per-request syscalls (Rasmus)
56
- Upgraded SQLite 3 to version 3.3.16 (Ilia)
67
- Added PDO::FETCH_KEY_PAIR mode that will fetch a 2 column result set into

Zend/zend_compile.c

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -941,24 +941,25 @@ void zend_do_init_string(znode *result TSRMLS_DC)
941941
}
942942

943943

944-
void zend_do_add_char(znode *result, znode *op1, znode *op2 TSRMLS_DC)
945-
{
946-
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
947-
948-
opline->opcode = ZEND_ADD_CHAR;
949-
opline->op1 = *op1;
950-
opline->op2 = *op2;
951-
opline->op2.op_type = IS_CONST;
952-
opline->result = opline->op1;
953-
*result = opline->result;
954-
}
955-
956-
957944
void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC)
958945
{
959-
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
946+
zend_op *opline;
947+
948+
if (Z_STRLEN(op2->u.constant) > 1) {
949+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
950+
opline->opcode = ZEND_ADD_STRING;
951+
} else if (Z_STRLEN(op2->u.constant) == 1) {
952+
int ch = *Z_STRVAL(op2->u.constant);
960953

961-
opline->opcode = ZEND_ADD_STRING;
954+
/* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
955+
efree(Z_STRVAL(op2->u.constant));
956+
ZVAL_LONG(&op2->u.constant, ch);
957+
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
958+
opline->opcode = ZEND_ADD_CHAR;
959+
} else { /* String can be empty after a variable at the end of a heredoc */
960+
efree(Z_STRVAL(op2->u.constant));
961+
return;
962+
}
962963
opline->op1 = *op1;
963964
opline->op2 = *op2;
964965
opline->op2.op_type = IS_CONST;
@@ -3930,24 +3931,6 @@ void zend_do_declare_end(znode *declare_token TSRMLS_DC)
39303931
}
39313932

39323933

3933-
void zend_do_end_heredoc(TSRMLS_D)
3934-
{
3935-
int opline_num = get_next_op_number(CG(active_op_array))-1;
3936-
zend_op *opline = &CG(active_op_array)->opcodes[opline_num];
3937-
3938-
if (opline->opcode != ZEND_ADD_STRING) {
3939-
return;
3940-
}
3941-
3942-
opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
3943-
if (opline->op2.u.constant.value.str.len>0) {
3944-
if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') {
3945-
opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
3946-
}
3947-
}
3948-
}
3949-
3950-
39513934
void zend_do_exit(znode *result, znode *message TSRMLS_DC)
39523935
{
39533936
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -4136,12 +4119,12 @@ int zendlex(znode *zendlval TSRMLS_DC)
41364119
{
41374120
int retval;
41384121

4139-
again:
41404122
if (CG(increment_lineno)) {
41414123
CG(zend_lineno)++;
41424124
CG(increment_lineno) = 0;
41434125
}
41444126

4127+
again:
41454128
Z_TYPE(zendlval->u.constant) = IS_LONG;
41464129
retval = lex_scan(&zendlval->u.constant TSRMLS_CC);
41474130
switch (retval) {
@@ -4152,8 +4135,7 @@ int zendlex(znode *zendlval TSRMLS_DC)
41524135
goto again;
41534136

41544137
case T_CLOSE_TAG:
4155-
if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1]=='\n'
4156-
|| (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-2]=='\r' && LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1])) {
4138+
if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
41574139
CG(increment_lineno) = 1;
41584140
}
41594141
retval = ';'; /* implicit ; */

Zend/zend_compile.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,6 @@ void zend_check_writable_variable(znode *variable);
392392
void zend_do_free(znode *op1 TSRMLS_DC);
393393

394394
void zend_do_init_string(znode *result TSRMLS_DC);
395-
void zend_do_add_char(znode *result, znode *op1, znode *op2 TSRMLS_DC);
396395
void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC);
397396
void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC);
398397

@@ -488,8 +487,6 @@ void zend_do_declare_begin(TSRMLS_D);
488487
void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC);
489488
void zend_do_declare_end(znode *declare_token TSRMLS_DC);
490489

491-
void zend_do_end_heredoc(TSRMLS_D);
492-
493490
void zend_do_exit(znode *result, znode *message TSRMLS_DC);
494491

495492
void zend_do_begin_silence(znode *strudel_token TSRMLS_DC);

Zend/zend_language_parser.y

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
* LALR shift/reduce conflicts and how they are resolved:
2525
*
2626
* - 2 shift/reduce conflicts due to the dangeling elseif/else ambiguity. Solved by shift.
27-
* - 1 shift/reduce conflict due to arrays within encapsulated strings. Solved by shift.
28-
* - 1 shift/reduce conflict due to objects within encapsulated strings. Solved by shift.
2927
*
3028
*/
3129

@@ -49,7 +47,7 @@
4947
%}
5048

5149
%pure_parser
52-
%expect 4
50+
%expect 2
5351

5452
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
5553
%left ','
@@ -709,8 +707,7 @@ scalar:
709707
| class_constant { $$ = $1; }
710708
| common_scalar { $$ = $1; }
711709
| '"' encaps_list '"' { $$ = $2; }
712-
| '\'' encaps_list '\'' { $$ = $2; }
713-
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; zend_do_end_heredoc(TSRMLS_C); }
710+
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; }
714711
;
715712

716713

@@ -869,16 +866,7 @@ non_empty_array_pair_list:
869866

870867
encaps_list:
871868
encaps_list encaps_var { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
872-
| encaps_list T_STRING { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
873-
| encaps_list T_NUM_STRING { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
874869
| encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
875-
| encaps_list T_CHARACTER { zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); }
876-
| encaps_list T_BAD_CHARACTER { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
877-
| encaps_list '[' { Z_LVAL($2.u.constant) = (long) '['; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); }
878-
| encaps_list ']' { Z_LVAL($2.u.constant) = (long) ']'; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); }
879-
| encaps_list '{' { Z_LVAL($2.u.constant) = (long) '{'; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); }
880-
| encaps_list '}' { Z_LVAL($2.u.constant) = (long) '}'; zend_do_add_char(&$$, &$1, &$2 TSRMLS_CC); }
881-
| 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); }
882870
| /* empty */ { zend_do_init_string(&$$ TSRMLS_CC); }
883871

884872
;

0 commit comments

Comments
 (0)