summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Espie <espie@cvs.openbsd.org>2016-10-23 14:54:15 +0000
committerMarc Espie <espie@cvs.openbsd.org>2016-10-23 14:54:15 +0000
commita7d8c014706b82ca3ffbf3d366b50814a2f8021a (patch)
treea92910b1394c2eec12c0cd1ee817a911b91eb937
parenta8c708926cfd7755b9eb9d41c5cd93e89fef24fe (diff)
add !!=
feedback and okay millert@
-rw-r--r--usr.bin/make/make.129
-rw-r--r--usr.bin/make/parse.c4
-rw-r--r--usr.bin/make/parsevar.c29
-rw-r--r--usr.bin/make/var.c27
-rw-r--r--usr.bin/make/var.h5
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