Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make make(1): rework memory allocation for the name ...
details: https://anonhg.NetBSD.org/src/rev/464e7a6015b5
branches: trunk
changeset: 940213:464e7a6015b5
user: rillig <rillig%NetBSD.org@localhost>
date: Tue Oct 06 08:13:27 2020 +0000
description:
make(1): rework memory allocation for the name of variables
There's more to know about variable names than fits in a one-liner.
While here, enforce that the name is not modified by splitting it into
the established (var + var_freeIt) pattern.
Since the name is not modified and not freed in the middle of evaluating
an expression, there is no need to make a backup copy of it. That code
had been necessary more than 12 years ago, but not anymore since the
code got a lot cleaner since then.
diffstat:
usr.bin/make/var.c | 70 ++++++++++++++++++++++++++++++-----------------------
1 files changed, 40 insertions(+), 30 deletions(-)
diffs (171 lines):
diff -r 1c27234d9047 -r 464e7a6015b5 usr.bin/make/var.c
--- a/usr.bin/make/var.c Tue Oct 06 07:52:47 2020 +0000
+++ b/usr.bin/make/var.c Tue Oct 06 08:13:27 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.569 2020/10/06 07:52:47 rillig Exp $ */
+/* $NetBSD: var.c,v 1.570 2020/10/06 08:13:27 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -121,7 +121,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.569 2020/10/06 07:52:47 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.570 2020/10/06 08:13:27 rillig Exp $");
#define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1)
#define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2)
@@ -213,11 +213,31 @@
VAR_IN_USE, VAR_FROM_ENV,
VAR_EXPORTED, VAR_REEXPORT, VAR_FROM_CMD, VAR_READONLY);
+/* Variables are defined using one of the VAR=value assignments. Their
+ * value can be queried by expressions such as $V, ${VAR}, or with modifiers
+ * such as ${VAR:S,from,to,g:Q}.
+ *
+ * There are 3 kinds of variables: context variables, environment variables,
+ * undefined variables.
+ *
+ * Context variables are stored in a GNode.context. The only way to undefine
+ * a context variable is using the .undef directive. In particular, it must
+ * not be possible to undefine a variable during the evaluation of an
+ * expression, or Var.name might point nowhere.
+ *
+ * Environment variables are temporary. They are returned by VarFind, and
+ * after using them, they must be freed using VarFreeEnv.
+ *
+ * Undefined variables occur during evaluation of variable expressions such
+ * as ${UNDEF:Ufallback} in Var_Parse and ApplyModifiers.
+ */
typedef struct Var {
- char *name; /* the variable's name; it is allocated for
- * environment variables and aliased to the
- * Hash_Entry name for all other variables,
- * and thus must not be modified */
+ /* The name of the variable, once set, doesn't change anymore.
+ * For context variables, it aliases the corresponding Hash_Entry name.
+ * For environment and undefined variables, it is allocated. */
+ const char *name;
+ void *name_freeIt;
+
Buffer val; /* its value */
VarFlags flags; /* miscellaneous status flags */
} Var;
@@ -254,11 +274,12 @@
} VarPatternFlags;
static Var *
-VarNew(char *name, const char *value, VarFlags flags)
+VarNew(const char *name, void *name_freeIt, const char *value, VarFlags flags)
{
size_t value_len = strlen(value);
Var *var = bmake_malloc(sizeof *var);
var->name = name;
+ var->name_freeIt = name_freeIt;
Buf_Init(&var->val, value_len + 1);
Buf_AddBytes(&var->val, value, value_len);
var->flags = flags;
@@ -360,8 +381,10 @@
if (var == NULL && (flags & FIND_ENV)) {
char *env;
- if ((env = getenv(name)) != NULL)
- return VarNew(bmake_strdup(name), env, VAR_FROM_ENV);
+ if ((env = getenv(name)) != NULL) {
+ char *varname = bmake_strdup(name);
+ return VarNew(varname, varname, env, VAR_FROM_ENV);
+ }
if (checkEnvFirst && (flags & FIND_GLOBAL) && ctxt != VAR_GLOBAL) {
var = Hash_FindValue(&VAR_GLOBAL->context, name);
@@ -394,7 +417,7 @@
{
if (!(v->flags & VAR_FROM_ENV))
return FALSE;
- free(v->name);
+ free(v->name_freeIt);
Buf_Destroy(&v->val, destroy);
free(v);
return TRUE;
@@ -406,7 +429,8 @@
VarAdd(const char *name, const char *val, GNode *ctxt, VarSet_Flags flags)
{
Hash_Entry *he = Hash_CreateEntry(&ctxt->context, name, NULL);
- Var *v = VarNew(he->name, val, flags & VAR_SET_READONLY ? VAR_READONLY : 0);
+ Var *v = VarNew(he->name, NULL, val,
+ flags & VAR_SET_READONLY ? VAR_READONLY : 0);
Hash_SetValue(he, v);
if (!(ctxt->flags & INTERNAL)) {
VAR_DEBUG3("%s:%s = %s\n", ctxt->name, name, val);
@@ -436,8 +460,7 @@
unsetenv(v->name);
if (strcmp(v->name, MAKE_EXPORTED) == 0)
var_exportedVars = VAR_EXPORTED_NONE;
- if (v->name != he->name)
- free(v->name);
+ assert(v->name_freeIt == NULL);
Hash_DeleteEntry(&ctxt->context, he);
Buf_Destroy(&v->val, TRUE);
free(v);
@@ -2807,7 +2830,6 @@
ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
{
GNode *v_ctxt;
- char *sv_name;
char delim;
char *val;
VarParseResult res;
@@ -2820,20 +2842,13 @@
return AMR_UNKNOWN; /* "::<unrecognised>" */
- if (st->v->name[0] == 0) {
+ if (st->v->name[0] == '\0') {
*pp = mod + 1;
return AMR_BAD;
}
v_ctxt = st->ctxt; /* context where v belongs */
- sv_name = NULL;
- if (st->exprFlags & VEF_UNDEF) {
- /*
- * We need to bmake_strdup() it in case ParseModifierPart() recurses.
- */
- sv_name = st->v->name;
- st->v->name = bmake_strdup(st->v->name);
- } else if (st->ctxt != VAR_GLOBAL) {
+ if (!(st->exprFlags & VEF_UNDEF) && st->ctxt != VAR_GLOBAL) {
Var *gv = VarFind(st->v->name, st->ctxt, 0);
if (gv == NULL)
v_ctxt = VAR_GLOBAL;
@@ -2854,11 +2869,6 @@
delim = st->startc == '(' ? ')' : '}';
res = ParseModifierPart(pp, delim, st->eflags, st, &val, NULL, NULL, NULL);
- if (st->exprFlags & VEF_UNDEF) {
- /* restore original name */
- free(st->v->name);
- st->v->name = sv_name;
- }
if (res != VPR_OK)
return AMR_CLEANUP;
@@ -3630,7 +3640,7 @@
* At the end, after applying all modifiers, if the expression
* is still undefined, Var_Parse will return an empty string
* instead of the actually computed value. */
- v = VarNew(varname, "", 0);
+ v = VarNew(varname, varname, "", 0);
exprFlags = VEF_UNDEF;
} else
free(varname);
@@ -3716,7 +3726,7 @@
}
if (nstr != Buf_GetAll(&v->val, NULL))
Buf_Destroy(&v->val, TRUE);
- free(v->name);
+ free(v->name_freeIt);
free(v);
}
*out_val = nstr;
Home |
Main Index |
Thread Index |
Old Index