Module Name: src
Committed By: rillig
Date: Mon Dec 13 02:17:59 UTC 2021
Modified Files:
src/usr.bin/make: var.c
Log Message:
make: distinguish between short-lived and environment variables
No functional change.
To generate a diff of this commit:
cvs rdiff -u -r1.977 -r1.978 src/usr.bin/make/var.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.977 src/usr.bin/make/var.c:1.978
--- src/usr.bin/make/var.c:1.977 Mon Dec 13 02:07:58 2021
+++ src/usr.bin/make/var.c Mon Dec 13 02:17:59 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.977 2021/12/13 02:07:58 rillig Exp $ */
+/* $NetBSD: var.c,v 1.978 2021/12/13 02:17:59 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -140,7 +140,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.977 2021/12/13 02:07:58 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.978 2021/12/13 02:17:59 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -176,11 +176,17 @@ typedef struct Var {
bool fromCmd: 1;
/*
- * The variable comes from the environment.
+ * The variable is short-lived.
* These variables are not registered in any GNode, therefore they
- * must be freed as soon as they are not used anymore.
+ * must be freed after use.
+ */
+ bool shortLived: 1;
+
+ /*
+ * The variable comes from the environment.
+ * Appending to its value moves the variable to the global scope.
*/
- bool fromEnv: 1;
+ bool fromEnvironment: 1;
/*
* The variable value cannot be changed anymore, and the variable
@@ -329,7 +335,8 @@ static const char VarEvalMode_Name[][32]
static Var *
-VarNew(FStr name, const char *value, bool fromEnv, bool readOnly)
+VarNew(FStr name, const char *value,
+ bool shortLived, bool fromEnvironment, bool readOnly)
{
size_t value_len = strlen(value);
Var *var = bmake_malloc(sizeof *var);
@@ -337,7 +344,8 @@ VarNew(FStr name, const char *value, boo
Buf_InitSize(&var->val, value_len + 1);
Buf_AddBytes(&var->val, value, value_len);
var->fromCmd = false;
- var->fromEnv = fromEnv;
+ var->shortLived = shortLived;
+ var->fromEnvironment = fromEnvironment;
var->readOnly = readOnly;
var->inUse = false;
var->exported = false;
@@ -431,7 +439,7 @@ VarFindSubstring(Substring name, GNode *
envName = Substring_Str(name);
envValue = getenv(envName.str);
if (envValue != NULL)
- return VarNew(envName, envValue, true, false);
+ return VarNew(envName, envValue, true, true, false);
FStr_Done(&envName);
if (opts.checkEnvFirst && scope != SCOPE_GLOBAL) {
@@ -459,7 +467,7 @@ VarFind(const char *name, GNode *scope,
static void
VarFreeShortLived(Var *v)
{
- if (!v->fromEnv) /* TODO: replace with v->shortLived */
+ if (!v->shortLived)
return;
FStr_Done(&v->name);
@@ -473,7 +481,7 @@ VarAdd(const char *name, const char *val
{
HashEntry *he = HashTable_CreateEntry(&scope->vars, name, NULL);
Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), value,
- false, (flags & VAR_SET_READONLY) != 0);
+ false, false, (flags & VAR_SET_READONLY) != 0);
HashEntry_Set(he, v);
DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, value);
return v;
@@ -1121,17 +1129,18 @@ Var_Append(GNode *scope, const char *nam
DEBUG3(VAR, "%s: %s = %s\n", scope->name, name, v->val.data);
- if (v->fromEnv) {
+ if (v->fromEnvironment) {
/*
- * If the original variable came from the environment,
- * we have to install it in the global scope (we
- * could place it in the environment, but then we
- * should provide a way to export other variables...)
+ * The variable originally came from the environment.
+ * Install it in the global scope (we could place it
+ * in the environment, but then we should provide a
+ * way to export other variables...)
*/
- v->fromEnv = false;
+ v->fromEnvironment = false;
+ v->shortLived = false;
/*
* This is the only place where a variable is
- * created whose v->name is not the same as
+ * created in a scope, where v->name does not alias
* scope->vars->key.
*/
HashTable_Set(&scope->vars, name, v);
@@ -1250,13 +1259,13 @@ Var_Value(GNode *scope, const char *name
if (v == NULL)
return FStr_InitRefer(NULL);
- if (!v->fromEnv)
+ if (!v->shortLived)
return FStr_InitRefer(v->val.data);
- /* Since environment variables are short-lived, free it now. */
- FStr_Done(&v->name);
- value = Buf_DoneData(&v->val);
- free(v);
+ value = v->val.data;
+ v->val.data = NULL;
+ VarFreeShortLived(v);
+
return FStr_InitOwn(value);
}
@@ -4408,7 +4417,8 @@ ParseVarnameLong(
if (v == NULL && Substring_Equals(name, ".SUFFIXES")) {
char *suffixes = Suff_NamesStr();
v = VarNew(FStr_InitRefer(".SUFFIXES"), suffixes,
- false, true);
+ /* TODO: change to true to fix memory leak */
+ false, false, true);
free(suffixes);
} else if (v == NULL)
v = FindLocalLegacyVar(name, scope, out_true_extraModifiers);
@@ -4443,7 +4453,12 @@ ParseVarnameLong(
* is still undefined, Var_Parse will return an empty string
* instead of the actually computed value.
*/
- v = VarNew(LazyBuf_DoneGet(&varname), "", false, false);
+ /*
+ * XXX: shortLived == true sounds more sensible, this will
+ * allow to merge duplicate code at the end of Var_Parse.
+ */
+ v = VarNew(LazyBuf_DoneGet(&varname), "",
+ false, false, false);
*out_true_exprDefined = DEF_UNDEF;
} else
LazyBuf_Done(&varname);
@@ -4655,7 +4670,7 @@ Var_Parse(const char **pp, GNode *scope,
*pp = p;
- if (v->fromEnv) {
+ if (v->shortLived) {
FreeShortLived(v, &expr);
} else if (expr.defined != DEF_REGULAR) {