summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorharti <harti@FreeBSD.org>2005-05-06 18:30:06 +0000
committerharti <harti@FreeBSD.org>2005-05-06 18:30:06 +0000
commit9e2faf2a2d1d132b64803f711bdc86494a945dea (patch)
tree63e1aad932422a7e009bf4546d317d2a3db92daf /usr.bin
parent491568ac84a241eb8ffe4266ddf975db8e546faa (diff)
downloadFreeBSD-src-9e2faf2a2d1d132b64803f711bdc86494a945dea.zip
FreeBSD-src-9e2faf2a2d1d132b64803f711bdc86494a945dea.tar.gz
Introduce a new pseudo-target .EXPORTVAR which allows to put a
make macro into the environment of programs executed by make. This has approximately the same function as gmake's export directive. The form of a pseudo target was deliberately choosen to minimize work for POSIX compatibility (Makefiles are not allowed to use any targets starting with a dot and consisting only of uppercase letters except those specified in the standard when they want POSIX compatible behaviour, so such a Makefile can never contain .EXPORTVAR.) Change the handling of macros coming from the environment: instead of asking the environment for each variable we could not find otherwise put all the environment variables in a special variable environment just at start up. This has been tested on the ports cluster by kris. Submitted by: Max Okumoto <okumoto@ucsd.edu>
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/make/hash_tables.c49
-rw-r--r--usr.bin/make/main.c5
-rw-r--r--usr.bin/make/parse.c6
-rw-r--r--usr.bin/make/var.c146
-rw-r--r--usr.bin/make/var.h7
5 files changed, 119 insertions, 94 deletions
diff --git a/usr.bin/make/hash_tables.c b/usr.bin/make/hash_tables.c
index 5c5e16a..5436326 100644
--- a/usr.bin/make/hash_tables.c
+++ b/usr.bin/make/hash_tables.c
@@ -1,7 +1,7 @@
/*
* DO NOT EDIT
* $FreeBSD$
- * auto-generated from FreeBSD: src/usr.bin/make/parse.c,v 1.99 2005/04/29 14:37:44 harti Exp
+ * auto-generated from FreeBSD: src/usr.bin/make/parse.c,v 1.100 2005/04/29 15:15:28 harti Exp
* DO NOT EDIT
*/
#include <sys/types.h>
@@ -66,8 +66,8 @@ directive_hash(const u_char *key, size_t len)
}
/*
* d=2
- * n=69
- * m=33
+ * n=72
+ * m=34
* c=2.09
* maxlen=1
* minklen=4
@@ -75,34 +75,35 @@ directive_hash(const u_char *key, size_t len)
* minchar=46
* maxchar=95
* loop=0
- * numiter=8
+ * numiter=4
* seed=
*/
static const signed char keyword_g[] = {
- -1, 17, 16, 0, -1, -1, -1, -1, 25, 18,
- 2, -1, -1, 27, 28, 1, 0, 15, 16, -1,
- -1, 14, 19, 1, -1, 13, -1, 0, 1, -1,
- 11, 15, 0, 8, 14, 18, 31, -1, -1, 22,
- -1, 27, -1, 0, -1, 9, -1, -1, -1, 21,
- 3, 25, 0, 0, 0, -1, -1, 6, 0, 19,
- -1, -1, -1, 23, -1, 17, -1, 0, 0,
+ 8, 15, -1, 25, 22, 20, -1, 33, 16, -1,
+ 21, 31, 0, 0, 0, 29, 30, 8, -1, 0,
+ -1, 21, -1, 0, -1, -1, -1, -1, -1, 4,
+ -1, -1, 25, 28, -1, 27, 11, 23, 0, 0,
+ 24, -1, -1, 0, 3, 0, -1, 24, 0, 0,
+ -1, 28, 12, -1, 20, 13, -1, 5, -1, 1,
+ 0, 0, -1, 0, 10, 19, 13, 9, -1, 2,
+ -1, -1,
};
static const u_char keyword_T0[] = {
- 8, 30, 55, 61, 14, 13, 48, 1, 18, 12,
- 0, 52, 1, 40, 44, 52, 33, 58, 29, 29,
- 3, 30, 26, 42, 1, 49, 10, 26, 5, 45,
- 65, 13, 6, 22, 45, 61, 7, 25, 62, 65,
- 8, 34, 48, 50, 5, 63, 33, 38, 52, 33,
+ 32, 10, 54, 61, 2, 35, 62, 50, 52, 53,
+ 70, 7, 62, 18, 24, 30, 31, 66, 10, 61,
+ 52, 71, 56, 56, 28, 6, 33, 67, 12, 41,
+ 39, 45, 51, 21, 34, 53, 56, 40, 47, 52,
+ 21, 61, 60, 12, 7, 28, 42, 38, 38, 52,
};
static const u_char keyword_T1[] = {
- 44, 18, 49, 61, 56, 13, 1, 54, 1, 47,
- 46, 17, 22, 36, 25, 66, 14, 36, 58, 51,
- 60, 22, 61, 19, 43, 37, 5, 18, 50, 58,
- 32, 65, 47, 12, 28, 34, 65, 29, 59, 67,
- 48, 36, 15, 41, 44, 11, 39, 29, 18, 68,
+ 0, 39, 65, 48, 13, 62, 46, 42, 5, 50,
+ 69, 69, 69, 43, 2, 46, 12, 6, 11, 9,
+ 24, 10, 25, 64, 68, 13, 57, 55, 17, 33,
+ 1, 18, 0, 67, 10, 14, 57, 56, 0, 6,
+ 50, 13, 3, 47, 56, 22, 37, 13, 28, 48,
};
@@ -122,8 +123,8 @@ keyword_hash(const u_char *key, size_t len)
f1 += keyword_T1[-46 + *kp];
}
- f0 %= 69;
- f1 %= 69;
+ f0 %= 72;
+ f1 %= 72;
- return (keyword_g[f0] + keyword_g[f1]) % 33;
+ return (keyword_g[f0] + keyword_g[f1]) % 34;
}
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 8bb8897..2b8fd8a 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -101,6 +101,8 @@ __FBSDID("$FreeBSD$");
#define MAKEFLAGS ".MAKEFLAGS"
+extern char **environ; /* XXX what header declares this variable? */
+
/* Targets to be made */
Lst create = Lst_Initializer(create);
@@ -695,7 +697,7 @@ main(int argc, char **argv)
*/
Dir_Init(); /* Initialize directory structures so -I flags
* can be processed correctly */
- Var_Init(); /* As well as the lists of variables for
+ Var_Init(environ); /* As well as the lists of variables for
* parsing arguments */
str_init();
@@ -781,6 +783,7 @@ main(int argc, char **argv)
Dir_InitDot(); /* Initialize the "." directory */
if (objdir != curdir)
Path_AddDir(&dirSearchPath, curdir);
+ Var_Set(".ST_EXPORTVAR", "YES", VAR_GLOBAL);
Var_Set(".CURDIR", curdir, VAR_GLOBAL);
Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
diff --git a/usr.bin/make/parse.c b/usr.bin/make/parse.c
index 56f9e24..fb48a77 100644
--- a/usr.bin/make/parse.c
+++ b/usr.bin/make/parse.c
@@ -153,13 +153,13 @@ typedef enum {
Begin, /* .BEGIN */
Default, /* .DEFAULT */
End, /* .END */
+ ExportVar, /* .EXPORTVAR */
Ignore, /* .IGNORE */
Includes, /* .INCLUDES */
Interrupt, /* .INTERRUPT */
Libs, /* .LIBS */
MFlags, /* .MFLAGS or .MAKEFLAGS */
Main, /* .MAIN and we don't have anyth. user-spec. to make */
- NoExport, /* .NOEXPORT */
Not, /* Not special */
NotParallel, /* .NOTPARALELL */
Null, /* .NULL */
@@ -204,6 +204,7 @@ static const struct keyword {
{ ".DEFAULT", Default, 0 },
{ ".END", End, 0 },
{ ".EXEC", Attribute, OP_EXEC },
+ { ".EXPORTVAR", ExportVar, 0 },
{ ".IGNORE", Ignore, OP_IGNORE },
{ ".INCLUDES", Includes, 0 },
{ ".INTERRUPT", Interrupt, 0 },
@@ -1170,6 +1171,9 @@ ParseDoDependency(char *line)
}
Lst_Destroy(&paths, NOFREE);
+ } else if (specType == ExportVar) {
+ Var_SetEnv(line, VAR_GLOBAL);
+
} else {
/* list of sources in order */
Lst curSrcs = Lst_Initializer(curSrc);
diff --git a/usr.bin/make/var.c b/usr.bin/make/var.c
index 892e1da..6be737c 100644
--- a/usr.bin/make/var.c
+++ b/usr.bin/make/var.c
@@ -141,6 +141,7 @@ static char varNoError[] = "";
* The four contexts are searched in the reverse order from which they are
* listed.
*/
+GNode *VAR_ENV; /* variables from the environment */
GNode *VAR_GLOBAL; /* variables from the makefile */
GNode *VAR_CMD; /* variables defined on the command-line */
@@ -283,19 +284,14 @@ static Var *
VarFindEnv(const char name[], GNode *ctxt)
{
Var *var;
- char *env;
name = VarLocal(name);
- /* First look for the variable in the given context. */
if ((var = VarLookup(&ctxt->context, name)) != NULL)
return (var);
- /* Look for the variable in the environment. */
- if ((env = getenv(name)) != NULL) {
- /* craft this variable from the environment value */
- return (VarCreate(name, env, VAR_FROM_ENV));
- }
+ if ((var = VarLookup(&VAR_ENV->context, name)) != NULL)
+ return (var);
return (NULL);
}
@@ -325,7 +321,6 @@ VarFindAny(const char name[], GNode *ctxt)
Boolean localCheckEnvFirst;
LstNode *ln;
Var *var;
- char *env;
name = VarLocal(name);
@@ -361,11 +356,8 @@ VarFindAny(const char name[], GNode *ctxt)
return (var);
}
- /* look in the environment */
- if ((env = getenv(name)) != NULL) {
- /* craft this variable from the environment value */
- return (VarCreate(name, env, VAR_FROM_ENV));
- }
+ if ((var = VarLookup(&VAR_ENV->context, name)) != NULL)
+ return (var);
/* deferred check for the environment (in case of -e/-E) */
if ((ctxt != VAR_GLOBAL) && (checkEnvFirst || localCheckEnvFirst)) {
@@ -376,10 +368,8 @@ VarFindAny(const char name[], GNode *ctxt)
return (NULL);
}
-/*-
- *-----------------------------------------------------------------------
- * VarAdd --
- * Add a new variable of name name and value val to the given context.
+/**
+ * Add a new variable of name name and value val to the given context.
*
* Results:
* None
@@ -388,7 +378,6 @@ VarFindAny(const char name[], GNode *ctxt)
* The new variable is placed at the front of the given context
* The name and val arguments are duplicated so they may
* safely be freed.
- *-----------------------------------------------------------------------
*/
static void
VarAdd(const char *name, const char *val, GNode *ctxt)
@@ -462,22 +451,68 @@ Var_Set(const char *name, const char *val, GNode *ctxt)
v = VarFindOnly(n, ctxt);
if (v == NULL) {
VarAdd(n, val, ctxt);
+ if (ctxt == VAR_CMD) {
+ /*
+ * Any variables given on the command line
+ * are automatically exported to the
+ * environment (as per POSIX standard)
+ */
+ setenv(n, val, 1);
+ }
} else {
Buf_Clear(v->val);
Buf_Append(v->val, val);
- DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, val));
- }
- /*
- * Any variables given on the command line are automatically exported
- * to the environment (as per POSIX standard)
- */
- if (ctxt == VAR_CMD) {
- setenv(n, val, 1);
+ if (ctxt == VAR_CMD || (v->flags & VAR_TO_ENV)) {
+ /*
+ * Any variables given on the command line
+ * are automatically exported to the
+ * environment (as per POSIX standard)
+ */
+ setenv(n, val, 1);
+ }
+
}
+
+ DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, val));
free(n);
}
+/*
+ * Var_SetEnv --
+ * Set the VAR_TO_ENV flag on a variable
+ */
+void
+Var_SetEnv(const char *name, GNode *ctxt)
+{
+ Var *v;
+
+ v = VarFindOnly(name, VAR_CMD);
+ if (v != NULL) {
+ /*
+ * Do not allow .EXPORT: to be set on variables
+ * from the comand line or MAKEFLAGS.
+ */
+ Error(
+ "Warning: Did not set .EXPORTVAR: on %s because it "
+ "is from the comand line or MAKEFLAGS", name);
+ return;
+ }
+
+ v = VarFindAny(name, ctxt);
+ if (v == NULL) {
+ Lst_AtFront(&VAR_ENV->context,
+ VarCreate(name, NULL, VAR_TO_ENV));
+ setenv(name, "", 1);
+ Error("Warning: .EXPORTVAR: set on undefined variable %s", name);
+ } else {
+ if ((v->flags & VAR_TO_ENV) == 0) {
+ v->flags |= VAR_TO_ENV;
+ setenv(v->name, Buf_Data(v->val), 1);
+ }
+ }
+}
+
/*-
*-----------------------------------------------------------------------
* Var_Append --
@@ -514,21 +549,6 @@ Var_Append(const char *name, const char *val, GNode *ctxt)
}
if (v == NULL) {
VarAdd(n, val, ctxt);
-
- } else if (v->flags & VAR_FROM_ENV) {
- Buf_AddByte(v->val, (Byte)' ');
- Buf_Append(v->val, val);
- DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, Buf_Data(v->val)));
- /*
- * If the original variable came from the
- * environment, we have to install it in the global
- * context (we could place it in the environment, but
- * then we should provide a way to export other
- * variables...)
- */
- v->flags &= ~VAR_FROM_ENV;
- Lst_AtFront(&ctxt->context, v);
-
} else {
Buf_AddByte(v->val, (Byte)' ');
Buf_Append(v->val, val);
@@ -561,10 +581,6 @@ Var_Exists(const char *name, GNode *ctxt)
if (v == NULL) {
free(n);
return (FALSE);
- } else if (v->flags & VAR_FROM_ENV) {
- VarDestroy(v, TRUE);
- free(n);
- return (TRUE);
} else {
free(n);
return (TRUE);
@@ -595,10 +611,6 @@ Var_Value(const char *name, GNode *ctxt, char **frp)
if (v == NULL) {
p = NULL;
*frp = NULL;
- } else if (v->flags & VAR_FROM_ENV) {
- p = Buf_Data(v->val);
- *frp = p;
- VarDestroy(v, FALSE);
} else {
p = Buf_Data(v->val);
*frp = NULL;
@@ -1320,10 +1332,6 @@ ParseRestModifier(VarParser *vp, char startc, Buffer *buf, Boolean *freeResult)
v = VarFindAny(vname, vp->ctxt);
if (v != NULL) {
value = ParseModifier(vp, startc, v, freeResult);
-
- if (v->flags & VAR_FROM_ENV) {
- VarDestroy(v, TRUE);
- }
return (value);
}
@@ -1430,11 +1438,6 @@ ParseRestEnd(VarParser *vp, Buffer *buf, Boolean *freeResult)
v = VarFindAny(vname, vp->ctxt);
if (v != NULL) {
value = VarExpand(v, vp);
-
- if (v->flags & VAR_FROM_ENV) {
- VarDestroy(v, TRUE);
- }
-
*freeResult = TRUE;
return (value);
}
@@ -1600,11 +1603,6 @@ VarParseShort(VarParser *vp, Boolean *freeResult)
v = VarFindAny(vname, vp->ctxt);
if (v != NULL) {
value = VarExpand(v, vp);
-
- if (v->flags & VAR_FROM_ENV) {
- VarDestroy(v, TRUE);
- }
-
*freeResult = TRUE;
return (value);
}
@@ -1950,11 +1948,29 @@ Var_GetHead(char *file)
*-----------------------------------------------------------------------
*/
void
-Var_Init(void)
+Var_Init(char **env)
{
+ char **ptr;
- VAR_GLOBAL = Targ_NewGN("Global");
VAR_CMD = Targ_NewGN("Command");
+ VAR_ENV = Targ_NewGN("Environment");
+ VAR_GLOBAL = Targ_NewGN("Global");
+
+ /*
+ * Copy user environment variables into ENV context.
+ */
+ for (ptr = env; *ptr != NULL; ++ptr) {
+ char *tmp = estrdup(*ptr);
+ const char *name = tmp;
+ char *sep = strchr(name, '=');
+ const char *value = sep + 1;
+
+ if (sep != NULL) {
+ *sep = '\0';
+ VarAdd(name, value, VAR_ENV);
+ }
+ free(tmp);
+ }
}
/*-
diff --git a/usr.bin/make/var.h b/usr.bin/make/var.h
index 3128b2b..f5fb9c6 100644
--- a/usr.bin/make/var.h
+++ b/usr.bin/make/var.h
@@ -57,12 +57,12 @@ typedef struct Var {
#define VAR_IN_USE 1 /* Variable's value currently being used.
* Used to avoid recursion */
-#define VAR_FROM_ENV 2 /* Variable comes from the environment */
-
#define VAR_JUNK 4 /* Variable is a junk variable that
* should be destroyed when done with
* it. Used by Var_Parse for undefined,
* modified variables */
+
+#define VAR_TO_ENV 8 /* Place variable in environment */
} Var;
/* Var*Pattern flags */
@@ -95,10 +95,11 @@ void Var_Dump(const struct GNode *);
Boolean Var_Exists(const char *, struct GNode *);
char *Var_GetHead(char *);
char *Var_GetTail(char *);
-void Var_Init(void);
+void Var_Init(char **);
char *Var_Parse(const char *, struct GNode *, Boolean, size_t *, Boolean *);
char *Var_Quote(const char *);
void Var_Set(const char *, const char *, struct GNode *);
+void Var_SetEnv(const char *, struct GNode *);
struct Buffer *Var_Subst(const char *, const char *, struct GNode *, Boolean);
char *Var_Value(const char *, struct GNode *, char **);
OpenPOWER on IntegriCloud