Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make make(1): allow .undef to undefine multiple vari...



details:   https://anonhg.NetBSD.org/src/rev/1bfb06c1aa99
branches:  trunk
changeset: 948250:1bfb06c1aa99
user:      rillig <rillig%NetBSD.org@localhost>
date:      Tue Dec 22 20:10:21 2020 +0000

description:
make(1): allow .undef to undefine multiple variables at once

Since make doesn't support variable names containing spaces, this edge
case is not enough reason to stop this feature.  Having multiple
variable names as arguments nicely aligns with other directives such as
.for and .export.

diffstat:

 usr.bin/make/make.1                         |  10 ++--
 usr.bin/make/nonints.h                      |   4 +-
 usr.bin/make/unit-tests/directive-undef.exp |   4 +-
 usr.bin/make/unit-tests/directive-undef.mk  |  51 ++++++++++++++---------
 usr.bin/make/var.c                          |  60 ++++++++++++++--------------
 5 files changed, 71 insertions(+), 58 deletions(-)

diffs (247 lines):

diff -r d42a81270f9e -r 1bfb06c1aa99 usr.bin/make/make.1
--- a/usr.bin/make/make.1       Tue Dec 22 19:38:44 2020 +0000
+++ b/usr.bin/make/make.1       Tue Dec 22 20:10:21 2020 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: make.1,v 1.293 2020/11/25 00:50:44 sjg Exp $
+.\"    $NetBSD: make.1,v 1.294 2020/12/22 20:10:21 rillig Exp $
 .\"
 .\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"    from: @(#)make.1        8.4 (Berkeley) 3/19/94
 .\"
-.Dd November 24, 2020
+.Dd December 22, 2020
 .Dt MAKE 1
 .Os
 .Sh NAME
@@ -1748,9 +1748,9 @@
 except that variables in the value are not expanded.
 .It Ic .info Ar message
 The message is printed along with the name of the makefile and line number.
-.It Ic .undef Ar variable
-Un-define the specified global variable.
-Only global variables may be un-defined.
+.It Ic .undef Ar variable ...
+Un-define the specified global variables.
+Only global variables can be un-defined.
 .It Ic .unexport Ar variable ...
 The opposite of
 .Ql .export .
diff -r d42a81270f9e -r 1bfb06c1aa99 usr.bin/make/nonints.h
--- a/usr.bin/make/nonints.h    Tue Dec 22 19:38:44 2020 +0000
+++ b/usr.bin/make/nonints.h    Tue Dec 22 20:10:21 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nonints.h,v 1.180 2020/12/20 21:07:32 rillig Exp $     */
+/*     $NetBSD: nonints.h,v 1.181 2020/12/22 20:10:21 rillig Exp $     */
 
 /*-
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -396,7 +396,7 @@
 
 void Var_DeleteVar(const char *, GNode *);
 void Var_Delete(const char *, GNode *);
-void Var_Undef(char *);
+void Var_Undef(const char *);
 void Var_Set(const char *, const char *, GNode *);
 void Var_SetWithFlags(const char *, const char *, GNode *, VarSetFlags);
 void Var_Append(const char *, const char *, GNode *);
diff -r d42a81270f9e -r 1bfb06c1aa99 usr.bin/make/unit-tests/directive-undef.exp
--- a/usr.bin/make/unit-tests/directive-undef.exp       Tue Dec 22 19:38:44 2020 +0000
+++ b/usr.bin/make/unit-tests/directive-undef.exp       Tue Dec 22 20:10:21 2020 +0000
@@ -1,5 +1,5 @@
-make: "directive-undef.mk" line 14: The .undef directive requires exactly 1 argument
-make: "directive-undef.mk" line 24: The .undef directive requires exactly 1 argument
+make: "directive-undef.mk" line 29: The .undef directive requires an argument
+make: "directive-undef.mk" line 86: Unknown modifier 'Z'
 make: Fatal errors encountered -- cannot continue
 make: stopped in unit-tests
 exit status 1
diff -r d42a81270f9e -r 1bfb06c1aa99 usr.bin/make/unit-tests/directive-undef.mk
--- a/usr.bin/make/unit-tests/directive-undef.mk        Tue Dec 22 19:38:44 2020 +0000
+++ b/usr.bin/make/unit-tests/directive-undef.mk        Tue Dec 22 20:10:21 2020 +0000
@@ -1,18 +1,23 @@
-# $NetBSD: directive-undef.mk,v 1.8 2020/12/19 22:10:18 rillig Exp $
+# $NetBSD: directive-undef.mk,v 1.9 2020/12/22 20:10:21 rillig Exp $
 #
 # Tests for the .undef directive.
 #
 # See also:
 #      directive-misspellings.mk
 
-# As of 2020-07-28, .undef only undefines the first variable.
-# All further variable names are silently ignored.
-# See parse.c, string literal "undef".
+# Before var.c 1.737 from 2020-12-19, .undef only undefined the first
+# variable, silently skipping all further variable names.
+#
+# Before var.c 1.761 from 2020-12-22, .undef complained about too many
+# arguments.
+#
+# Since var.c 1.761 from 2020-12-22, .undef handles multiple variable names
+# just like the .export directive.
 1=             1
 2=             2
 3=             3
 .undef 1 2 3
-.if ${1:U_}${2:U_}${3:U_} != _23
+.if ${1:U_}${2:U_}${3:U_} != ___
 .  warning $1$2$3
 .endif
 
@@ -29,41 +34,39 @@
 .undef ${:U}
 
 
-# The argument of .undef is a single word, delimited by whitespace, without
-# any possibility of escaping or having variable expressions containing
-# spaces.  This word is then expanded exactly once, and the expanded string
-# is the single variable name.  This allows variable names to contain spaces,
-# as well as unbalanced single and double quotes.
+# The argument of .undef is first expanded exactly once and then split into
+# words, just like everywhere else.  This prevents variables whose names
+# contain spaces or unbalanced 'single' or "double" quotes from being
+# undefined, but these characters do not appear in variables names anyway.
 1=             1
 2=             2
 3=             3
 ${:U1 2 3}=    one two three
 VARNAMES=      1 2 3
 .undef ${VARNAMES}             # undefines the variable "1 2 3"
-.if defined(${:U1 2 3})
-.  error
-.endif
-.if ${1}${2}${3} != "123"      # these are still defined
+.if !defined(${:U1 2 3})
 .  error
 .endif
-.undef 1
-.undef 2
-.undef 3
+.if ${1:U_}${2:U_}${3:U_} != "___"     # these are still defined
+.  error
+.endif
 
 
-# It must be possible to undefine variables whose name includes spaces.
+# A variable named " " cannot be undefined.  There's no practical use case
+# for such variables anyway.
 SPACE=         ${:U }
 ${SPACE}=      space
 .if !defined(${SPACE})
 .  error
 .endif
 .undef ${SPACE}
-.if defined(${SPACE})
+.if !defined(${SPACE})
 .  error
 .endif
 
 
-# It must be possible to undefine variables whose name includes dollars.
+# A variable named "$" can be undefined since the argument to .undef is
+# expanded exactly once, before being split into words.
 DOLLAR=                $$
 ${DOLLAR}=     dollar
 .if !defined(${DOLLAR})
@@ -75,5 +78,13 @@
 .endif
 
 
+# Since var.c 1.762 from 2020-12-22, parse errors in the argument should be
+# properly detected and should stop the .undef directive from doing any work.
+#
+# As of var.c 1.762, this doesn't happen though because the error handling
+# in Var_Parse and Var_Subst is not done properly.
+.undef ${VARNAMES:L:Z}
+
+
 all:
        @:;
diff -r d42a81270f9e -r 1bfb06c1aa99 usr.bin/make/var.c
--- a/usr.bin/make/var.c        Tue Dec 22 19:38:44 2020 +0000
+++ b/usr.bin/make/var.c        Tue Dec 22 20:10:21 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: var.c,v 1.761 2020/12/21 21:04:18 rillig Exp $ */
+/*     $NetBSD: var.c,v 1.762 2020/12/22 20:10:21 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -131,7 +131,7 @@
 #include "metachar.h"
 
 /*     "@(#)var.c      8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.761 2020/12/21 21:04:18 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.762 2020/12/22 20:10:21 rillig Exp $");
 
 typedef enum VarFlags {
        VAR_NONE        = 0,
@@ -513,38 +513,40 @@
 }
 
 /*
- * Undefine a single variable from the global scope.  The argument is
- * expanded once.
+ * Undefine one or more variables from the global scope.
+ * The argument is expanded exactly once and then split into words.
  */
 void
-Var_Undef(char *arg)
+Var_Undef(const char *arg)
 {
-       /*
-        * The argument must consist of exactly 1 word.  Accepting more than
-        * 1 word would have required to split the argument into several
-        * words, and such splitting is already done subtly different in many
-        * other places of make.
-        *
-        * Using Str_Words to split the words, followed by Var_Subst to expand
-        * each variable name once would make it impossible to undefine
-        * variables whose names contain space characters or unbalanced
-        * quotes or backslashes in arbitrary positions.
-        *
-        * Using Var_Subst on the whole argument and splitting the words
-        * afterwards using Str_Words would make it impossible to undefine
-        * variables whose names contain space characters.
-        */
-       char *cp = arg;
-
-       for (; !ch_isspace(*cp) && *cp != '\0'; cp++)
-               continue;
-       if (cp == arg || *cp != '\0') {
+       VarParseResult vpr;
+       char *expanded;
+       Words varnames;
+       size_t i;
+
+       if (arg[0] == '\0') {
+               Parse_Error(PARSE_FATAL,
+                   "The .undef directive requires an argument");
+               return;
+       }
+
+       vpr = Var_Subst(arg, VAR_GLOBAL, VARE_WANTRES, &expanded);
+       if (vpr != VPR_OK) {
                Parse_Error(PARSE_FATAL,
-                   "The .undef directive requires exactly 1 argument");
+                   "Error in variable names to be undefined");
+               return;
        }
-       *cp = '\0';
-
-       Var_Delete(arg, VAR_GLOBAL);
+
+       varnames = Str_Words(expanded, FALSE);
+       if (varnames.len == 1 && varnames.words[0][0] == '\0')
+               varnames.len = 0;
+
+       for (i = 0; i < varnames.len; i++) {
+               const char *varname = varnames.words[i];
+               Var_DeleteVar(varname, VAR_GLOBAL);
+       }
+
+       Words_Free(varnames);
 }
 
 static Boolean



Home | Main Index | Thread Index | Old Index