Module Name:    src
Committed By:   rillig
Date:           Mon Aug  3 15:08:00 UTC 2020

Modified Files:
        src/usr.bin/make: var.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.408 -r1.409 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.408 src/usr.bin/make/var.c:1.409
--- src/usr.bin/make/var.c:1.408	Mon Aug  3 14:42:50 2020
+++ src/usr.bin/make/var.c	Mon Aug  3 15:08:00 2020
@@ -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 @@ VarUniq(const char *str)
  * 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 @@ VarStrftime(const char *fmt, int zulu, t
     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 @@ typedef struct {
 				 * 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 @@ typedef struct {
 				 * embedded spaces (as opposed to the
 				 * usual behaviour of treating it as
 				 * several space-separated words). */
-
 } ApplyModifiersState;
 
 typedef enum {
@@ -1899,20 +1921,21 @@ ModMatchEq(const char *mod, const char *
 
 /* :@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 @@ ApplyModifier_Loop(const char *mod, Appl
 
     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 @@ ApplyModifier_Loop(const char *mod, Appl
 
 /* :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 @@ ApplyModifier_Defined(const char *mod, A
      */
     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 @@ ApplyModifier_Defined(const char *mod, A
 	    p++;
 	}
     }
-
-    st->next = p;
+    *pp = p;
 
     if (st->v->flags & VAR_JUNK)
 	st->v->flags |= VAR_KEEP;
@@ -1997,8 +2019,9 @@ ApplyModifier_Defined(const char *mod, A
 
 /* :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 @@ ApplyModifier_Gmtime(const char *mod, Ap
     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 @@ ApplyModifier_Gmtime(const char *mod, Ap
 
 /* :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 @@ ApplyModifier_Localtime(const char *mod,
     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 @@ ApplyModifier_Localtime(const char *mod,
 
 /* :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 @@ ApplyModifier_Path(const char *mod, Appl
     }
     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 @@ ApplyModifier_Exclam(const char *mod, Ap
 /* 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 @@ ApplyModifier_Range(const char *mod, App
     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 @@ ApplyModifier_Range(const char *mod, App
 
 /* :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;
     /*
@@ -2165,8 +2193,8 @@ ApplyModifier_Match(const char *mod, App
 		break;
 	}
     }
-    st->next = p;
-    const char *endpat = st->next;
+    *pp = p;
+    const char *endpat = p;
 
     char *pattern;
     if (copy) {
@@ -2212,16 +2240,16 @@ ApplyModifier_Match(const char *mod, App
 
 /* :S,from,to, */
 static ApplyModifierResult
-ApplyModifier_Subst(const char * const mod, ApplyModifiersState *st)
+ApplyModifier_Subst(const char **pp, ApplyModifiersState *st)
 {
-    char delim = mod[1];
+    char delim = (*pp)[1];
     if (delim == '\0') {
 	Error("Missing delimiter for :S modifier");
-	st->next = mod + 1;
+	(*pp)++;
 	return AMR_CLEANUP;
     }
 
-    st->next = mod + 2;
+    *pp += 2;
 
     ModifyWord_SubstArgs args;
     args.pflags = 0;
@@ -2230,12 +2258,12 @@ ApplyModifier_Subst(const char * const m
      * If pattern begins with '^', it is anchored to the
      * start of the word -- skip over it and flag pattern.
      */
-    if (*st->next == '^') {
+    if (**pp == '^') {
 	args.pflags |= VARP_ANCHOR_START;
-	st->next++;
+	(*pp)++;
     }
 
-    char *lhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *lhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				  &args.lhsLen, &args.pflags, NULL);
     if (lhs == NULL) {
 	st->missing_delim = delim;
@@ -2243,7 +2271,7 @@ ApplyModifier_Subst(const char * const m
     }
     args.lhs = lhs;
 
-    char *rhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *rhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				  &args.rhsLen, NULL, &args);
     if (rhs == NULL) {
 	st->missing_delim = delim;
@@ -2252,8 +2280,8 @@ ApplyModifier_Subst(const char * const m
     args.rhs = rhs;
 
     Boolean oneBigWord = st->oneBigWord;
-    for (;; st->next++) {
-	switch (*st->next) {
+    for (;; (*pp)++) {
+	switch (**pp) {
 	case 'g':
 	    args.pflags |= VARP_SUB_GLOBAL;
 	    continue;
@@ -2279,18 +2307,18 @@ ApplyModifier_Subst(const char * const m
 
 /* :C,from,to, */
 static ApplyModifierResult
-ApplyModifier_Regex(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Regex(const char **pp, ApplyModifiersState *st)
 {
-    char delim = mod[1];
+    char delim = (*pp)[1];
     if (delim == '\0') {
 	Error("Missing delimiter for :C modifier");
-	st->next = mod + 1;
+	(*pp)++;
 	return AMR_CLEANUP;
     }
 
-    st->next = mod + 2;
+    *pp += 2;
 
-    char *re = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *re = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				 NULL, NULL, NULL);
     if (re == NULL) {
 	st->missing_delim = delim;
@@ -2298,7 +2326,7 @@ ApplyModifier_Regex(const char *mod, App
     }
 
     ModifyWord_SubstRegexArgs args;
-    args.replace = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    args.replace = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				     NULL, NULL, NULL);
     if (args.replace == NULL) {
 	free(re);
@@ -2308,8 +2336,8 @@ ApplyModifier_Regex(const char *mod, App
 
     args.pflags = 0;
     Boolean oneBigWord = st->oneBigWord;
-    for (;; st->next++) {
-	switch (*st->next) {
+    for (;; (*pp)++) {
+	switch (**pp) {
 	case 'g':
 	    args.pflags |= VARP_SUB_GLOBAL;
 	    continue;
@@ -2352,16 +2380,19 @@ ModifyWord_Copy(const char *word, SepBuf
 
 /* :ts<separator> */
 static ApplyModifierResult
-ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st)
+ApplyModifier_ToSep(const char **pp, ApplyModifiersState *st)
 {
+    /* XXX: pp points to the 's', for historic reasons only.
+     * Changing this will influence the error messages. */
+    const char *sep = *pp + 1;
     if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
 	/* ":ts<any><endc>" or ":ts<any>:" */
 	st->sep = sep[0];
-	st->next = sep + 1;
+	*pp = sep + 1;
     } else if (sep[0] == st->endc || sep[0] == ':') {
 	/* ":ts<endc>" or ":ts:" */
 	st->sep = '\0';		/* no separator */
-	st->next = sep;
+	*pp = sep;
     } else if (sep[0] == '\\') {
 	const char *xp = sep + 1;
 	int base = 8;		/* assume octal */
@@ -2369,11 +2400,11 @@ ApplyModifier_ToSep(const char *sep, App
 	switch (sep[1]) {
 	case 'n':
 	    st->sep = '\n';
-	    st->next = sep + 2;
+	    *pp = sep + 2;
 	    break;
 	case 't':
 	    st->sep = '\t';
-	    st->next = sep + 2;
+	    *pp = sep + 2;
 	    break;
 	case 'x':
 	    base = 16;
@@ -2391,7 +2422,7 @@ ApplyModifier_ToSep(const char *sep, App
 	    st->sep = strtoul(xp, &end, base);
 	    if (*end != ':' && *end != st->endc)
 		return AMR_BAD;
-	    st->next = end;
+	    *pp = end;
 	    break;
 	}
     } else {
@@ -2405,16 +2436,17 @@ ApplyModifier_ToSep(const char *sep, App
 
 /* :tA, :tu, :tl, :ts<separator>, etc. */
 static ApplyModifierResult
-ApplyModifier_To(const char *mod, ApplyModifiersState *st)
+ApplyModifier_To(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     assert(mod[0] == 't');
 
-    st->next = mod + 1;		/* make sure it is set */
+    *pp = mod + 1;		/* make sure it is set */
     if (mod[1] == st->endc || mod[1] == ':' || mod[1] == '\0')
 	return AMR_BAD;		/* Found ":t<endc>" or ":t:". */
 
     if (mod[1] == 's')
-	return ApplyModifier_ToSep(mod + 2, st);
+	return ApplyModifier_ToSep(pp, st);
 
     if (mod[2] != st->endc && mod[2] != ':')
 	return AMR_BAD;		/* Found ":t<unrecognised><unrecognised>". */
@@ -2423,25 +2455,25 @@ ApplyModifier_To(const char *mod, ApplyM
     if (mod[1] == 'A') {	/* absolute path */
 	st->newVal = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->val,
 				 ModifyWord_Realpath, NULL);
-	st->next = mod + 2;
+	*pp = mod + 2;
     } else if (mod[1] == 'u') {
 	size_t len = strlen(st->val);
 	st->newVal = bmake_malloc(len + 1);
 	size_t i;
 	for (i = 0; i < len + 1; i++)
 	    st->newVal[i] = toupper((unsigned char)st->val[i]);
-	st->next = mod + 2;
+	*pp = mod + 2;
     } else if (mod[1] == 'l') {
 	size_t len = strlen(st->val);
 	st->newVal = bmake_malloc(len + 1);
 	size_t i;
 	for (i = 0; i < len + 1; i++)
 	    st->newVal[i] = tolower((unsigned char)st->val[i]);
-	st->next = mod + 2;
+	*pp = mod + 2;
     } else if (mod[1] == 'W' || mod[1] == 'w') {
 	st->oneBigWord = mod[1] == 'W';
 	st->newVal = st->val;
-	st->next = mod + 2;
+	*pp = mod + 2;
     } else {
 	/* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
 	return AMR_BAD;
@@ -2451,19 +2483,19 @@ ApplyModifier_To(const char *mod, ApplyM
 
 /* :[#], :[1], etc. */
 static ApplyModifierResult
-ApplyModifier_Words(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Words(const char **pp, ApplyModifiersState *st)
 {
-    st->next = mod + 1;		/* point to char after '[' */
+    (*pp)++;			/* skip the '[' */
     char delim = ']';		/* look for closing ']' */
-    char *estr = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *estr = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				   NULL, NULL, NULL);
     if (estr == NULL) {
 	st->missing_delim = delim;
 	return AMR_CLEANUP;
     }
 
-    /* now st->next points just after the closing ']' */
-    if (st->next[0] != ':' && st->next[0] != st->endc)
+    /* now *pp points just after the closing ']' */
+    if (**pp != ':' && **pp != st->endc)
 	goto bad_modifier;	/* Found junk after ']' */
 
     if (estr[0] == '\0')
@@ -2565,9 +2597,9 @@ str_cmp_desc(const void *a, const void *
 
 /* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */
 static ApplyModifierResult
-ApplyModifier_Order(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Order(const char **pp, ApplyModifiersState *st)
 {
-    st->next = mod + 1;		/* skip past the 'O' in any case */
+    const char *mod = (*pp)++;	/* skip past the 'O' in any case */
 
     char *as;			/* word list memory */
     int ac;
@@ -2579,7 +2611,7 @@ ApplyModifier_Order(const char *mod, App
 
     } else if ((mod[1] == 'r' || mod[1] == 'x') &&
 	       (mod[2] == st->endc || mod[2] == ':')) {
-	st->next = mod + 2;
+	(*pp)++;
 
 	if (mod[1] == 'r') {
 	    /* :Or sorts descending */
@@ -2613,7 +2645,7 @@ ApplyModifier_Order(const char *mod, App
 
 /* :? then : else */
 static ApplyModifierResult
-ApplyModifier_IfElse(const char *mod, ApplyModifiersState *st)
+ApplyModifier_IfElse(const char **pp, ApplyModifiersState *st)
 {
     Boolean value = FALSE;
     VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES;
@@ -2628,9 +2660,9 @@ ApplyModifier_IfElse(const char *mod, Ap
 	    else_eflags |= VARE_WANTRES;
     }
 
-    st->next = mod + 1;
+    (*pp)++;			/* skip past the '?' */
     char delim = ':';
-    char *then_expr = ParseModifierPart(&st->next, delim, then_eflags, st->ctxt,
+    char *then_expr = ParseModifierPart(pp, delim, then_eflags, st->ctxt,
 					NULL, NULL, NULL);
     if (then_expr == NULL) {
 	st->missing_delim = delim;
@@ -2638,14 +2670,14 @@ ApplyModifier_IfElse(const char *mod, Ap
     }
 
     delim = st->endc;		/* BRCLOSE or PRCLOSE */
-    char *else_expr = ParseModifierPart(&st->next, delim, else_eflags, st->ctxt,
+    char *else_expr = ParseModifierPart(pp, delim, else_eflags, st->ctxt,
 					NULL, NULL, NULL);
     if (else_expr == NULL) {
 	st->missing_delim = delim;
 	return AMR_CLEANUP;
     }
 
-    st->next--;
+    (*pp)--;
     if (cond_rc == COND_INVALID) {
 	Error("Bad conditional expression `%s' in %s?%s:%s",
 	    st->v->name, st->v->name, then_expr, else_expr);
@@ -2686,8 +2718,9 @@ ApplyModifier_IfElse(const char *mod, Ap
  *			variable.
  */
 static ApplyModifierResult
-ApplyModifier_Assign(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Assign(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     const char *op = mod + 1;
     if (!(op[0] == '=' ||
 	(op[1] == '=' &&
@@ -2696,7 +2729,7 @@ ApplyModifier_Assign(const char *mod, Ap
 
 
     if (st->v->name[0] == 0) {
-	st->next = mod + 1;
+	*pp = mod + 1;
 	return AMR_BAD;
     }
 
@@ -2720,15 +2753,15 @@ ApplyModifier_Assign(const char *mod, Ap
     case '+':
     case '?':
     case '!':
-	st->next = mod + 3;
+	*pp = mod + 3;
 	break;
     default:
-	st->next = mod + 2;
+	*pp = mod + 2;
 	break;
     }
 
     char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE;
-    char *val = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *val = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				  NULL, NULL, NULL);
     if (st->v->flags & VAR_JUNK) {
 	/* restore original name */
@@ -2740,7 +2773,7 @@ ApplyModifier_Assign(const char *mod, Ap
 	return AMR_CLEANUP;
     }
 
-    st->next--;
+    (*pp)--;
 
     if (st->eflags & VARE_WANTRES) {
 	switch (op[0]) {
@@ -2773,8 +2806,9 @@ ApplyModifier_Assign(const char *mod, Ap
 
 /* remember current value */
 static ApplyModifierResult
-ApplyModifier_Remember(const char *mod, ApplyModifiersState *st)
+ApplyModifier_Remember(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     if (!ModMatchEq(mod, "_", st->endc))
 	return AMR_UNKNOWN;
 
@@ -2783,10 +2817,10 @@ ApplyModifier_Remember(const char *mod, 
 	char *name = bmake_strndup(mod + 2, n);
 	Var_Set(name, st->val, st->ctxt);
 	free(name);
-	st->next = mod + 2 + n;
+	*pp = mod + 2 + n;
     } else {
 	Var_Set("_", st->val, st->ctxt);
-	st->next = mod + 1;
+	*pp = mod + 1;
     }
     st->newVal = st->val;
     return AMR_OK;
@@ -2795,8 +2829,9 @@ ApplyModifier_Remember(const char *mod, 
 #ifdef SYSVVARSUB
 /* :from=to */
 static ApplyModifierResult
-ApplyModifier_SysV(const char *mod, ApplyModifiersState *st)
+ApplyModifier_SysV(const char **pp, ApplyModifiersState *st)
 {
+    const char *mod = *pp;
     Boolean eqFound = FALSE;
 
     /*
@@ -2815,14 +2850,14 @@ ApplyModifier_SysV(const char *mod, Appl
 	else if (*next == st->startc)
 	    nest++;
 	if (nest > 0)
-	    (next)++;
+	    next++;
     }
     if (*next != st->endc || !eqFound)
 	return AMR_UNKNOWN;
 
     char delim = '=';
-    st->next = mod;
-    char *lhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    *pp = mod;
+    char *lhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				  NULL, NULL, NULL);
     if (lhs == NULL) {
 	st->missing_delim = delim;
@@ -2830,7 +2865,7 @@ ApplyModifier_SysV(const char *mod, Appl
     }
 
     delim = st->endc;
-    char *rhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
+    char *rhs = ParseModifierPart(pp, delim, st->eflags, st->ctxt,
 				  NULL, NULL, NULL);
     if (rhs == NULL) {
 	st->missing_delim = delim;
@@ -2841,7 +2876,7 @@ ApplyModifier_SysV(const char *mod, Appl
      * SYSV modifications happen through the whole
      * string. Note the pattern is anchored at the end.
      */
-    st->next--;
+    (*pp)--;
     if (lhs[0] == '\0' && *st->val == '\0') {
 	st->newVal = st->val;	/* special case */
     } else {
@@ -2937,10 +2972,11 @@ ApplyModifiers(
 
     ApplyModifiersState st = {
 	startc, endc, v, ctxt, eflags,
-	val, NULL, NULL, '\0', ' ', FALSE
+	val, NULL, '\0', ' ', FALSE
     };
 
     const char *p = *pp;
+    const char *mod;
     while (*p != '\0' && *p != endc) {
 
 	if (*p == '$') {
@@ -2996,71 +3032,70 @@ ApplyModifiers(
 		*p, st.val);
 	}
 	st.newVal = var_Error;		/* default value, in case of errors */
-	st.next = NULL; /* fail fast if an ApplyModifier forgets to set this */
 	ApplyModifierResult res = AMR_BAD;	/* just a safe fallback */
-	char modifier = *p;
-	switch (modifier) {
+	mod = p;
+	switch (*mod) {
 	case ':':
-	    res = ApplyModifier_Assign(p, &st);
+	    res = ApplyModifier_Assign(&p, &st);
 	    break;
 	case '@':
-	    res = ApplyModifier_Loop(p, &st);
+	    res = ApplyModifier_Loop(&p, &st);
 	    break;
 	case '_':
-	    res = ApplyModifier_Remember(p, &st);
+	    res = ApplyModifier_Remember(&p, &st);
 	    break;
 	case 'D':
 	case 'U':
-	    res = ApplyModifier_Defined(p, &st);
+	    res = ApplyModifier_Defined(&p, &st);
 	    break;
 	case 'L':
 	    if (st.v->flags & VAR_JUNK)
 		st.v->flags |= VAR_KEEP;
 	    st.newVal = bmake_strdup(st.v->name);
-	    st.next = p + 1;
+	    p++;
 	    res = AMR_OK;
 	    break;
 	case 'P':
-	    res = ApplyModifier_Path(p, &st);
+	    res = ApplyModifier_Path(&p, &st);
 	    break;
 	case '!':
-	    res = ApplyModifier_Exclam(p, &st);
+	    res = ApplyModifier_Exclam(&p, &st);
 	    break;
 	case '[':
-	    res = ApplyModifier_Words(p, &st);
+	    res = ApplyModifier_Words(&p, &st);
 	    break;
 	case 'g':
-	    res = ApplyModifier_Gmtime(p, &st);
+	    res = ApplyModifier_Gmtime(&p, &st);
 	    break;
 	case 'h':
-	    res = ApplyModifier_Hash(p, &st);
+	    res = ApplyModifier_Hash(&p, &st);
 	    break;
 	case 'l':
-	    res = ApplyModifier_Localtime(p, &st);
+	    res = ApplyModifier_Localtime(&p, &st);
 	    break;
 	case 't':
-	    res = ApplyModifier_To(p, &st);
+	    res = ApplyModifier_To(&p, &st);
 	    break;
 	case 'N':
 	case 'M':
-	    res = ApplyModifier_Match(p, &st);
+	    res = ApplyModifier_Match(&p, &st);
 	    break;
 	case 'S':
-	    res = ApplyModifier_Subst(p, &st);
+	    res = ApplyModifier_Subst(&p, &st);
 	    break;
 	case '?':
-	    res = ApplyModifier_IfElse(p, &st);
+	    res = ApplyModifier_IfElse(&p, &st);
 	    break;
 #ifndef NO_REGEX
 	case 'C':
-	    res = ApplyModifier_Regex(p, &st);
+	    res = ApplyModifier_Regex(&p, &st);
 	    break;
 #endif
 	case 'q':
 	case 'Q':
 	    if (p[1] == st.endc || p[1] == ':') {
-		st.newVal = VarQuote(st.val, modifier == 'q');
-		st.next = p + 1;
+		st.newVal = VarQuote(st.val, *mod == 'q');
+		p++;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
@@ -3069,7 +3104,7 @@ ApplyModifiers(
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Tail, NULL);
-		st.next = p + 1;
+		p++;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
@@ -3078,7 +3113,7 @@ ApplyModifiers(
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Head, NULL);
-		st.next = p + 1;
+		p++;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
@@ -3087,7 +3122,7 @@ ApplyModifiers(
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Suffix, NULL);
-		st.next = p + 1;
+		p++;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
@@ -3096,21 +3131,21 @@ ApplyModifiers(
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
 					st.val, ModifyWord_Root, NULL);
-		st.next = p + 1;
+		p++;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
 	    break;
 	case 'r':
-	    res = ApplyModifier_Range(p, &st);
+	    res = ApplyModifier_Range(&p, &st);
 	    break;
 	case 'O':
-	    res = ApplyModifier_Order(p, &st);
+	    res = ApplyModifier_Order(&p, &st);
 	    break;
 	case 'u':
 	    if (p[1] == st.endc || p[1] == ':') {
 		st.newVal = VarUniq(st.val);
-		st.next = p + 1;
+		p++;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
@@ -3125,7 +3160,7 @@ ApplyModifiers(
 			Error(emsg, st.val);
 		} else
 		    st.newVal = varNoError;
-		st.next = p + 2;
+		p += 2;
 		res = AMR_OK;
 	    } else
 		res = AMR_UNKNOWN;
@@ -3136,15 +3171,16 @@ ApplyModifiers(
 	}
 
 #ifdef SYSVVARSUB
-	if (res == AMR_UNKNOWN)
-	    res = ApplyModifier_SysV(p, &st);
+	if (res == AMR_UNKNOWN) {
+	    assert(p == mod);
+	    res = ApplyModifier_SysV(&p, &st);
+	}
 #endif
 
 	if (res == AMR_UNKNOWN) {
-	    Error("Unknown modifier '%c'", *p);
-	    st.next = p + 1;
-	    while (*st.next != ':' && *st.next != st.endc && *st.next != '\0')
-		st.next++;
+	    Error("Unknown modifier '%c'", *mod);
+	    for (p++; *p != ':' && *p != st.endc && *p != '\0'; p++)
+		continue;
 	    st.newVal = var_Error;
 	}
 	if (res == AMR_CLEANUP)
@@ -3154,7 +3190,7 @@ ApplyModifiers(
 
 	if (DEBUG(VAR)) {
 	    fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
-		st.v->name, modifier, st.newVal);
+		st.v->name, *mod, st.newVal);
 	}
 
 	if (st.newVal != st.val) {
@@ -3167,14 +3203,14 @@ ApplyModifiers(
 		*freePtr = st.val;
 	    }
 	}
-	if (*st.next == '\0' && st.endc != '\0') {
+	if (*p == '\0' && st.endc != '\0') {
 	    Error("Unclosed variable specification (expecting '%c') "
 		"for \"%s\" (value \"%s\") modifier %c",
-		st.endc, st.v->name, st.val, modifier);
-	} else if (*st.next == ':') {
-	    st.next++;
+		st.endc, st.v->name, st.val, *mod);
+	} else if (*p == ':') {
+	    p++;
 	}
-	p = st.next;
+	mod = p;
     }
 out:
     *pp = p;
@@ -3182,10 +3218,10 @@ out:
 
 bad_modifier:
     Error("Bad modifier `:%.*s' for %s",
-	  (int)strcspn(p, ":)}"), p, st.v->name);
+	  (int)strcspn(mod, ":)}"), mod, st.v->name);
 
 cleanup:
-    *pp = st.next;
+    *pp = p;
     if (st.missing_delim != '\0')
 	Error("Unclosed substitution for %s (%c missing)",
 	      st.v->name, st.missing_delim);

Reply via email to