Module Name:    src
Committed By:   rillig
Date:           Mon Mar 15 12:15:03 UTC 2021

Modified Files:
        src/usr.bin/make: arch.c cond.c meta.c nonints.h parse.c suff.c var.c
        src/usr.bin/make/unit-tests: cond-func-empty.mk recursive.mk
            varmod-defined.mk varmod-ifelse.mk varmod-loop.mk
            varparse-errors.mk

Log Message:
make: replace enum bit-field with struct bit-field for VarEvalFlags

This makes the code easier to read, especially in var.c.  It also makes
debugging sessions easier since some debuggers don't show enum
bit-fields symbolically as soon as more than one bit is set.

The code outside var.c is basically unchanged, except that instead of
passing the individual flags, there are 4 predefined evaluation modes.
These suffice for all practical use cases.  Only in the implementation
deep inside var.c, the value of the flags keepDollar and keepUndef
differs.

There is no way of passing the struct to EnumFlags_ToString, which means
the ToString function has to be spelled out explicitly.  This allows for
fine-tuning the representation in the debug log, to reduce the amount of
uppercae letters.

No functional change.


To generate a diff of this commit:
cvs rdiff -u -r1.197 -r1.198 src/usr.bin/make/arch.c
cvs rdiff -u -r1.258 -r1.259 src/usr.bin/make/cond.c
cvs rdiff -u -r1.178 -r1.179 src/usr.bin/make/meta.c
cvs rdiff -u -r1.204 -r1.205 src/usr.bin/make/nonints.h
cvs rdiff -u -r1.551 -r1.552 src/usr.bin/make/parse.c
cvs rdiff -u -r1.347 -r1.348 src/usr.bin/make/suff.c
cvs rdiff -u -r1.884 -r1.885 src/usr.bin/make/var.c
cvs rdiff -u -r1.12 -r1.13 src/usr.bin/make/unit-tests/cond-func-empty.mk
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/recursive.mk
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/unit-tests/varmod-defined.mk \
    src/usr.bin/make/unit-tests/varmod-ifelse.mk
cvs rdiff -u -r1.10 -r1.11 src/usr.bin/make/unit-tests/varmod-loop.mk
cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/varparse-errors.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/arch.c
diff -u src/usr.bin/make/arch.c:1.197 src/usr.bin/make/arch.c:1.198
--- src/usr.bin/make/arch.c:1.197	Fri Feb  5 05:15:12 2021
+++ src/usr.bin/make/arch.c	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: arch.c,v 1.197 2021/02/05 05:15:12 rillig Exp $	*/
+/*	$NetBSD: arch.c,v 1.198 2021/03/15 12:15:03 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -126,7 +126,7 @@
 #include "config.h"
 
 /*	"@(#)arch.c	8.2 (Berkeley) 1/2/94"	*/
-MAKE_RCSID("$NetBSD: arch.c,v 1.197 2021/02/05 05:15:12 rillig Exp $");
+MAKE_RCSID("$NetBSD: arch.c,v 1.198 2021/03/15 12:15:03 rillig Exp $");
 
 typedef struct List ArchList;
 typedef struct ListNode ArchListNode;
@@ -207,7 +207,7 @@ Arch_ParseArchive(char **pp, GNodeList *
 
 			/* XXX: is expanded twice: once here and once below */
 			(void)Var_Parse(&nested_p, scope,
-					VARE_WANTRES | VARE_UNDEFERR, &result);
+			    VARE_UNDEFERR, &result);
 			/* TODO: handle errors */
 			isError = result.str == var_Error;
 			FStr_Done(&result);
@@ -223,8 +223,7 @@ Arch_ParseArchive(char **pp, GNodeList *
 	*cp++ = '\0';
 	if (expandLibName) {
 		char *expanded;
-		(void)Var_Subst(libName.str, scope,
-		    VARE_WANTRES | VARE_UNDEFERR, &expanded);
+		(void)Var_Subst(libName.str, scope, VARE_UNDEFERR, &expanded);
 		/* TODO: handle errors */
 		libName = MFStr_InitOwn(expanded);
 	}
@@ -250,8 +249,7 @@ Arch_ParseArchive(char **pp, GNodeList *
 				const char *nested_p = cp;
 
 				(void)Var_Parse(&nested_p, scope,
-						VARE_WANTRES | VARE_UNDEFERR,
-						&result);
+				    VARE_UNDEFERR, &result);
 				/* TODO: handle errors */
 				isError = result.str == var_Error;
 				FStr_Done(&result);
@@ -306,9 +304,8 @@ Arch_ParseArchive(char **pp, GNodeList *
 			char *p;
 			char *unexpandedMemName = memName;
 
-			(void)Var_Subst(memName, scope,
-					VARE_WANTRES | VARE_UNDEFERR,
-					&memName);
+			(void)Var_Subst(memName, scope, VARE_UNDEFERR,
+			    &memName);
 			/* TODO: handle errors */
 
 			/*

Index: src/usr.bin/make/cond.c
diff -u src/usr.bin/make/cond.c:1.258 src/usr.bin/make/cond.c:1.259
--- src/usr.bin/make/cond.c:1.258	Mon Mar 15 11:41:07 2021
+++ src/usr.bin/make/cond.c	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: cond.c,v 1.258 2021/03/15 11:41:07 rillig Exp $	*/
+/*	$NetBSD: cond.c,v 1.259 2021/03/15 12:15:03 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -95,7 +95,7 @@
 #include "dir.h"
 
 /*	"@(#)cond.c	8.2 (Berkeley) 1/2/94"	*/
-MAKE_RCSID("$NetBSD: cond.c,v 1.258 2021/03/15 11:41:07 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.259 2021/03/15 12:15:03 rillig Exp $");
 
 /*
  * The parsing of conditional expressions is based on this grammar:
@@ -265,7 +265,7 @@ ParseFuncArg(CondParser *par, const char
 			 * error, though perhaps we should.
 			 */
 			VarEvalFlags eflags = doEval
-			    ? VARE_WANTRES | VARE_UNDEFERR
+			    ? VARE_UNDEFERR
 			    : VARE_PARSE_ONLY;
 			FStr nestedVal;
 			(void)Var_Parse(&p, SCOPE_CMDLINE, eflags, &nestedVal);
@@ -420,7 +420,7 @@ CondParser_StringExpr(CondParser *par, c
 	VarParseResult parseResult;
 
 	/* if we are in quotes, an undefined variable is ok */
-	eflags = doEval && !quoted ? VARE_WANTRES | VARE_UNDEFERR
+	eflags = doEval && !quoted ? VARE_UNDEFERR
 	    : doEval ? VARE_WANTRES
 	    : VARE_PARSE_ONLY;
 

Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.178 src/usr.bin/make/meta.c:1.179
--- src/usr.bin/make/meta.c:1.178	Mon Feb 22 23:21:33 2021
+++ src/usr.bin/make/meta.c	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*      $NetBSD: meta.c,v 1.178 2021/02/22 23:21:33 rillig Exp $ */
+/*      $NetBSD: meta.c,v 1.179 2021/03/15 12:15:03 rillig Exp $ */
 
 /*
  * Implement 'meta' mode.
@@ -1516,7 +1516,7 @@ meta_oodate(GNode *gn, Boolean oodate)
 			DEBUG2(META, "%s: %d: cannot compare command using .OODATE\n",
 			       fname, lineno);
 		    }
-		    (void)Var_Subst(cmd, gn, VARE_WANTRES|VARE_UNDEFERR, &cmd);
+		    (void)Var_Subst(cmd, gn, VARE_UNDEFERR, &cmd);
 		    /* TODO: handle errors */
 
 		    if ((cp = strchr(cmd, '\n')) != NULL) {

Index: src/usr.bin/make/nonints.h
diff -u src/usr.bin/make/nonints.h:1.204 src/usr.bin/make/nonints.h:1.205
--- src/usr.bin/make/nonints.h:1.204	Mon Mar 15 11:41:07 2021
+++ src/usr.bin/make/nonints.h	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: nonints.h,v 1.204 2021/03/15 11:41:07 rillig Exp $	*/
+/*	$NetBSD: nonints.h,v 1.205 2021/03/15 12:15:03 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -292,22 +292,25 @@ const char *GNodeMade_Name(GNodeMade);
 void Var_Init(void);
 void Var_End(void);
 
-typedef enum VarEvalFlags {
-	VARE_PARSE_ONLY		= 0,
+typedef struct VarEvalFlags {
 
 	/*
 	 * Expand and evaluate variables during parsing.
 	 *
+	 * Without this flag, the expression is only parsed, without
+	 * evaluating any part of it.
+	 *
 	 * TODO: Document what Var_Parse and Var_Subst return when this flag
-	 * is not set.
+	 *  is not set.  As of 2021-03-15, they return unspecified,
+	 *  inconsistent results.
 	 */
-	VARE_WANTRES		= 1 << 0,
+	Boolean wantRes: 1;
 
 	/*
 	 * Treat undefined variables as errors.
-	 * Must only be used in combination with VARE_WANTRES.
+	 * Must only be used in combination with wantRes.
 	 */
-	VARE_UNDEFERR		= 1 << 1,
+	Boolean undefErr: 1;
 
 	/*
 	 * Keep '$$' as '$$' instead of reducing it to a single '$'.
@@ -317,7 +320,7 @@ typedef enum VarEvalFlags {
 	 * expanding '$$file' to '$file' in the first assignment and
 	 * interpreting it as '${f}' followed by 'ile' in the next assignment.
 	 */
-	VARE_KEEP_DOLLAR	= 1 << 2,
+	Boolean keepDollar: 1;
 
 	/*
 	 * Keep undefined variables as-is instead of expanding them to an
@@ -330,9 +333,22 @@ typedef enum VarEvalFlags {
 	 *	# way) is still undefined, the updated CFLAGS becomes
 	 *	# "-I.. $(.INCLUDES)".
 	 */
-	VARE_KEEP_UNDEF		= 1 << 3
+	Boolean keepUndef: 1;
+
+	/*
+	 * Without this padding, GCC 9.3.0 on NetBSD 9.99.80 generates larger
+	 * code than necessary (1.2 kB), masking out the unused bits from the
+	 * int (since that is the default representation of Boolean in make),
+	 * even for initializers consisting entirely of constants.
+	 */
+	Boolean : 1;
 } VarEvalFlags;
 
+#define VARE_PARSE_ONLY	(VarEvalFlags) { FALSE, FALSE, FALSE, FALSE }
+#define VARE_WANTRES	(VarEvalFlags) { TRUE, FALSE, FALSE, FALSE }
+#define VARE_UNDEFERR	(VarEvalFlags) { TRUE, TRUE, FALSE, FALSE }
+#define VARE_KEEP_DOLLAR_UNDEF (VarEvalFlags) { TRUE, FALSE, TRUE, TRUE }
+
 typedef enum VarSetFlags {
 	VAR_SET_NONE		= 0,
 
@@ -361,7 +377,8 @@ typedef enum VarParseResult {
 	 * Some callers handle this case differently, so return this
 	 * information to them, for now.
 	 *
-	 * TODO: Replace this with a new flag VARE_KEEP_UNDEFINED.
+	 * TODO: Instead of having this special return value, rather ensure
+	 *  that VarEvalFlags.keepUndef is processed properly.
 	 */
 	VPR_UNDEF
 

Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.551 src/usr.bin/make/parse.c:1.552
--- src/usr.bin/make/parse.c:1.551	Mon Mar 15 11:41:07 2021
+++ src/usr.bin/make/parse.c	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: parse.c,v 1.551 2021/03/15 11:41:07 rillig Exp $	*/
+/*	$NetBSD: parse.c,v 1.552 2021/03/15 12:15:03 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -109,7 +109,7 @@
 #include "pathnames.h"
 
 /*	"@(#)parse.c	8.3 (Berkeley) 3/19/94"	*/
-MAKE_RCSID("$NetBSD: parse.c,v 1.551 2021/03/15 11:41:07 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.552 2021/03/15 12:15:03 rillig Exp $");
 
 /* types and constants */
 
@@ -1898,8 +1898,7 @@ VarAssign_EvalSubst(GNode *scope, const 
 	if (!Var_ExistsExpand(scope, name))
 		Var_SetExpand(scope, name, "");
 
-	(void)Var_Subst(uvalue, scope,
-	    VARE_WANTRES | VARE_KEEP_DOLLAR | VARE_KEEP_UNDEF, &evalue);
+	(void)Var_Subst(uvalue, scope, VARE_KEEP_DOLLAR_UNDEF, &evalue);
 	/* TODO: handle errors */
 
 	Var_SetExpand(scope, name, evalue);
@@ -1918,8 +1917,8 @@ VarAssign_EvalShell(const char *name, co
 	cmd = FStr_InitRefer(uvalue);
 	if (strchr(cmd.str, '$') != NULL) {
 		char *expanded;
-		(void)Var_Subst(cmd.str, SCOPE_CMDLINE,
-		    VARE_WANTRES | VARE_UNDEFERR, &expanded);
+		(void)Var_Subst(cmd.str, SCOPE_CMDLINE, VARE_UNDEFERR,
+		    &expanded);
 		/* TODO: handle errors */
 		cmd = FStr_InitOwn(expanded);
 	}
@@ -3131,7 +3130,7 @@ ParseDependency(char *line)
 	 * Var_Parse does not print any parse errors in such a case.
 	 * It simply returns the special empty string var_Error,
 	 * which cannot be detected in the result of Var_Subst. */
-	eflags = opts.strict ? VARE_WANTRES : VARE_WANTRES | VARE_UNDEFERR;
+	eflags = opts.strict ? VARE_WANTRES : VARE_UNDEFERR;
 	(void)Var_Subst(line, SCOPE_CMDLINE, eflags, &expanded_line);
 	/* TODO: handle errors */
 

Index: src/usr.bin/make/suff.c
diff -u src/usr.bin/make/suff.c:1.347 src/usr.bin/make/suff.c:1.348
--- src/usr.bin/make/suff.c:1.347	Mon Mar 15 11:41:07 2021
+++ src/usr.bin/make/suff.c	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: suff.c,v 1.347 2021/03/15 11:41:07 rillig Exp $	*/
+/*	$NetBSD: suff.c,v 1.348 2021/03/15 12:15:03 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -114,7 +114,7 @@
 #include "dir.h"
 
 /*	"@(#)suff.c	8.4 (Berkeley) 3/21/94"	*/
-MAKE_RCSID("$NetBSD: suff.c,v 1.347 2021/03/15 11:41:07 rillig Exp $");
+MAKE_RCSID("$NetBSD: suff.c,v 1.348 2021/03/15 12:15:03 rillig Exp $");
 
 typedef List SuffixList;
 typedef ListNode SuffixListNode;
@@ -1380,7 +1380,7 @@ ExpandChildren(GNodeListNode *cln, GNode
 	}
 
 	DEBUG1(SUFF, "Expanding \"%s\"...", cgn->name);
-	(void)Var_Subst(cgn->name, pgn, VARE_WANTRES | VARE_UNDEFERR, &cp);
+	(void)Var_Subst(cgn->name, pgn, VARE_UNDEFERR, &cp);
 	/* TODO: handle errors */
 
 	{

Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.884 src/usr.bin/make/var.c:1.885
--- src/usr.bin/make/var.c:1.884	Mon Mar 15 11:41:07 2021
+++ src/usr.bin/make/var.c	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.884 2021/03/15 11:41:07 rillig Exp $	*/
+/*	$NetBSD: var.c,v 1.885 2021/03/15 12:15:03 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -140,7 +140,7 @@
 #include "metachar.h"
 
 /*	"@(#)var.c	8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.884 2021/03/15 11:41:07 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.885 2021/03/15 12:15:03 rillig Exp $");
 
 typedef enum VarFlags {
 	VFL_NONE	= 0,
@@ -267,10 +267,38 @@ typedef struct SepBuf {
 	char sep;
 } SepBuf;
 
+enum {
+	VarEvalFlags_ToStringSize = sizeof
+	    "VARE_UNDEFERR|VARE_WANTRES|VARE_KEEP_DOLLAR|VARE_KEEP_UNDEF"
+};
 
-ENUM_FLAGS_RTTI_4(VarEvalFlags,
-		  VARE_UNDEFERR, VARE_WANTRES, VARE_KEEP_DOLLAR,
-		  VARE_KEEP_UNDEF);
+MAKE_INLINE char *
+str_append(char *dst, const char *src)
+{
+	size_t len = strlen(src);
+	memcpy(dst, src, len);
+	return dst + len;
+}
+
+static const char *
+VarEvalFlags_ToString(char *buf, VarEvalFlags eflags)
+{
+	char *p = buf;
+
+	/* TODO: WANTRES should be mentioned before UNDEFERR */
+	if (eflags.undefErr)
+		p = str_append(p, "VARE_UNDEFERR|");
+	if (eflags.wantRes)
+		p = str_append(p, "VARE_WANTRES|");
+	if (eflags.keepDollar)
+		p = str_append(p, "VARE_KEEP_DOLLAR|");
+	if (eflags.keepUndef)
+		p = str_append(p, "VARE_KEEP_UNDEF|");
+	if (p == buf)
+		return "none";
+	p[-1] = '\0';
+	return buf;
+}
 
 /*
  * This lets us tell if we have replaced the original environ
@@ -287,11 +315,11 @@ char var_Error[] = "";
 
 /*
  * Special return value for Var_Parse, indicating an undefined variable in
- * a case where VARE_UNDEFERR is not set.  This undefined variable is
+ * a case where VarEvalFlags.undefErr is not set.  This undefined variable is
  * typically a dynamic variable such as ${.TARGET}, whose expansion needs to
  * be deferred until it is defined in an actual target.
  *
- * See VARE_KEEP_UNDEF.
+ * See VarEvalFlags.keepUndef.
  */
 static char varUndefined[] = "";
 
@@ -2172,11 +2200,11 @@ ParseModifierPartSubst(
 			continue;
 		}
 
-		if (eflags & VARE_WANTRES) { /* Nested variable, evaluated */
+		if (eflags.wantRes) {	/* Nested variable, evaluated */
 			const char *nested_p = p;
 			FStr nested_val;
-			VarEvalFlags nested_eflags =
-			    eflags & ~(unsigned)VARE_KEEP_DOLLAR;
+			VarEvalFlags nested_eflags = eflags;
+			nested_eflags.keepDollar = FALSE;
 
 			(void)Var_Parse(&nested_p, st->expr->scope,
 			    nested_eflags, &nested_val);
@@ -2189,10 +2217,10 @@ ParseModifierPartSubst(
 
 		/*
 		 * XXX: This whole block is very similar to Var_Parse without
-		 * VARE_WANTRES.  There may be subtle edge cases though that
-		 * are not yet covered in the unit tests and that are parsed
-		 * differently, depending on whether they are evaluated or
-		 * not.
+		 * VarEvalFlags.wantRes.  There may be subtle edge cases
+		 * though that are not yet covered in the unit tests and that
+		 * are parsed differently, depending on whether they are
+		 * evaluated or not.
 		 *
 		 * This subtle difference is not documented in the manual
 		 * page, neither is the difference between parsing :D and
@@ -2260,8 +2288,7 @@ ParseModifierPart(
     const char **pp,
     /* Parsing stops at this delimiter */
     char delim,
-    /* Flags for evaluating nested variables; if VARE_WANTRES is not set,
-     * the text is only parsed. */
+    /* Flags for evaluating nested variables. */
     VarEvalFlags eflags,
     ApplyModifiersState *st,
     char **out_part
@@ -2423,10 +2450,11 @@ ApplyModifier_Loop(const char **pp, Appl
 	if (res != VPR_OK)
 		return AMR_CLEANUP;
 
-	if (!(expr->eflags & VARE_WANTRES))
+	if (!expr->eflags.wantRes)
 		goto done;
 
-	args.eflags = expr->eflags & ~(unsigned)VARE_KEEP_DOLLAR;
+	args.eflags = expr->eflags;
+	args.eflags.keepDollar = FALSE;
 	prev_sep = st->sep;
 	st->sep = ' ';		/* XXX: should be st->sep for consistency */
 	ModifyWords(st, ModifyWord_Loop, &args, st->oneBigWord);
@@ -2453,7 +2481,7 @@ ApplyModifier_Defined(const char **pp, A
 	const char *p;
 
 	VarEvalFlags eflags = VARE_PARSE_ONLY;
-	if (expr->eflags & VARE_WANTRES)
+	if (expr->eflags.wantRes)
 		if ((**pp == 'D') == (expr->defined == DEF_REGULAR))
 			eflags = expr->eflags;
 
@@ -2482,7 +2510,7 @@ ApplyModifier_Defined(const char **pp, A
 
 			(void)Var_Parse(&p, expr->scope, eflags, &nested_val);
 			/* TODO: handle errors */
-			if (expr->eflags & VARE_WANTRES)
+			if (expr->eflags.wantRes)
 				Buf_AddStr(&buf, nested_val.str);
 			FStr_Done(&nested_val);
 			continue;
@@ -2496,7 +2524,7 @@ ApplyModifier_Defined(const char **pp, A
 
 	Expr_Define(expr);
 
-	if (eflags & VARE_WANTRES)
+	if (eflags.wantRes)
 		Expr_SetValueOwn(expr, Buf_DoneData(&buf));
 	else
 		Buf_Done(&buf);
@@ -2512,7 +2540,7 @@ ApplyModifier_Literal(const char **pp, A
 
 	(*pp)++;
 
-	if (expr->eflags & VARE_WANTRES) {
+	if (expr->eflags.wantRes) {
 		Expr_Define(expr);
 		Expr_SetValueOwn(expr, bmake_strdup(expr->var->name.str));
 	}
@@ -2562,7 +2590,7 @@ ApplyModifier_Gmtime(const char **pp, Ap
 		*pp = mod + 6;
 	}
 
-	if (st->expr->eflags & VARE_WANTRES)
+	if (st->expr->eflags.wantRes)
 		Expr_SetValueOwn(st->expr,
 		    VarStrftime(st->expr->value.str, TRUE, utc));
 
@@ -2592,7 +2620,7 @@ ApplyModifier_Localtime(const char **pp,
 		*pp = mod + 9;
 	}
 
-	if (st->expr->eflags & VARE_WANTRES)
+	if (st->expr->eflags.wantRes)
 		Expr_SetValueOwn(st->expr,
 		    VarStrftime(st->expr->value.str, FALSE, utc));
 
@@ -2607,7 +2635,7 @@ ApplyModifier_Hash(const char **pp, Appl
 		return AMR_UNKNOWN;
 	*pp += 4;
 
-	if (st->expr->eflags & VARE_WANTRES)
+	if (st->expr->eflags.wantRes)
 		Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str));
 
 	return AMR_OK;
@@ -2623,7 +2651,7 @@ ApplyModifier_Path(const char **pp, Appl
 
 	(*pp)++;
 
-	if (!(st->expr->eflags & VARE_WANTRES))
+	if (!st->expr->eflags.wantRes)
 		return AMR_OK;
 
 	Expr_Define(expr);
@@ -2659,7 +2687,7 @@ ApplyModifier_ShellCommand(const char **
 		return AMR_CLEANUP;
 
 	errfmt = NULL;
-	if (expr->eflags & VARE_WANTRES)
+	if (expr->eflags.wantRes)
 		Expr_SetValueOwn(expr, Cmd_Exec(cmd, &errfmt));
 	else
 		Expr_SetValueRefer(expr, "");
@@ -2700,7 +2728,7 @@ ApplyModifier_Range(const char **pp, App
 		*pp = mod + 5;
 	}
 
-	if (!(st->expr->eflags & VARE_WANTRES))
+	if (!st->expr->eflags.wantRes)
 		return AMR_OK;
 
 	if (n == 0) {
@@ -2810,7 +2838,7 @@ ApplyModifier_Match(const char **pp, App
 
 	ParseModifier_Match(pp, st, &pattern);
 
-	if (st->expr->eflags & VARE_WANTRES) {
+	if (st->expr->eflags.wantRes) {
 		ModifyWordProc modifyWord =
 		    mod == 'M' ? ModifyWord_Match : ModifyWord_NoMatch;
 		ModifyWords(st, modifyWord, pattern, st->oneBigWord);
@@ -2919,7 +2947,7 @@ ApplyModifier_Regex(const char **pp, App
 	oneBigWord = st->oneBigWord;
 	ParsePatternFlags(pp, &args.pflags, &oneBigWord);
 
-	if (!(st->expr->eflags & VARE_WANTRES)) {
+	if (!(st->expr->eflags.wantRes)) {
 		free(args.replace);
 		free(re);
 		return AMR_OK;
@@ -2955,7 +2983,7 @@ ApplyModifier_Quote(const char **pp, App
 		return AMR_UNKNOWN;
 	(*pp)++;
 
-	if (st->expr->eflags & VARE_WANTRES)
+	if (st->expr->eflags.wantRes)
 		Expr_SetValueOwn(st->expr,
 		    VarQuote(st->expr->value.str, quoteDollar));
 
@@ -2976,9 +3004,9 @@ ApplyModifier_ToSep(const char **pp, App
 	const char *sep = *pp + 2;
 
 	/*
-	 * Even if VARE_WANTRES is not set, proceed as normal since there is
+	 * Even in parse-only mode, proceed as normal since there is
 	 * neither any observable side effect nor a performance penalty.
-	 * Checking for VARE_WANTRES for every single piece of code in here
+	 * Checking for wantRes for every single piece of code in here
 	 * would make the code in this function too hard to read.
 	 */
 
@@ -3104,14 +3132,14 @@ ApplyModifier_To(const char **pp, ApplyM
 
 	if (mod[1] == 'u') {				/* :tu */
 		*pp = mod + 2;
-		if (st->expr->eflags & VARE_WANTRES)
+		if (st->expr->eflags.wantRes)
 			Expr_SetValueOwn(expr, str_toupper(expr->value.str));
 		return AMR_OK;
 	}
 
 	if (mod[1] == 'l') {				/* :tl */
 		*pp = mod + 2;
-		if (st->expr->eflags & VARE_WANTRES)
+		if (st->expr->eflags.wantRes)
 			Expr_SetValueOwn(expr, str_tolower(expr->value.str));
 		return AMR_OK;
 	}
@@ -3145,7 +3173,7 @@ ApplyModifier_Words(const char **pp, App
 	if (!IsDelimiter(**pp, st))
 		goto bad_modifier;		/* Found junk after ']' */
 
-	if (!(expr->eflags & VARE_WANTRES))
+	if (!(expr->eflags.wantRes))
 		goto ok;
 
 	if (estr[0] == '\0')
@@ -3269,7 +3297,7 @@ ApplyModifier_Order(const char **pp, App
 	} else
 		return AMR_BAD;
 
-	if (!(st->expr->eflags & VARE_WANTRES))
+	if (!st->expr->eflags.wantRes)
 		return AMR_OK;
 
 	words = Str_Words(st->expr->value.str, FALSE);
@@ -3296,7 +3324,7 @@ ApplyModifier_IfElse(const char **pp, Ap
 	VarEvalFlags else_eflags = VARE_PARSE_ONLY;
 
 	int cond_rc = COND_PARSE;	/* anything other than COND_INVALID */
-	if (expr->eflags & VARE_WANTRES) {
+	if (expr->eflags.wantRes) {
 		cond_rc = Cond_EvalCondition(expr->var->name.str, &value);
 		if (cond_rc != COND_INVALID && value)
 			then_eflags = expr->eflags;
@@ -3322,7 +3350,7 @@ ApplyModifier_IfElse(const char **pp, Ap
 		return AMR_CLEANUP;
 	}
 
-	if (!(expr->eflags & VARE_WANTRES)) {
+	if (!expr->eflags.wantRes) {
 		free(then_expr);
 		free(else_expr);
 	} else if (value) {
@@ -3398,7 +3426,7 @@ ok:
 
 	(*pp)--;		/* Go back to the st->endc. */
 
-	if (!(expr->eflags & VARE_WANTRES))
+	if (!expr->eflags.wantRes)
 		goto done;
 
 	scope = expr->scope;	/* scope where v belongs */
@@ -3468,7 +3496,7 @@ ApplyModifier_Remember(const char **pp, 
 	} else
 		*pp = mod + 1;
 
-	if (expr->eflags & VARE_WANTRES)
+	if (expr->eflags.wantRes)
 		Var_Set(expr->scope, name.str, expr->value.str);
 	FStr_Done(&name);
 
@@ -3487,7 +3515,7 @@ ApplyModifier_WordFunc(const char **pp, 
 		return AMR_UNKNOWN;
 	(*pp)++;
 
-	if (st->expr->eflags & VARE_WANTRES)
+	if (st->expr->eflags.wantRes)
 		ModifyWords(st, modifyWord, NULL, st->oneBigWord);
 
 	return AMR_OK;
@@ -3500,7 +3528,7 @@ ApplyModifier_Unique(const char **pp, Ap
 		return AMR_UNKNOWN;
 	(*pp)++;
 
-	if (st->expr->eflags & VARE_WANTRES)
+	if (st->expr->eflags.wantRes)
 		Expr_SetValueOwn(st->expr, VarUniq(st->expr->value.str));
 
 	return AMR_OK;
@@ -3574,7 +3602,7 @@ ApplyModifier_SunShell(const char **pp, 
 		return AMR_UNKNOWN;
 	*pp = p + 2;
 
-	if (expr->eflags & VARE_WANTRES) {
+	if (expr->eflags.wantRes) {
 		const char *errfmt;
 		char *output = Cmd_Exec(expr->value.str, &errfmt);
 		if (errfmt != NULL)
@@ -4047,7 +4075,7 @@ ParseVarnameShort(char varname, const ch
 
 		val = UndefinedShortVarValue(varname, scope);
 		if (val == NULL)
-			val = eflags & VARE_UNDEFERR ? var_Error : varUndefined;
+			val = eflags.undefErr ? var_Error : varUndefined;
 
 		if (opts.strict && val == var_Error) {
 			Parse_Error(PARSE_FATAL,
@@ -4067,7 +4095,7 @@ ParseVarnameShort(char varname, const ch
 		 * If undefined expressions are allowed, this should rather
 		 * be VPR_UNDEF instead of VPR_OK.
 		 */
-		*out_FALSE_res = eflags & VARE_UNDEFERR ? VPR_UNDEF : VPR_OK;
+		*out_FALSE_res = eflags.undefErr ? VPR_UNDEF : VPR_OK;
 		*out_FALSE_val = val;
 		return FALSE;
 	}
@@ -4118,7 +4146,7 @@ EvalUndefined(Boolean dynamic, const cha
 		return VPR_OK;
 	}
 
-	if ((eflags & VARE_UNDEFERR) && opts.strict) {
+	if (eflags.undefErr && opts.strict) {
 		Parse_Error(PARSE_FATAL,
 		    "Variable \"%s\" is undefined", varname);
 		free(varname);
@@ -4126,7 +4154,7 @@ EvalUndefined(Boolean dynamic, const cha
 		return VPR_ERR;
 	}
 
-	if (eflags & VARE_UNDEFERR) {
+	if (eflags.undefErr) {
 		free(varname);
 		*out_val = FStr_InitRefer(var_Error);
 		return VPR_UNDEF;	/* XXX: Should be VPR_ERR instead. */
@@ -4280,13 +4308,13 @@ FreeEnvVar(Var *v, FStr *inout_val)
  *	*out_val	The value of the variable expression, never NULL.
  *	*out_val	var_Error if there was a parse error.
  *	*out_val	var_Error if the base variable of the expression was
- *			undefined, eflags contains VARE_UNDEFERR, and none of
+ *			undefined, eflags has undefErr set, and none of
  *			the modifiers turned the undefined expression into a
  *			defined expression.
  *			XXX: It is not guaranteed that an error message has
  *			been printed.
  *	*out_val	varUndefined if the base variable of the expression
- *			was undefined, eflags did not contain VARE_UNDEFERR,
+ *			was undefined, eflags did not have undefErr set,
  *			and none of the modifiers turned the undefined
  *			expression into a defined expression.
  *			XXX: It is not guaranteed that an error message has
@@ -4375,11 +4403,11 @@ Var_Parse(const char **pp, GNode *scope,
 	 * Before applying any modifiers, expand any nested expressions from
 	 * the variable value.
 	 */
-	if (strchr(expr.value.str, '$') != NULL && (eflags & VARE_WANTRES)) {
+	if (strchr(expr.value.str, '$') != NULL && eflags.wantRes) {
 		char *expanded;
 		VarEvalFlags nested_eflags = eflags;
 		if (opts.strict)
-			nested_eflags &= ~(unsigned)VARE_UNDEFERR;
+			nested_eflags.undefErr = FALSE;
 		v->flags |= VFL_IN_USE;
 		(void)Var_Subst(expr.value.str, scope, nested_eflags,
 		    &expanded);
@@ -4418,7 +4446,7 @@ Var_Parse(const char **pp, GNode *scope,
 				 * return an error marker instead.
 				 */
 				Expr_SetValueRefer(&expr,
-				    eflags & VARE_UNDEFERR
+				    eflags.undefErr
 					? var_Error : varUndefined);
 			}
 		}
@@ -4436,7 +4464,7 @@ static void
 VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalFlags eflags)
 {
 	/* A dollar sign may be escaped with another dollar sign. */
-	if (save_dollars && (eflags & VARE_KEEP_DOLLAR))
+	if (save_dollars && eflags.keepDollar)
 		Buf_AddByte(res, '$');
 	Buf_AddByte(res, '$');
 	*pp += 2;
@@ -4454,9 +4482,9 @@ VarSubstExpr(const char **pp, Buffer *bu
 	/* TODO: handle errors */
 
 	if (val.str == var_Error || val.str == varUndefined) {
-		if (!(eflags & VARE_KEEP_UNDEF)) {
+		if (!eflags.keepUndef) {
 			p = nested_p;
-		} else if ((eflags & VARE_UNDEFERR) || val.str == var_Error) {
+		} else if (eflags.undefErr || val.str == var_Error) {
 
 			/*
 			 * XXX: This condition is wrong.  If val == var_Error,

Index: src/usr.bin/make/unit-tests/cond-func-empty.mk
diff -u src/usr.bin/make/unit-tests/cond-func-empty.mk:1.12 src/usr.bin/make/unit-tests/cond-func-empty.mk:1.13
--- src/usr.bin/make/unit-tests/cond-func-empty.mk:1.12	Mon Feb 22 20:38:55 2021
+++ src/usr.bin/make/unit-tests/cond-func-empty.mk	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-empty.mk,v 1.12 2021/02/22 20:38:55 rillig Exp $
+# $NetBSD: cond-func-empty.mk,v 1.13 2021/03/15 12:15:03 rillig Exp $
 #
 # Tests for the empty() function in .if conditions, which tests a variable
 # expression for emptiness.
@@ -93,8 +93,8 @@ WORD=	word
 # neither leading nor trailing spaces are trimmed in the argument of the
 # function.  If the spaces were trimmed, the variable name would be "" and
 # that variable is indeed undefined.  Since ParseEmptyArg calls Var_Parse
-# without VARE_UNDEFERR, the value of the undefined variable is returned as
-# an empty string.
+# without VarEvalFlags.undefErr, the value of the undefined variable is
+# returned as an empty string.
 ${:U }=	space
 .if empty( )
 .  error
@@ -168,14 +168,14 @@ ${:U WORD }=	variable name with spaces
 # parsing it, this unrealistic variable name should have done no harm.
 #
 # The variable expression was expanded though, and this was wrong.  The
-# expansion was done without the VARE_WANTRES flag (called VARF_WANTRES back
+# expansion was done without VarEvalFlags.wantRes (called VARF_WANTRES back
 # then) though.  This had the effect that the ${:U1} from the value of VARNAME
 # expanded to an empty string.  This in turn created the seemingly recursive
 # definition VARNAME=${VARNAME}, and that definition was never meant to be
 # expanded.
 #
 # This was fixed by expanding nested variable expressions in the variable name
-# only if the flag VARE_WANTRES is given.
+# only if the flag VarEvalFlags.wantRes is given.
 VARNAME=	${VARNAME${:U1}}
 .if defined(VARNAME${:U2}) && !empty(VARNAME${:U2})
 .endif

Index: src/usr.bin/make/unit-tests/recursive.mk
diff -u src/usr.bin/make/unit-tests/recursive.mk:1.4 src/usr.bin/make/unit-tests/recursive.mk:1.5
--- src/usr.bin/make/unit-tests/recursive.mk:1.4	Mon Nov  9 20:50:56 2020
+++ src/usr.bin/make/unit-tests/recursive.mk	Mon Mar 15 12:15:03 2021
@@ -1,12 +1,12 @@
-# $NetBSD: recursive.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $
+# $NetBSD: recursive.mk,v 1.5 2021/03/15 12:15:03 rillig Exp $
 #
 # In -dL mode, a variable may get expanded before it makes sense.
 # This would stop make from doing anything since the "recursive" error
 # is fatal and exits immediately.
 #
 # The purpose of evaluating that variable early was just to detect
-# whether there are unclosed variables.  It might be enough to parse the
-# variable value without VARE_WANTRES for that purpose.
+# whether there are unclosed variables.  The variable value is therefore
+# parsed with VARE_PARSE_ONLY for that purpose.
 #
 # Seen in pkgsrc/x11/libXfixes, and probably many more package that use
 # GNU Automake.
@@ -36,4 +36,3 @@ MISSING_BRACE_INDIRECT:=	${:U\${MISSING_
 UNCLOSED=	$(MISSING_PAREN
 UNCLOSED=	${MISSING_BRACE
 UNCLOSED=	${MISSING_BRACE_INDIRECT}
-

Index: src/usr.bin/make/unit-tests/varmod-defined.mk
diff -u src/usr.bin/make/unit-tests/varmod-defined.mk:1.9 src/usr.bin/make/unit-tests/varmod-defined.mk:1.10
--- src/usr.bin/make/unit-tests/varmod-defined.mk:1.9	Thu Nov 12 00:40:55 2020
+++ src/usr.bin/make/unit-tests/varmod-defined.mk	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-defined.mk,v 1.9 2020/11/12 00:40:55 rillig Exp $
+# $NetBSD: varmod-defined.mk,v 1.10 2021/03/15 12:15:03 rillig Exp $
 #
 # Tests for the :D variable modifier, which returns the given string
 # if the variable is defined.  It is closely related to the :U modifier.
@@ -91,7 +91,7 @@ DEF=	defined
 # that they preserve dollars in a ':=' assignment.  This is because
 # ApplyModifier_Defined passes the eflags unmodified to Var_Parse, unlike
 # ApplyModifier_Loop, which uses ParseModifierPart, which in turn removes
-# VARE_KEEP_DOLLAR from eflags.
+# VarEvalFlags.keepDollar from eflags.
 #
 # XXX: This inconsistency is documented nowhere.
 .MAKEFLAGS: -dv
Index: src/usr.bin/make/unit-tests/varmod-ifelse.mk
diff -u src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.9 src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.10
--- src/usr.bin/make/unit-tests/varmod-ifelse.mk:1.9	Mon Jan 25 19:05:39 2021
+++ src/usr.bin/make/unit-tests/varmod-ifelse.mk	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-ifelse.mk,v 1.9 2021/01/25 19:05:39 rillig Exp $
+# $NetBSD: varmod-ifelse.mk,v 1.10 2021/03/15 12:15:03 rillig Exp $
 #
 # Tests for the ${cond:?then:else} variable modifier, which evaluates either
 # the then-expression or the else-expression, depending on the condition.
@@ -74,7 +74,7 @@ COND:=	${${UNDEF} == "":?bad-assign:bad-
 # conditional expression".
 #
 # XXX: The left-hand side is enclosed in quotes.  This results in Var_Parse
-# being called without VARE_UNDEFERR being set.  When ApplyModifier_IfElse
+# being called without VarEvalFlags.undefErr.  When ApplyModifier_IfElse
 # returns AMR_CLEANUP as result, Var_Parse returns varUndefined since the
 # value of the variable expression is still undefined.  CondParser_String is
 # then supposed to do proper error handling, but since varUndefined is local

Index: src/usr.bin/make/unit-tests/varmod-loop.mk
diff -u src/usr.bin/make/unit-tests/varmod-loop.mk:1.10 src/usr.bin/make/unit-tests/varmod-loop.mk:1.11
--- src/usr.bin/make/unit-tests/varmod-loop.mk:1.10	Tue Feb 23 14:17:21 2021
+++ src/usr.bin/make/unit-tests/varmod-loop.mk	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-loop.mk,v 1.10 2021/02/23 14:17:21 rillig Exp $
+# $NetBSD: varmod-loop.mk,v 1.11 2021/03/15 12:15:03 rillig Exp $
 #
 # Tests for the :@var@...${var}...@ variable modifier.
 
@@ -124,9 +124,9 @@ mod-loop-dollar:
 # This string literal is written with 8 dollars, and this is saved as the
 # variable value.  But as soon as this value is evaluated, it goes through
 # Var_Subst, which replaces each '$$' with a single '$'.  This could be
-# prevented by VARE_KEEP_DOLLAR, but that flag is usually removed before
-# expanding subexpressions.  See ApplyModifier_Loop and ParseModifierPart
-# for examples.
+# prevented by VarEvalFlags.keepDollar, but that flag is usually removed
+# before expanding subexpressions.  See ApplyModifier_Loop and
+# ParseModifierPart for examples.
 #
 .MAKEFLAGS: -dcp
 USE_8_DOLLARS=	${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$
@@ -135,20 +135,20 @@ USE_8_DOLLARS=	${:U1:@var@${8_DOLLARS}@}
 .endif
 #
 SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS}
-# The ':=' assignment operator evaluates the variable value using the flag
-# VARE_KEEP_DOLLAR, which means that some dollar signs are preserved, but not
-# all.  The dollar signs in the top-level expression and in the indirect
-# ${8_DOLLARS} are preserved.
+# The ':=' assignment operator evaluates the variable value using the mode
+# VARE_KEEP_DOLLAR_UNDEF, which means that some dollar signs are preserved,
+# but not all.  The dollar signs in the top-level expression and in the
+# indirect ${8_DOLLARS} are preserved.
 #
 # The variable modifier :@var@ does not preserve the dollar signs though, no
 # matter in which context it is evaluated.  What happens in detail is:
 # First, the modifier part "${8_DOLLARS}" is parsed without expanding it.
 # Next, each word of the value is expanded on its own, and at this moment
-# in ApplyModifier_Loop, the VARE_KEEP_DOLLAR flag is not passed down to
+# in ApplyModifier_Loop, the flag keepDollar is not passed down to
 # ModifyWords, resulting in "$$$$" for the first word of USE_8_DOLLARS.
 #
 # The remaining words of USE_8_DOLLARS are not affected by any variable
-# modifier and are thus expanded with the flag VARE_KEEP_DOLLAR in action.
+# modifier and are thus expanded with the flag keepDollar in action.
 # The variable SUBST_CONTAINING_LOOP therefore gets assigned the raw value
 # "$$$$ $$$$$$$$ $$$$$$$$".
 #

Index: src/usr.bin/make/unit-tests/varparse-errors.mk
diff -u src/usr.bin/make/unit-tests/varparse-errors.mk:1.3 src/usr.bin/make/unit-tests/varparse-errors.mk:1.4
--- src/usr.bin/make/unit-tests/varparse-errors.mk:1.3	Sun Dec 20 19:47:34 2020
+++ src/usr.bin/make/unit-tests/varparse-errors.mk	Mon Mar 15 12:15:03 2021
@@ -1,4 +1,4 @@
-# $NetBSD: varparse-errors.mk,v 1.3 2020/12/20 19:47:34 rillig Exp $
+# $NetBSD: varparse-errors.mk,v 1.4 2021/03/15 12:15:03 rillig Exp $
 
 # Tests for parsing and evaluating all kinds of variable expressions.
 #
@@ -25,7 +25,7 @@ ERR_BAD_MOD=	An ${:Uindirect:Z} expressi
 ERR_EVAL=	An evaluation error ${:Uvalue:C,.,\3,}.
 
 # In a conditional, a variable expression that is not enclosed in quotes is
-# expanded using the flags VARE_UNDEFERR and VARE_WANTRES.
+# expanded using the mode VARE_UNDEFERR.
 # The variable itself must be defined.
 # It may refer to undefined variables though.
 .if ${REF_UNDEF} != "A reference to an undefined variable."

Reply via email to