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) {

Reply via email to