Sun Mar 14 16:43:31 2021 UTC ()
make: only evaluate the ':_' modifier if the expression is needed

See var-eval-short.mk:46 for the test demonstrating this change.
Previously, the expression ${:Uword:_=VAR} was evaluated including all
its side effects even though it was in an irrelevant branch of the
condition.


(rillig)
diff -r1.865 -r1.866 src/usr.bin/make/var.c
diff -r1.1 -r1.2 src/usr.bin/make/unit-tests/var-eval-short.exp

cvs diff -r1.865 -r1.866 src/usr.bin/make/var.c (expand / switch to unified diff)

--- src/usr.bin/make/var.c 2021/03/14 16:03:04 1.865
+++ src/usr.bin/make/var.c 2021/03/14 16:43:30 1.866
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.865 2021/03/14 16:03:04 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.866 2021/03/14 16:43:30 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -130,27 +130,27 @@ @@ -130,27 +130,27 @@
130#include <regex.h> 130#include <regex.h>
131#endif 131#endif
132#include <errno.h> 132#include <errno.h>
133#include <inttypes.h> 133#include <inttypes.h>
134#include <limits.h> 134#include <limits.h>
135#include <time.h> 135#include <time.h>
136 136
137#include "make.h" 137#include "make.h"
138#include "dir.h" 138#include "dir.h"
139#include "job.h" 139#include "job.h"
140#include "metachar.h" 140#include "metachar.h"
141 141
142/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 142/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
143MAKE_RCSID("$NetBSD: var.c,v 1.865 2021/03/14 16:03:04 rillig Exp $"); 143MAKE_RCSID("$NetBSD: var.c,v 1.866 2021/03/14 16:43:30 rillig Exp $");
144 144
145typedef enum VarFlags { 145typedef enum VarFlags {
146 VFL_NONE = 0, 146 VFL_NONE = 0,
147 147
148 /* 148 /*
149 * The variable's value is currently being used by Var_Parse or 149 * The variable's value is currently being used by Var_Parse or
150 * Var_Subst. This marker is used to avoid endless recursion. 150 * Var_Subst. This marker is used to avoid endless recursion.
151 */ 151 */
152 VFL_IN_USE = 1 << 0, 152 VFL_IN_USE = 1 << 0,
153 153
154 /* 154 /*
155 * The variable comes from the environment. 155 * The variable comes from the environment.
156 * These variables are not registered in any GNode, therefore they 156 * These variables are not registered in any GNode, therefore they
@@ -3408,49 +3408,55 @@ ok: @@ -3408,49 +3408,55 @@ ok:
3408 Expr_SetValueRefer(expr, ""); 3408 Expr_SetValueRefer(expr, "");
3409 return AMR_OK; 3409 return AMR_OK;
3410} 3410}
3411 3411
3412/* 3412/*
3413 * :_=... 3413 * :_=...
3414 * remember current value 3414 * remember current value
3415 */ 3415 */
3416static ApplyModifierResult 3416static ApplyModifierResult
3417ApplyModifier_Remember(const char **pp, ApplyModifiersState *st) 3417ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
3418{ 3418{
3419 Expr *expr = st->expr; 3419 Expr *expr = st->expr;
3420 const char *mod = *pp; 3420 const char *mod = *pp;
 3421
3421 if (!ModMatchEq(mod, "_", st)) 3422 if (!ModMatchEq(mod, "_", st))
3422 return AMR_UNKNOWN; 3423 return AMR_UNKNOWN;
3423 3424
3424 if (mod[1] == '=') { 3425 if (mod[1] == '=') {
3425 /* 3426 /*
3426 * XXX: This ad-hoc call to strcspn deviates from the usual 3427 * XXX: This ad-hoc call to strcspn deviates from the usual
3427 * behavior defined in ParseModifierPart. This creates an 3428 * behavior defined in ParseModifierPart. This creates an
3428 * unnecessary, undocumented inconsistency in make. 3429 * unnecessary, undocumented inconsistency in make.
3429 */ 3430 */
3430 size_t n = strcspn(mod + 2, ":)}"); 3431 size_t n = strcspn(mod + 2, ":)}");
3431 char *name = bmake_strldup(mod + 2, n); 
3432 *pp = mod + 2 + n; 3432 *pp = mod + 2 + n;
3433 3433
3434 /* 3434 if (expr->eflags & VARE_WANTRES) {
3435 * FIXME: do not expand the variable name here; it would only 3435 char *name = bmake_strldup(mod + 2, n);
3436 * work for single-character variable names anyway. 3436
3437 */ 3437 /*
3438 Var_SetExpand(expr->scope, name, expr->value.str); 3438 * FIXME: do not expand the variable name here; it
3439 free(name); 3439 * would only work for single-character variable names
 3440 * anyway.
 3441 */
 3442 Var_SetExpand(expr->scope, name, expr->value.str);
 3443 free(name);
 3444 }
3440 } else { 3445 } else {
3441 *pp = mod + 1; 3446 *pp = mod + 1;
3442 3447
3443 Var_Set(expr->scope, "_", expr->value.str); 3448 if (expr->eflags & VARE_WANTRES)
 3449 Var_Set(expr->scope, "_", expr->value.str);
3444 } 3450 }
3445 return AMR_OK; 3451 return AMR_OK;
3446} 3452}
3447 3453
3448/* 3454/*
3449 * Apply the given function to each word of the variable value, 3455 * Apply the given function to each word of the variable value,
3450 * for a single-letter modifier such as :H, :T. 3456 * for a single-letter modifier such as :H, :T.
3451 */ 3457 */
3452static ApplyModifierResult 3458static ApplyModifierResult
3453ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st, 3459ApplyModifier_WordFunc(const char **pp, ApplyModifiersState *st,
3454 ModifyWordProc modifyWord) 3460 ModifyWordProc modifyWord)
3455{ 3461{
3456 if (!IsDelimiter((*pp)[1], st)) 3462 if (!IsDelimiter((*pp)[1], st))

cvs diff -r1.1 -r1.2 src/usr.bin/make/unit-tests/var-eval-short.exp (expand / switch to unified diff)

--- src/usr.bin/make/unit-tests/var-eval-short.exp 2021/03/14 11:49:37 1.1
+++ src/usr.bin/make/unit-tests/var-eval-short.exp 2021/03/14 16:43:30 1.2
@@ -1,11 +1,10 @@ @@ -1,11 +1,10 @@
1unexpected 1unexpected
2make: Bad modifier ":[${FAIL" for variable "" 2make: Bad modifier ":[${FAIL" for variable ""
3make: "var-eval-short.mk" line 43: Malformed conditional (0 && ${:Uword:[${FAIL}]}) 3make: "var-eval-short.mk" line 43: Malformed conditional (0 && ${:Uword:[${FAIL}]})
4make: "var-eval-short.mk" line 48: Missing argument for ".error" 
5make: "var-eval-short.mk" line 63: Invalid time value: ${FAIL}} 4make: "var-eval-short.mk" line 63: Invalid time value: ${FAIL}}
6make: "var-eval-short.mk" line 63: Malformed conditional (0 && ${:Uword:gmtime=${FAIL}}) 5make: "var-eval-short.mk" line 63: Malformed conditional (0 && ${:Uword:gmtime=${FAIL}})
7make: "var-eval-short.mk" line 77: Invalid time value: ${FAIL}} 6make: "var-eval-short.mk" line 77: Invalid time value: ${FAIL}}
8make: "var-eval-short.mk" line 77: Malformed conditional (0 && ${:Uword:localtime=${FAIL}}) 7make: "var-eval-short.mk" line 77: Malformed conditional (0 && ${:Uword:localtime=${FAIL}})
9make: Fatal errors encountered -- cannot continue 8make: Fatal errors encountered -- cannot continue
10make: stopped in unit-tests 9make: stopped in unit-tests
11exit status 1 10exit status 1