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: split parameters for evaluating variable ...



details:   https://anonhg.NetBSD.org/src/rev/a70ce16ddbec
branches:  trunk
changeset: 1018744:a70ce16ddbec
user:      rillig <rillig%NetBSD.org@localhost>
date:      Mon Feb 15 17:44:09 2021 +0000

description:
make: split parameters for evaluating variable expressions

The details of how variable expressions are evaluated is controlled by
several parameters: startc and endc differ for $(VAR) and ${VAR}, the
value of the expression can be interpreted as a single big word, and
when joining several words (such as with ':M' or ':S'), there may be a
custom word separator (defined with ':ts*').

The scope of half of these parameters is the whole variable expression,
the other half of the parameters are reset after each chain of indirect
modifiers.  To make this distinction obvious in the code, extract Expr
from ApplyModifiersState.  Previously, these details were hidden in how
parameters are passed and restored among ApplyModifiersIndirect and
ApplyModifiers.

The changes in the individual ApplyModifier functions are numerous but
straight-forward.  They mostly replace 'st' with 'expr'.

The changes in ApplyModifiers and ApplyModifiersIndirect are more
subtle.  The value of the expression is no longer passed around but is
stored in a fixed location, in Expr, which makes it easier to reason
about memory management.

The code in ApplyModifiers after 'cleanup' looks quite different but
preserves the existing behavior.  Expr_SetValueRefer is nothing else
than the combination of FStr_Done followed by FStr_InitRefer.  Storing
exprStatus back at the end was responsible for passing the definedness
of the expression after applying the indirect modifiers back to the
outer ApplyModifiersState.  The same effect is now achieved by having
Expr.status with a wider scope.

No functional change.

diffstat:

 usr.bin/make/var.c |  368 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 202 insertions(+), 166 deletions(-)

diffs (truncated from 1027 to 300 lines):

diff -r 4e4d5b5b7af4 -r a70ce16ddbec usr.bin/make/var.c
--- a/usr.bin/make/var.c        Mon Feb 15 16:32:07 2021 +0000
+++ b/usr.bin/make/var.c        Mon Feb 15 17:44:09 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: var.c,v 1.822 2021/02/15 06:46:01 rillig Exp $ */
+/*     $NetBSD: var.c,v 1.823 2021/02/15 17:44:09 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -139,7 +139,7 @@
 #include "metachar.h"
 
 /*     "@(#)var.c      8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.822 2021/02/15 06:46:01 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.823 2021/02/15 17:44:09 rillig Exp $");
 
 typedef enum VarFlags {
        VAR_NONE        = 0,
@@ -2020,16 +2020,32 @@
        "VES_DEF"
 };
 
+/* A variable expression such as $@ or ${VAR:Mpattern:Q}. */
+typedef struct Expr {
+       Var *var;
+       FStr value;
+       VarEvalFlags const eflags;
+       GNode *const scope;
+       ExprStatus status;
+} Expr;
+
+/*
+ * Data that is used when applying a chain of modifiers to an expression.
+ * For indirect modifiers, the effects of this data stops after the indirect
+ * modifiers have been applies.
+ *
+ * It may or may not be intended that 'status' has scope Expr while 'sep' and
+ * 'oneBigWord' have smaller scope, terminating at the end of a chain of
+ * indirect modifiers.
+ *
+ * See varmod-indirect.mk.
+ */
 typedef struct ApplyModifiersState {
+       Expr *expr;
        /* '\0' or '{' or '(' */
        const char startc;
        /* '\0' or '}' or ')' */
        const char endc;
-       Var *const var;
-       GNode *const scope;
-       const VarEvalFlags eflags;
-       /* The value of the expression, never NULL. */
-       FStr value;
        /* Word separator in expansions (see the :ts modifier). */
        char sep;
        /*
@@ -2038,16 +2054,13 @@
         * big word, possibly containing spaces.
         */
        Boolean oneBigWord;
-       ExprStatus exprStatus;
 } ApplyModifiersState;
 
-typedef ApplyModifiersState Expr;
-
 static void
 Expr_Define(Expr *expr)
 {
-       if (expr->exprStatus == VES_UNDEF)
-               expr->exprStatus = VES_DEF;
+       if (expr->status == VES_UNDEF)
+               expr->status = VES_DEF;
 }
 
 static void
@@ -2152,8 +2165,8 @@
                        VarEvalFlags nested_eflags =
                            eflags & ~(unsigned)VARE_KEEP_DOLLAR;
 
-                       (void)Var_Parse(&nested_p, st->scope, nested_eflags,
-                           &nested_val);
+                       (void)Var_Parse(&nested_p, st->expr->scope,
+                           nested_eflags, &nested_val);
                        /* TODO: handle errors */
                        Buf_AddStr(&buf, nested_val.str);
                        FStr_Done(&nested_val);
@@ -2203,7 +2216,7 @@
        if (*p != delim) {
                *pp = p;
                Error("Unfinished modifier for %s ('%c' missing)",
-                   st->var->name.str, delim);
+                   st->expr->var->name.str, delim);
                *out_part = NULL;
                return VPR_ERR;
        }
@@ -2332,22 +2345,24 @@
            ModifyWordProc modifyWord, void *modifyWord_args,
            Boolean oneBigWord)
 {
+       Expr *expr = st->expr;
+       const char *val = expr->value.str;
        SepBuf result;
        Words words;
        size_t i;
 
        if (oneBigWord) {
                SepBuf_Init(&result, st->sep);
-               modifyWord(st->value.str, &result, modifyWord_args);
+               modifyWord(val, &result, modifyWord_args);
                goto done;
        }
 
        SepBuf_Init(&result, st->sep);
 
-       words = Str_Words(st->value.str, FALSE);
+       words = Str_Words(val, FALSE);
 
        DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n",
-           st->value.str, (unsigned)words.len);
+           val, (unsigned)words.len);
 
        for (i = 0; i < words.len; i++) {
                modifyWord(words.words[i], &result, modifyWord_args);
@@ -2358,18 +2373,19 @@
        Words_Free(words);
 
 done:
-       Expr_SetValueOwn(st, SepBuf_DoneData(&result));
+       Expr_SetValueOwn(expr, SepBuf_DoneData(&result));
 }
 
 /* :@var@...${var}...@ */
 static ApplyModifierResult
 ApplyModifier_Loop(const char **pp, ApplyModifiersState *st)
 {
+       Expr *expr = st->expr;
        struct ModifyWord_LoopArgs args;
        char prev_sep;
        VarParseResult res;
 
-       args.scope = st->scope;
+       args.scope = expr->scope;
 
        (*pp)++;                /* Skip the first '@' */
        res = ParseModifierPart(pp, '@', VARE_NONE, st, &args.tvar);
@@ -2379,7 +2395,7 @@
                Parse_Error(PARSE_FATAL,
                    "In the :@ modifier of \"%s\", the variable name \"%s\" "
                    "must not contain a dollar.",
-                   st->var->name.str, args.tvar);
+                   expr->var->name.str, args.tvar);
                return AMR_CLEANUP;
        }
 
@@ -2387,7 +2403,7 @@
        if (res != VPR_OK)
                return AMR_CLEANUP;
 
-       args.eflags = st->eflags & ~(unsigned)VARE_KEEP_DOLLAR;
+       args.eflags = expr->eflags & ~(unsigned)VARE_KEEP_DOLLAR;
        prev_sep = st->sep;
        st->sep = ' ';          /* XXX: should be st->sep for consistency */
        ModifyWords(st, ModifyWord_Loop, &args, st->oneBigWord);
@@ -2397,7 +2413,7 @@
         * XXX: The variable name should not be expanded here, see
         * ModifyWord_Loop.
         */
-       Var_DeleteExpand(st->scope, args.tvar);
+       Var_DeleteExpand(expr->scope, args.tvar);
        free(args.tvar);
        free(args.str);
        return AMR_OK;
@@ -2407,13 +2423,14 @@
 static ApplyModifierResult
 ApplyModifier_Defined(const char **pp, ApplyModifiersState *st)
 {
+       Expr *expr = st->expr;
        Buffer buf;
        const char *p;
 
        VarEvalFlags eflags = VARE_NONE;
-       if (st->eflags & VARE_WANTRES)
-               if ((**pp == 'D') == (st->exprStatus == VES_NONE))
-                       eflags = st->eflags;
+       if (expr->eflags & VARE_WANTRES)
+               if ((**pp == 'D') == (expr->status == VES_NONE))
+                       eflags = expr->eflags;
 
        Buf_Init(&buf);
        p = *pp + 1;
@@ -2438,7 +2455,7 @@
                if (*p == '$') {
                        FStr nested_val;
 
-                       (void)Var_Parse(&p, st->scope, eflags, &nested_val);
+                       (void)Var_Parse(&p, expr->scope, eflags, &nested_val);
                        /* TODO: handle errors */
                        Buf_AddStr(&buf, nested_val.str);
                        FStr_Done(&nested_val);
@@ -2451,10 +2468,10 @@
        }
        *pp = p;
 
-       Expr_Define(st);
+       Expr_Define(expr);
 
        if (eflags & VARE_WANTRES)
-               Expr_SetValueOwn(st, Buf_DoneData(&buf));
+               Expr_SetValueOwn(expr, Buf_DoneData(&buf));
        else
                Buf_Done(&buf);
 
@@ -2465,8 +2482,9 @@
 static ApplyModifierResult
 ApplyModifier_Literal(const char **pp, ApplyModifiersState *st)
 {
-       Expr_Define(st);
-       Expr_SetValueOwn(st, bmake_strdup(st->var->name.str));
+       Expr *expr = st->expr;
+       Expr_Define(expr);
+       Expr_SetValueOwn(expr, bmake_strdup(expr->var->name.str));
        (*pp)++;
        return AMR_OK;
 }
@@ -2512,7 +2530,8 @@
                utc = 0;
                *pp = mod + 6;
        }
-       Expr_SetValueOwn(st, VarStrftime(st->value.str, TRUE, utc));
+       Expr_SetValueOwn(st->expr,
+           VarStrftime(st->expr->value.str, TRUE, utc));
        return AMR_OK;
 }
 
@@ -2538,7 +2557,8 @@
                utc = 0;
                *pp = mod + 9;
        }
-       Expr_SetValueOwn(st, VarStrftime(st->value.str, FALSE, utc));
+       Expr_SetValueOwn(st->expr,
+           VarStrftime(st->expr->value.str, FALSE, utc));
        return AMR_OK;
 }
 
@@ -2549,7 +2569,7 @@
        if (!ModMatch(*pp, "hash", st->endc))
                return AMR_UNKNOWN;
 
-       Expr_SetValueOwn(st, VarHash(st->value.str));
+       Expr_SetValueOwn(st->expr, VarHash(st->expr->value.str));
        *pp += 4;
        return AMR_OK;
 }
@@ -2558,23 +2578,24 @@
 static ApplyModifierResult
 ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
 {
+       Expr *expr = st->expr;
        GNode *gn;
        char *path;
 
-       Expr_Define(st);
-
-       gn = Targ_FindNode(st->var->name.str);
+       Expr_Define(expr);
+
+       gn = Targ_FindNode(expr->var->name.str);
        if (gn == NULL || gn->type & OP_NOPATH) {
                path = NULL;
        } else if (gn->path != NULL) {
                path = bmake_strdup(gn->path);
        } else {
                SearchPath *searchPath = Suff_FindPath(gn);
-               path = Dir_FindFile(st->var->name.str, searchPath);
+               path = Dir_FindFile(expr->var->name.str, searchPath);
        }
        if (path == NULL)
-               path = bmake_strdup(st->var->name.str);
-       Expr_SetValueOwn(st, path);
+               path = bmake_strdup(expr->var->name.str);
+       Expr_SetValueOwn(expr, path);
 
        (*pp)++;
        return AMR_OK;
@@ -2584,25 +2605,26 @@
 static ApplyModifierResult
 ApplyModifier_ShellCommand(const char **pp, ApplyModifiersState *st)
 {
+       Expr *expr = st->expr;
        char *cmd;
        const char *errfmt;
        VarParseResult res;
 
        (*pp)++;
-       res = ParseModifierPart(pp, '!', st->eflags, st, &cmd);
+       res = ParseModifierPart(pp, '!', expr->eflags, st, &cmd);
        if (res != VPR_OK)
                return AMR_CLEANUP;
 
        errfmt = NULL;



Home | Main Index | Thread Index | Old Index