awk: restore strdup elision optimization in assignment

function                                             old     new   delta
evaluate                                            3339    3387     +48

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2021-07-03 13:29:32 +02:00
parent 90404ed2f6
commit cb042b0582

View File

@ -102,7 +102,7 @@ enum {
#define VF_USER 0x0200 /* 1 = user input (may be numeric string) */ #define VF_USER 0x0200 /* 1 = user input (may be numeric string) */
#define VF_SPECIAL 0x0400 /* 1 = requires extra handling when changed */ #define VF_SPECIAL 0x0400 /* 1 = requires extra handling when changed */
#define VF_WALK 0x0800 /* 1 = variable has alloc'd x.walker list */ #define VF_WALK 0x0800 /* 1 = variable has alloc'd x.walker list */
#define VF_FSTR 0x1000 /* 1 = var::string points to fstring buffer */ #define VF_FSTR 0x1000 /* 1 = don't free() var::string (not malloced, or is owned by something else) */
#define VF_CHILD 0x2000 /* 1 = function arg; x.parent points to source */ #define VF_CHILD 0x2000 /* 1 = function arg; x.parent points to source */
#define VF_DIRTY 0x4000 /* 1 = variable was set explicitly */ #define VF_DIRTY 0x4000 /* 1 = variable was set explicitly */
@ -1371,6 +1371,12 @@ static node *parse_expr(uint32_t term_tc)
cn->a.n = vn->a.n; cn->a.n = vn->a.n;
if (tc & TS_BINOP) { if (tc & TS_BINOP) {
cn->l.n = vn; cn->l.n = vn;
//FIXME: this is the place to detect and reject assignments to non-lvalues.
//Currently we allow "assignments" to consts and temporaries, nonsense like this:
// awk 'BEGIN { "qwe" = 1 }'
// awk 'BEGIN { 7 *= 7 }'
// awk 'BEGIN { length("qwe") = 1 }'
// awk 'BEGIN { (1+1) += 3 }'
expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP; expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP;
if ((t_info & OPCLSMASK) == OC_PGETLINE) { if ((t_info & OPCLSMASK) == OC_PGETLINE) {
/* it's a pipe */ /* it's a pipe */
@ -3043,14 +3049,17 @@ static var *evaluate(node *op, var *res)
case XC( OC_MOVE ): case XC( OC_MOVE ):
debug_printf_eval("MOVE\n"); debug_printf_eval("MOVE\n");
/* if source is a temporary string, jusk relink it to dest */ /* if source is a temporary string, jusk relink it to dest */
//Disabled: if R.v is numeric but happens to have cached R.v->string, if (R.v == TMPVAR1
//then L.v ends up being a string, which is wrong && !(R.v->type & VF_NUMBER)
// if (R.v == TMPVAR1 && R.v->string) { /* Why check !NUMBER? if R.v is a number but has cached R.v->string,
// res = setvar_p(L.v, R.v->string); * L.v ends up a string, which is wrong */
// R.v->string = NULL; /*&& R.v->string - always not NULL (right?) */
// } else { ) {
res = setvar_p(L.v, R.v->string); /* avoids strdup */
R.v->string = NULL;
} else {
res = copyvar(L.v, R.v); res = copyvar(L.v, R.v);
// } }
break; break;
case XC( OC_TERNARY ): case XC( OC_TERNARY ):