summaryrefslogtreecommitdiff
path: root/devel/bmake/files/var.c
diff options
context:
space:
mode:
Diffstat (limited to 'devel/bmake/files/var.c')
-rw-r--r--devel/bmake/files/var.c263
1 files changed, 137 insertions, 126 deletions
diff --git a/devel/bmake/files/var.c b/devel/bmake/files/var.c
index 28fa6c30e57..946a235f310 100644
--- a/devel/bmake/files/var.c
+++ b/devel/bmake/files/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1.1.9 2011/06/18 22:18:13 bsiegert Exp $ */
+/* $NetBSD: var.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.1.1.9 2011/06/18 22:18:13 bsiegert Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: var.c,v 1.1.1.9 2011/06/18 22:18:13 bsiegert Exp $");
+__RCSID("$NetBSD: var.c,v 1.1.1.10 2015/05/19 21:36:44 joerg Exp $");
#endif
#endif /* not lint */
#endif
@@ -139,6 +139,13 @@ __RCSID("$NetBSD: var.c,v 1.1.1.9 2011/06/18 22:18:13 bsiegert Exp $");
#include "dir.h"
#include "job.h"
+extern int makelevel;
+/*
+ * This lets us tell if we have replaced the original environ
+ * (which we cannot free).
+ */
+char **savedEnv = NULL;
+
/*
* This is a harmless return value for Var_Parse that can be used by Var_Subst
* to determine if there was an error in parsing -- easier than returning
@@ -169,6 +176,7 @@ static char varNoError[] = "";
* The four contexts are searched in the reverse order from which they are
* listed.
*/
+GNode *VAR_INTERNAL; /* variables from make itself */
GNode *VAR_GLOBAL; /* variables from the makefile */
GNode *VAR_CMD; /* variables defined on the command-line */
@@ -303,7 +311,6 @@ static char *VarGetPattern(GNode *, Var_Parse_State *,
int, const char **, int, int *, int *,
VarPattern *);
static char *VarQuote(char *);
-static char *VarChangeCase(char *, int);
static char *VarHash(char *);
static char *VarModify(GNode *, Var_Parse_State *,
const char *,
@@ -402,6 +409,10 @@ VarFind(const char *name, GNode *ctxt, int flags)
(ctxt != VAR_GLOBAL))
{
var = Hash_FindEntry(&VAR_GLOBAL->context, name);
+ if ((var == NULL) && (ctxt != VAR_INTERNAL)) {
+ /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
+ var = Hash_FindEntry(&VAR_INTERNAL->context, name);
+ }
}
if ((var == NULL) && (flags & FIND_ENV)) {
char *env;
@@ -423,6 +434,9 @@ VarFind(const char *name, GNode *ctxt, int flags)
(ctxt != VAR_GLOBAL))
{
var = Hash_FindEntry(&VAR_GLOBAL->context, name);
+ if ((var == NULL) && (ctxt != VAR_INTERNAL)) {
+ var = Hash_FindEntry(&VAR_INTERNAL->context, name);
+ }
if (var == NULL) {
return NULL;
} else {
@@ -524,11 +538,20 @@ void
Var_Delete(const char *name, GNode *ctxt)
{
Hash_Entry *ln;
-
- ln = Hash_FindEntry(&ctxt->context, name);
+ char *cp;
+
+ if (strchr(name, '$')) {
+ cp = Var_Subst(NULL, name, VAR_GLOBAL, 0);
+ } else {
+ cp = (char *)name;
+ }
+ ln = Hash_FindEntry(&ctxt->context, cp);
if (DEBUG(VAR)) {
fprintf(debug_file, "%s:delete %s%s\n",
- ctxt->name, name, ln ? "" : " (not found)");
+ ctxt->name, cp, ln ? "" : " (not found)");
+ }
+ if (cp != name) {
+ free(cp);
}
if (ln != NULL) {
Var *v;
@@ -643,6 +666,15 @@ Var_ExportVars(void)
char *val;
int n;
+ /*
+ * Several make's support this sort of mechanism for tracking
+ * recursion - but each uses a different name.
+ * We allow the makefiles to update MAKELEVEL and ensure
+ * children see a correctly incremented value.
+ */
+ snprintf(tmp, sizeof(tmp), "%d", makelevel + 1);
+ setenv(MAKE_LEVEL_ENV, tmp, 1);
+
if (VAR_EXPORTED_NONE == var_exportedVars)
return;
@@ -742,6 +774,8 @@ Var_Export(char *str, int isExport)
/*
* This is called when .unexport[-env] is seen.
*/
+extern char **environ;
+
void
Var_UnExport(char *str)
{
@@ -760,28 +794,26 @@ Var_UnExport(char *str)
str += 8;
unexport_env = (strncmp(str, "-env", 4) == 0);
if (unexport_env) {
- extern char **environ;
- static char **savenv;
char **newenv;
- cp = getenv(MAKE_LEVEL); /* we should preserve this */
- if (environ == savenv) {
+ cp = getenv(MAKE_LEVEL_ENV); /* we should preserve this */
+ if (environ == savedEnv) {
/* we have been here before! */
newenv = bmake_realloc(environ, 2 * sizeof(char *));
} else {
- if (savenv) {
- free(savenv);
- savenv = NULL;
+ if (savedEnv) {
+ free(savedEnv);
+ savedEnv = NULL;
}
newenv = bmake_malloc(2 * sizeof(char *));
}
if (!newenv)
return;
/* Note: we cannot safely free() the original environ. */
- environ = savenv = newenv;
+ environ = savedEnv = newenv;
newenv[0] = NULL;
newenv[1] = NULL;
- setenv(MAKE_LEVEL, cp, 1);
+ setenv(MAKE_LEVEL_ENV, cp, 1);
} else {
for (; *str != '\n' && isspace((unsigned char) *str); str++)
continue;
@@ -905,6 +937,14 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
}
v = VarFind(name, ctxt, 0);
if (v == NULL) {
+ if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
+ /*
+ * This var would normally prevent the same name being added
+ * to VAR_GLOBAL, so delete it from there if needed.
+ * Otherwise -V name may show the wrong value.
+ */
+ Var_Delete(name, VAR_GLOBAL);
+ }
VarAdd(name, val, ctxt);
} else {
Buf_Empty(&v->val);
@@ -939,22 +979,6 @@ Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
}
- /*
- * Another special case.
- * Several make's support this sort of mechanism for tracking
- * recursion - but each uses a different name.
- * We allow the makefiles to update .MAKE.LEVEL and ensure
- * children see a correctly incremented value.
- */
- if (ctxt == VAR_GLOBAL && strcmp(MAKE_LEVEL, name) == 0) {
- char tmp[64];
- int level;
-
- level = atoi(val);
- snprintf(tmp, sizeof(tmp), "%u", level + 1);
- setenv(MAKE_LEVEL, tmp, 1);
- }
-
out:
if (expanded_name != NULL)
@@ -1133,7 +1157,7 @@ Var_Value(const char *name, GNode *ctxt, char **frp)
*-----------------------------------------------------------------------
*/
static Boolean
-VarHead(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarHead(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *dummy)
{
@@ -1181,7 +1205,7 @@ VarHead(GNode *ctx __unused, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static Boolean
-VarTail(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarTail(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *dummy)
{
@@ -1223,7 +1247,7 @@ VarTail(GNode *ctx __unused, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static Boolean
-VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarSuffix(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *dummy)
{
@@ -1264,7 +1288,7 @@ VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static Boolean
-VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarRoot(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *dummy)
{
@@ -1308,7 +1332,7 @@ VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static Boolean
-VarMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *pattern)
{
@@ -1399,7 +1423,7 @@ VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static Boolean
-VarNoMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarNoMatch(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *pattern)
{
@@ -1436,7 +1460,7 @@ VarNoMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
*-----------------------------------------------------------------------
*/
static Boolean
-VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarSubstitute(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
void *patternp)
{
@@ -1632,7 +1656,8 @@ VarREError(int errnum, regex_t *pat, const char *str)
*-----------------------------------------------------------------------
*/
static Boolean
-VarRESubstitute(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
+VarRESubstitute(GNode *ctx MAKE_ATTR_UNUSED,
+ Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
char *word, Boolean addSpace, Buffer *buf,
void *patternp)
{
@@ -1772,7 +1797,8 @@ VarRESubstitute(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
*-----------------------------------------------------------------------
*/
static Boolean
-VarLoopExpand(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
+VarLoopExpand(GNode *ctx MAKE_ATTR_UNUSED,
+ Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
char *word, Boolean addSpace, Buffer *buf,
void *loopp)
{
@@ -1815,7 +1841,7 @@ VarLoopExpand(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
*-----------------------------------------------------------------------
*/
static char *
-VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarSelectWords(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
const char *str, VarSelectWords_t *seldata)
{
Buffer buf; /* Buffer for the new string */
@@ -1890,9 +1916,9 @@ VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate,
* if successful.
*/
static Boolean
-VarRealpath(GNode *ctx __unused, Var_Parse_State *vpstate,
+VarRealpath(GNode *ctx MAKE_ATTR_UNUSED, Var_Parse_State *vpstate,
char *word, Boolean addSpace, Buffer *buf,
- void *patternp __unused)
+ void *patternp MAKE_ATTR_UNUSED)
{
struct stat st;
char rbuf[MAXPATHLEN];
@@ -2115,7 +2141,7 @@ VarUniq(const char *str)
*-----------------------------------------------------------------------
*/
static char *
-VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate __unused,
+VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate MAKE_ATTR_UNUSED,
int errnum, const char **tstr, int delim, int *flags,
int *length, VarPattern *pattern)
{
@@ -2288,9 +2314,7 @@ VarHash(char *str)
size_t len, len2;
unsigned char *ustr = (unsigned char *)str;
uint32_t h, k, c1, c2;
- int done;
- done = 1;
h = 0x971e137bU;
c1 = 0x95543787U;
c2 = 0x2ad7eb25U;
@@ -2320,7 +2344,7 @@ VarHash(char *str)
h = (h << 13) ^ (h >> 19);
h = h * 5 + 0x52dce729U;
h ^= k;
- } while (!done);
+ }
h ^= len2;
h *= 0x85ebca6b;
h ^= h >> 13;
@@ -2336,37 +2360,6 @@ VarHash(char *str)
return Buf_Destroy(&buf, FALSE);
}
-/*-
- *-----------------------------------------------------------------------
- * VarChangeCase --
- * Change the string to all uppercase or all lowercase
- *
- * Input:
- * str String to modify
- * upper TRUE -> uppercase, else lowercase
- *
- * Results:
- * The string with case changed
- *
- * Side Effects:
- * None.
- *
- *-----------------------------------------------------------------------
- */
-static char *
-VarChangeCase(char *str, int upper)
-{
- Buffer buf;
- int (*modProc)(int);
-
- modProc = (upper ? toupper : tolower);
- Buf_Init(&buf, 0);
- for (; *str ; str++) {
- Buf_AddByte(&buf, modProc(*str));
- }
- return Buf_Destroy(&buf, FALSE);
-}
-
static char *
VarStrftime(const char *fmt, int zulu)
{
@@ -2553,7 +2546,8 @@ ApplyModifiers(char *nstr, const char *tstr,
}
apply_mods:
if (DEBUG(VAR)) {
- fprintf(debug_file, "Applying :%c to \"%s\"\n", *tstr, nstr);
+ fprintf(debug_file, "Applying[%s] :%c to \"%s\"\n", v->name,
+ *tstr, nstr);
}
newStr = var_Error;
switch ((modifier = *tstr)) {
@@ -2642,7 +2636,7 @@ ApplyModifiers(char *nstr, const char *tstr,
break;
}
free(UNCONST(pattern.rhs));
- newStr = var_Error;
+ newStr = varNoError;
break;
}
goto default_case; /* "::<unrecognised>" */
@@ -3042,8 +3036,16 @@ ApplyModifiers(char *nstr, const char *tstr,
VarRealpath, NULL);
cp = tstr + 2;
termc = *cp;
- } else if (tstr[1] == 'u' || tstr[1] == 'l') {
- newStr = VarChangeCase(nstr, (tstr[1] == 'u'));
+ } else if (tstr[1] == 'u') {
+ char *dp = bmake_strdup(nstr);
+ for (newStr = dp; *dp; dp++)
+ *dp = toupper((unsigned char)*dp);
+ cp = tstr + 2;
+ termc = *cp;
+ } else if (tstr[1] == 'l') {
+ char *dp = bmake_strdup(nstr);
+ for (newStr = dp; *dp; dp++)
+ *dp = tolower((unsigned char)*dp);
cp = tstr + 2;
termc = *cp;
} else if (tstr[1] == 'W' || tstr[1] == 'w') {
@@ -3153,8 +3155,8 @@ ApplyModifiers(char *nstr, const char *tstr,
free(cp2);
}
if (DEBUG(VAR))
- fprintf(debug_file, "Pattern for [%s] is [%s]\n", nstr,
- pattern);
+ fprintf(debug_file, "Pattern[%s] for [%s] is [%s]\n",
+ v->name, nstr, pattern);
if (*tstr == 'M') {
newStr = VarModify(ctxt, &parsestate, nstr, VarMatch,
pattern);
@@ -3258,7 +3260,7 @@ ApplyModifiers(char *nstr, const char *tstr,
termc = *--cp;
delim = '\0';
- if (Cond_EvalExpression(NULL, v->name, &value, 0)
+ if (Cond_EvalExpression(NULL, v->name, &value, 0, FALSE)
== COND_INVALID) {
Error("Bad conditional expression `%s' in %s?%s:%s",
v->name, v->name, pattern.lhs, pattern.rhs);
@@ -3509,7 +3511,8 @@ ApplyModifiers(char *nstr, const char *tstr,
}
}
if (DEBUG(VAR)) {
- fprintf(debug_file, "Result of :%c is \"%s\"\n", modifier, newStr);
+ fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
+ v->name, modifier, newStr);
}
if (newStr != nstr) {
@@ -3596,14 +3599,13 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
* expanding it in a non-local context. This
* is done to support dynamic sources. The
* result is just the invocation, unaltered */
- Var_Parse_State parsestate; /* Flags passed to helper functions */
+ const char *extramodifiers; /* extra modifiers to apply first */
char name[2];
*freePtr = NULL;
+ extramodifiers = NULL;
dynamic = FALSE;
start = str;
- parsestate.oneBigWord = FALSE;
- parsestate.varSpace = ' '; /* word separator */
startc = str[1];
if (startc != PROPEN && startc != BROPEN) {
@@ -3657,6 +3659,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
}
} else {
Buffer buf; /* Holds the variable name */
+ int depth = 1;
endc = startc == PROPEN ? PRCLOSE : BRCLOSE;
Buf_Init(&buf, 0);
@@ -3664,11 +3667,22 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
/*
* Skip to the end character or a colon, whichever comes first.
*/
- for (tstr = str + 2;
- *tstr != '\0' && *tstr != endc && *tstr != ':';
- tstr++)
+ for (tstr = str + 2; *tstr != '\0'; tstr++)
{
/*
+ * Track depth so we can spot parse errors.
+ */
+ if (*tstr == startc) {
+ depth++;
+ }
+ if (*tstr == endc) {
+ if (--depth == 0)
+ break;
+ }
+ if (depth == 1 && *tstr == ':') {
+ break;
+ }
+ /*
* A variable inside a variable, expand
*/
if (*tstr == '$') {
@@ -3687,7 +3701,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
}
if (*tstr == ':') {
haveModifier = TRUE;
- } else if (*tstr != '\0') {
+ } else if (*tstr == endc) {
haveModifier = FALSE;
} else {
/*
@@ -3719,7 +3733,7 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
*/
if ((v == NULL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
(vlen == 2) && (str[1] == 'F' || str[1] == 'D') &&
- strchr("@%*!<>", str[0]) != NULL) {
+ strchr("@%?*!<>", str[0]) != NULL) {
/*
* Well, it's local -- go look for it.
*/
@@ -3728,29 +3742,12 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
v = VarFind(name, ctxt, 0);
if (v != NULL) {
- /*
- * No need for nested expansion or anything, as we're
- * the only one who sets these things and we sure don't
- * but nested invocations in them...
- */
- nstr = Buf_GetAll(&v->val, NULL);
-
if (str[1] == 'D') {
- nstr = VarModify(ctxt, &parsestate, nstr, VarHead,
- NULL);
- } else {
- nstr = VarModify(ctxt, &parsestate, nstr, VarTail,
- NULL);
+ extramodifiers = "H:";
+ }
+ else { /* F */
+ extramodifiers = "T:";
}
- /*
- * Resulting string is dynamically allocated, so
- * tell caller to free it.
- */
- *freePtr = nstr;
- *lengthPtr = tstr-start+1;
- Buf_Destroy(&buf, TRUE);
- VarFreeEnv(v, TRUE);
- return nstr;
}
}
@@ -3845,16 +3842,29 @@ Var_Parse(const char *str, GNode *ctxt, Boolean errnum, int *lengthPtr,
v->flags &= ~VAR_IN_USE;
- if ((nstr != NULL) && haveModifier) {
+ if ((nstr != NULL) && (haveModifier || extramodifiers != NULL)) {
+ void *extraFree;
int used;
- /*
- * Skip initial colon.
- */
- tstr++;
- nstr = ApplyModifiers(nstr, tstr, startc, endc,
- v, ctxt, errnum, &used, freePtr);
- tstr += used;
+ extraFree = NULL;
+ if (extramodifiers != NULL) {
+ nstr = ApplyModifiers(nstr, extramodifiers, '(', ')',
+ v, ctxt, errnum, &used, &extraFree);
+ }
+
+ if (haveModifier) {
+ /* Skip initial colon. */
+ tstr++;
+
+ nstr = ApplyModifiers(nstr, tstr, startc, endc,
+ v, ctxt, errnum, &used, freePtr);
+ tstr += used;
+ if (extraFree) {
+ free(extraFree);
+ }
+ } else {
+ *freePtr = extraFree;
+ }
}
if (*tstr) {
*lengthPtr = tstr - start + 1;
@@ -4037,7 +4047,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
*/
if (oldVars) {
str += length;
- } else if (undefErr) {
+ } else if (undefErr || val == var_Error) {
/*
* If variable is undefined, complain and skip the
* variable. The complaint will stop us from doing anything
@@ -4075,7 +4085,7 @@ Var_Subst(const char *var, const char *str, GNode *ctxt, Boolean undefErr)
}
}
- return Buf_Destroy(&buf, FALSE);
+ return Buf_DestroyCompact(&buf);
}
/*-
@@ -4142,6 +4152,7 @@ Var_GetHead(char *file)
void
Var_Init(void)
{
+ VAR_INTERNAL = Targ_NewGN("Internal");
VAR_GLOBAL = Targ_NewGN("Global");
VAR_CMD = Targ_NewGN("Command");