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): replace st->next with a simple string ...



details:   https://anonhg.NetBSD.org/src/rev/34ca7e025bd7
branches:  trunk
changeset: 1012604:34ca7e025bd7
user:      rillig <rillig%NetBSD.org@localhost>
date:      Mon Aug 03 15:08:00 2020 +0000

description:
make(1): replace st->next with a simple string iterator

This is the same style that OpenBSD's make has been using for 20 years
now.  Having one less field in ApplyModifiersState reduces complexity in
that place.

The individual modifiers currently don't handle parse errors
consistently.  Some update pp while others leave it as-is.  This
behavior may be aligned in a follow-up commit.

diffstat:

 usr.bin/make/var.c |  330 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 183 insertions(+), 147 deletions(-)

diffs (truncated from 945 to 300 lines):

diff -r 014776d73c5b -r 34ca7e025bd7 usr.bin/make/var.c
--- a/usr.bin/make/var.c        Mon Aug 03 14:42:50 2020 +0000
+++ b/usr.bin/make/var.c        Mon Aug 03 15:08:00 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: var.c,v 1.408 2020/08/03 14:42:50 rillig Exp $ */
+/*     $NetBSD: var.c,v 1.409 2020/08/03 15:08:00 rillig Exp $ */
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.408 2020/08/03 14:42:50 rillig Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.409 2020/08/03 15:08:00 rillig 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.408 2020/08/03 14:42:50 rillig Exp $");
+__RCSID("$NetBSD: var.c,v 1.409 2020/08/03 15:08:00 rillig Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -1605,7 +1605,9 @@
  * well as the backslash or the dollar, can be escaped with a backslash.
  *
  * Return the parsed (and possibly expanded) string, or NULL if no delimiter
- * was found.
+ * was found.  On successful return, the parsing position pp points right
+ * after the delimiter.  The delimiter is not included in the returned
+ * value though.
  */
 static char *
 ParseModifierPart(
@@ -1840,13 +1842,36 @@
     return bmake_strdup(buf);
 }
 
-/* The ApplyModifier functions all work in the same way.
- * They parse the modifier (often until the next colon) and store the
- * updated position for the parser into st->next
- * (except when returning AMR_UNKNOWN).
- * They take the st->val and generate st->newVal from it.
- * On failure, many of them update st->missing_delim.
+/* The ApplyModifier functions all work in the same way.  They get the
+ * current parsing position (pp) and parse the modifier from there.  The
+ * modifier typically lasts until the next ':', or a closing '}', ')'
+ * (taken from st->endc), or the end of the string (parse error).
+ *
+ * After parsing, no matter whether successful or not, they set the parsing
+ * position to the character after the modifier, or in case of parse errors,
+ * just increment the parsing position.  (That's how it is right now, it
+ * shouldn't hurt to keep the parsing position as-is in case of parse errors.)
+ *
+ * On success, an ApplyModifier function:
+ *     * sets the parsing position *pp to the first character following the
+ *       current modifier
+ *     * processes the current variable value from st->val to produce the
+ *       modified variable value and stores it in st->newVal
+ *     * returns AMR_OK
+ *
+ * On parse errors, an ApplyModifier function:
+ *     * either issues a custom error message and then returns AMR_CLEANUP
+ *     * or returns AMR_BAD to issue the standard "Bad modifier" error message
+ *     In both of these cases, it updates the parsing position.
+ *     Modifiers that use ParseModifierPart typically set st->missing_delim
+ *     and then return AMR_CLEANUP to issue the standard error message.
+ *
+ * If the expected modifier was not found, several modifiers return AMR_UNKNOWN
+ * to fall back to the SysV modifier ${VAR:from=to}.  This is especially
+ * useful for newly added long-name modifiers, to avoid breaking any existing
+ * code.  In such a case the parsing position must not be changed.
  */
+
 typedef struct {
     const int startc;          /* '\0' or '{' or '(' */
     const int endc;
@@ -1858,8 +1883,6 @@
                                 * modifier is applied */
     char *newVal;              /* The new value after applying the modifier
                                 * to the expression */
-    const char *next;          /* The position where parsing continues
-                                * after the current modifier. */
     char missing_delim;                /* For error reporting */
 
     Byte sep;                  /* Word separator in expansions */
@@ -1868,7 +1891,6 @@
                                 * embedded spaces (as opposed to the
                                 * usual behaviour of treating it as
                                 * several space-separated words). */
-
 } ApplyModifiersState;
 
 typedef enum {
@@ -1899,20 +1921,21 @@
 
 /* :@var@...${var}...@ */
 static ApplyModifierResult
-ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) {
+ApplyModifier_Loop(const char **pp, ApplyModifiersState *st) {
     ModifyWord_LoopArgs args;
 
     args.ctx = st->ctxt;
-    st->next = mod + 1;
+
+    (*pp)++;                   /* Skip the first '@' */
     char delim = '@';
-    args.tvar = ParseModifierPart(&st->next, delim, st->eflags & ~VARE_WANTRES,
+    args.tvar = ParseModifierPart(pp, delim, st->eflags & ~VARE_WANTRES,
                                  st->ctxt, NULL, NULL, NULL);
     if (args.tvar == NULL) {
        st->missing_delim = delim;
        return AMR_CLEANUP;
     }
 
-    args.str = ParseModifierPart(&st->next, delim, st->eflags & ~VARE_WANTRES,
+    args.str = ParseModifierPart(pp, delim, st->eflags & ~VARE_WANTRES,
                                 st->ctxt, NULL, NULL, NULL);
     if (args.str == NULL) {
        st->missing_delim = delim;
@@ -1921,7 +1944,7 @@
 
     args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES);
     int prev_sep = st->sep;
-    st->sep = ' ';             /* XXX: this is inconsistent */
+    st->sep = ' ';             /* XXX: should be st->sep for consistency */
     st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val,
                             ModifyWord_Loop, &args);
     st->sep = prev_sep;
@@ -1933,12 +1956,12 @@
 
 /* :Ddefined or :Uundefined */
 static ApplyModifierResult
-ApplyModifier_Defined(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Defined(const char **pp, ApplyModifiersState *st)
 {
     VarEvalFlags neflags;
     if (st->eflags & VARE_WANTRES) {
        Boolean wantres;
-       if (*mod == 'U')
+       if (**pp == 'U')
            wantres = (st->v->flags & VAR_JUNK) != 0;
        else
            wantres = (st->v->flags & VAR_JUNK) == 0;
@@ -1957,7 +1980,7 @@
      */
     Buffer buf;                        /* Buffer for patterns */
     Buf_InitZ(&buf, 0);
-    const char *p = mod + 1;
+    const char *p = *pp + 1;
     while (*p != st->endc && *p != ':' && *p != '\0') {
        if (*p == '\\' &&
            (p[1] == ':' || p[1] == '$' || p[1] == st->endc || p[1] == '\\')) {
@@ -1981,8 +2004,7 @@
            p++;
        }
     }
-
-    st->next = p;
+    *pp = p;
 
     if (st->v->flags & VAR_JUNK)
        st->v->flags |= VAR_KEEP;
@@ -1997,8 +2019,9 @@
 
 /* :gmtime */
 static ApplyModifierResult
-ApplyModifier_Gmtime(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Gmtime(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     if (!ModMatchEq(mod, "gmtime", st->endc))
        return AMR_UNKNOWN;
 
@@ -2006,10 +2029,10 @@
     if (mod[6] == '=') {
        char *ep;
        utc = strtoul(mod + 7, &ep, 10);
-       st->next = ep;
+       *pp = ep;
     } else {
        utc = 0;
-       st->next = mod + 6;
+       *pp = mod + 6;
     }
     st->newVal = VarStrftime(st->val, 1, utc);
     return AMR_OK;
@@ -2017,8 +2040,9 @@
 
 /* :localtime */
 static Boolean
-ApplyModifier_Localtime(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Localtime(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     if (!ModMatchEq(mod, "localtime", st->endc))
        return AMR_UNKNOWN;
 
@@ -2026,10 +2050,10 @@
     if (mod[9] == '=') {
        char *ep;
        utc = strtoul(mod + 10, &ep, 10);
-       st->next = ep;
+       *pp = ep;
     } else {
        utc = 0;
-       st->next = mod + 9;
+       *pp = mod + 9;
     }
     st->newVal = VarStrftime(st->val, 0, utc);
     return AMR_OK;
@@ -2037,22 +2061,23 @@
 
 /* :hash */
 static ApplyModifierResult
-ApplyModifier_Hash(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Hash(const char **pp, ApplyModifiersState *st)
 {
-    if (!ModMatch(mod, "hash", st->endc))
+    if (!ModMatch(*pp, "hash", st->endc))
        return AMR_UNKNOWN;
 
     st->newVal = VarHash(st->val);
-    st->next = mod + 4;
+    *pp += 4;
     return AMR_OK;
 }
 
 /* :P */
 static ApplyModifierResult
-ApplyModifier_Path(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Path(const char **pp, ApplyModifiersState *st)
 {
     if (st->v->flags & VAR_JUNK)
        st->v->flags |= VAR_KEEP;
+
     GNode *gn = Targ_FindNode(st->v->name, TARG_NOCREATE);
     if (gn == NULL || gn->type & OP_NOPATH) {
        st->newVal = NULL;
@@ -2063,17 +2088,18 @@
     }
     if (st->newVal == NULL)
        st->newVal = bmake_strdup(st->v->name);
-    st->next = mod + 1;
+
+    (*pp)++;
     return AMR_OK;
 }
 
 /* :!cmd! */
 static ApplyModifierResult
-ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Exclam(const char **pp, ApplyModifiersState *st)
 {
-    st->next = mod + 1;
+    (*pp)++;
     char delim = '!';
-    char *cmd = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *cmd = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
                                  NULL, NULL, NULL);
     if (cmd == NULL) {
        st->missing_delim = delim;
@@ -2098,8 +2124,9 @@
 /* The :range modifier generates an integer sequence as long as the words.
  * The :range=7 modifier generates an integer sequence from 1 to 7. */
 static ApplyModifierResult
-ApplyModifier_Range(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Range(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     if (!ModMatchEq(mod, "range", st->endc))
        return AMR_UNKNOWN;
 
@@ -2107,10 +2134,10 @@
     if (mod[5] == '=') {
        char *ep;
        n = strtoul(mod + 6, &ep, 10);
-       st->next = ep;
+       *pp = ep;
     } else {
        n = 0;
-       st->next = mod + 5;
+       *pp = mod + 5;
     }
 
     if (n == 0) {
@@ -2136,8 +2163,9 @@
 
 /* :Mpattern or :Npattern */
 static ApplyModifierResult
-ApplyModifier_Match(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Match(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     Boolean copy = FALSE;      /* pattern should be, or has been, copied */
     Boolean needSubst = FALSE;
     /*



Home | Main Index | Thread Index | Old Index