diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2016-10-23 14:54:15 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2016-10-23 14:54:15 +0000 |
commit | a7d8c014706b82ca3ffbf3d366b50814a2f8021a (patch) | |
tree | a92910b1394c2eec12c0cd1ee817a911b91eb937 | |
parent | a8c708926cfd7755b9eb9d41c5cd93e89fef24fe (diff) |
add !!=
feedback and okay millert@
-rw-r--r-- | usr.bin/make/make.1 | 29 | ||||
-rw-r--r-- | usr.bin/make/parse.c | 4 | ||||
-rw-r--r-- | usr.bin/make/parsevar.c | 29 | ||||
-rw-r--r-- | usr.bin/make/var.c | 27 | ||||
-rw-r--r-- | usr.bin/make/var.h | 5 |
5 files changed, 76 insertions, 18 deletions
diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1 index 0a430ba29f9..dfab4bb19ef 100644 --- a/usr.bin/make/make.1 +++ b/usr.bin/make/make.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: make.1,v 1.120 2015/03/13 19:58:41 jmc Exp $ +.\" $OpenBSD: make.1,v 1.121 2016/10/23 14:54:14 espie Exp $ .\" $NetBSD: make.1,v 1.18 1997/03/10 21:19:53 christos Exp $ .\" .\" Copyright (c) 1990, 1993 @@ -30,7 +30,7 @@ .\" .\" from: @(#)make.1 8.4 (Berkeley) 3/19/94 .\" -.Dd $Mdocdate: March 13 2015 $ +.Dd $Mdocdate: October 23 2016 $ .Dt MAKE 1 .Os .Sh NAME @@ -530,13 +530,26 @@ extension .Pc . Normally, expansion is not done until the variable is referenced. .It Ic \&!= -Expand the value and pass it to the shell for execution and assign -the result to the variable. -Any newlines in the result are replaced with spaces +Perform variable expansion and pass the result to the shell for +execution on the spot, assigning the result to the variable. +Any newlines in the result are also replaced with spaces .Po .Bx extension .Pc . +.It Ic \&!!= +Perform variable expansion on the spot and pass the result to the shell +for execution only when the value is needed, assigning the result to +the variable. +.Pp +This is almost identical to +.Ic \&!= +except that a shell is only run when the variable value is needed. +Any newlines in the result are also replaced with spaces +.Po +.Ox +extension +.Pc . .El .Pp Any whitespace before the assigned @@ -558,6 +571,12 @@ if .Va A is not yet defined. .Pp +Combinations that do not make sense, such as +.Bd -literal -offset indent +A +!!= cmd +.Ed +will not work. +.Pp Variables are expanded by surrounding the variable name with either curly braces .Pq Ql {} diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c index ce6f424f8fd..a1dedd1240b 100644 --- a/usr.bin/make/parse.c +++ b/usr.bin/make/parse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.c,v 1.117 2016/10/21 16:12:38 espie Exp $ */ +/* $OpenBSD: parse.c,v 1.118 2016/10/23 14:54:14 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* @@ -1321,7 +1321,7 @@ handle_poison(const char *line) line); return false; } else { - Var_MarkPoisoned(name, ename, type); + Var_Mark(name, ename, type); return true; } } diff --git a/usr.bin/make/parsevar.c b/usr.bin/make/parsevar.c index 5c00622238a..80791272767 100644 --- a/usr.bin/make/parsevar.c +++ b/usr.bin/make/parsevar.c @@ -1,4 +1,4 @@ -/* $OpenBSD: parsevar.c,v 1.15 2013/11/22 15:47:35 espie Exp $ */ +/* $OpenBSD: parsevar.c,v 1.16 2016/10/23 14:54:14 espie Exp $ */ /* $NetBSD: parse.c,v 1.29 1997/03/10 21:20:04 christos Exp $ */ /* @@ -79,6 +79,8 @@ parse_variable_assignment(const char *line, int ctxt) #define VAR_APPEND 2 #define VAR_SHELL 4 #define VAR_OPT 8 +#define VAR_LAZYSHELL 16 +#define VAR_SUNSHELL 32 int type; struct Name name; @@ -90,11 +92,14 @@ parse_variable_assignment(const char *line, int ctxt) type = VAR_NORMAL; + /* double operators (except for :) are forbidden */ + /* OPT and APPEND don't match */ + /* APPEND and LAZYSHELL can't really work */ while (*arg != '=') { /* Check operator type. */ switch (*arg++) { case '+': - if (type & (VAR_OPT|VAR_APPEND)) + if (type & (VAR_OPT|VAR_LAZYSHELL|VAR_APPEND)) type = VAR_INVALID; else type |= VAR_APPEND; @@ -110,7 +115,7 @@ parse_variable_assignment(const char *line, int ctxt) case ':': if (FEATURES(FEATURE_SUNSHCMD) && strncmp(arg, "sh", 2) == 0) { - type = VAR_SHELL; + type = VAR_SUNSHELL; arg += 2; while (*arg != '=' && *arg != '\0') arg++; @@ -123,7 +128,12 @@ parse_variable_assignment(const char *line, int ctxt) break; case '!': - if (type & VAR_SHELL) + if (type & VAR_SHELL) { + if (type & (VAR_APPEND)) + type = VAR_INVALID; + else + type = VAR_LAZYSHELL; + } else if (type & (VAR_LAZYSHELL|VAR_SUNSHELL)) type = VAR_INVALID; else type |= VAR_SHELL; @@ -147,7 +157,7 @@ parse_variable_assignment(const char *line, int ctxt) VarName_Free(&name); return true; } - if (type & VAR_SHELL) { + if (type & (VAR_SHELL|VAR_SUNSHELL)) { char *err; if (strchr(arg, '$') != NULL) { @@ -164,6 +174,13 @@ parse_variable_assignment(const char *line, int ctxt) Parse_Error(PARSE_WARNING, err, arg); arg = res1; } + if (type & VAR_LAZYSHELL) { + if (strchr(arg, '$') != NULL) { + /* There's a dollar sign in the command, so perform + * variable expansion on the whole thing. */ + arg = Var_Subst(arg, NULL, true); + } + } if (type & VAR_SUBST) { /* * Allow variables in the old value to be undefined, but leave @@ -195,6 +212,8 @@ parse_variable_assignment(const char *line, int ctxt) Var_Appendi_with_ctxt(name.s, name.e, arg, ctxt); else Var_Seti_with_ctxt(name.s, name.e, arg, ctxt); + if (type & VAR_LAZYSHELL) + Var_Mark(name.s, name.e, VAR_EXEC_LATER); VarName_Free(&name); free(res2); diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c index 94853d6b7d9..0ed3654bc36 100644 --- a/usr.bin/make/var.c +++ b/usr.bin/make/var.c @@ -1,4 +1,4 @@ -/* $OpenBSD: var.c,v 1.100 2016/10/14 09:27:21 natano Exp $ */ +/* $OpenBSD: var.c,v 1.101 2016/10/23 14:54:14 espie Exp $ */ /* $NetBSD: var.c,v 1.18 1997/03/18 19:24:46 christos Exp $ */ /* @@ -72,6 +72,7 @@ #include "config.h" #include "defines.h" #include "buf.h" +#include "cmd_exec.h" #include "stats.h" #include "pathnames.h" #include "varmodifiers.h" @@ -241,7 +242,10 @@ static void fill_from_env(Var *); static Var *create_var(const char *, const char *); static void var_set_initial_value(Var *, const char *); static void var_set_value(Var *, const char *); -#define var_get_value(v) Buf_Retrieve(&((v)->val)) +#define var_get_value(v) ((v)->flags & VAR_EXEC_LATER ? \ + var_exec_cmd(v) : \ + Buf_Retrieve(&((v)->val))) +static char *var_exec_cmd(Var *); static void var_append_value(Var *, const char *); static void poison_check(Var *); static void var_set_append(const char *, const char *, const char *, int, bool); @@ -538,10 +542,10 @@ find_global_var(const char *name, const char *ename, uint32_t k) return v; } -/* mark variable as poisoned, in a given setup. +/* mark variable with special flags, in a given setup. */ void -Var_MarkPoisoned(const char *name, const char *ename, unsigned int type) +Var_Mark(const char *name, const char *ename, unsigned int type) { Var *v; uint32_t k; @@ -680,6 +684,21 @@ Var_Appendi_with_ctxt(const char *name, const char *ename, const char *val, var_set_append(name, ename, val, ctxt, true); } +static char * +var_exec_cmd(Var *v) +{ + char *arg = Buf_Retrieve(&(v->val)); + char *err; + char *res1; + res1 = Cmd_Exec(arg, &err); + if (err) + Parse_Error(PARSE_WARNING, err, arg); + var_set_value(v, res1); + free(res1); + v->flags &= ~VAR_EXEC_LATER; + return Buf_Retrieve(&(v->val)); +} + /* XXX different semantics for Var_Valuei() and Var_Definedi(): * references to poisoned value variables will error out in Var_Valuei(), * but not in Var_Definedi(), so the following construct works: diff --git a/usr.bin/make/var.h b/usr.bin/make/var.h index 6083bffc24f..e7246a331fc 100644 --- a/usr.bin/make/var.h +++ b/usr.bin/make/var.h @@ -1,6 +1,6 @@ #ifndef VAR_H #define VAR_H -/* $OpenBSD: var.h,v 1.18 2016/10/14 09:27:21 natano Exp $ */ +/* $OpenBSD: var.h,v 1.19 2016/10/23 14:54:14 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. * @@ -161,6 +161,7 @@ extern bool errorIsOkay; #define POISON_NORMAL 64 #define POISON_EMPTY 128 #define POISON_NOT_DEFINED 256 +#define VAR_EXEC_LATER 512 -extern void Var_MarkPoisoned(const char *, const char *, unsigned int); +extern void Var_Mark(const char *, const char *, unsigned int); #endif |