Mon Jul 27 23:24:55 2020 UTC ()
make(1): rename ApplyModifiersState.cp to next

The name "next" is more descriptive than a mere "cp".  It's easy to look
up the type of the variable, but not so easy to guess the purpose of the
variable, therefore the new name concentrates on the purpose.


(rillig)
diff -r1.347 -r1.348 src/usr.bin/make/var.c

cvs diff -r1.347 -r1.348 src/usr.bin/make/var.c (expand / switch to unified diff)

--- src/usr.bin/make/var.c 2020/07/27 23:04:18 1.347
+++ src/usr.bin/make/var.c 2020/07/27 23:24:55 1.348
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.347 2020/07/27 23:04:18 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.348 2020/07/27 23:24:55 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -59,34 +59,34 @@ @@ -59,34 +59,34 @@
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: var.c,v 1.347 2020/07/27 23:04:18 rillig Exp $"; 72static char rcsid[] = "$NetBSD: var.c,v 1.348 2020/07/27 23:24:55 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94"; 77static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
78#else 78#else
79__RCSID("$NetBSD: var.c,v 1.347 2020/07/27 23:04:18 rillig Exp $"); 79__RCSID("$NetBSD: var.c,v 1.348 2020/07/27 23:24:55 rillig Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * var.c -- 85 * var.c --
86 * Variable-handling functions 86 * Variable-handling functions
87 * 87 *
88 * Interface: 88 * Interface:
89 * Var_Set Set the value of a variable in the given 89 * Var_Set Set the value of a variable in the given
90 * context. The variable is created if it doesn't 90 * context. The variable is created if it doesn't
91 * yet exist. 91 * yet exist.
92 * 92 *
@@ -2036,27 +2036,27 @@ VarStrftime(const char *fmt, int zulu, t @@ -2036,27 +2036,27 @@ VarStrftime(const char *fmt, int zulu, t
2036 return bmake_strdup(buf); 2036 return bmake_strdup(buf);
2037} 2037}
2038 2038
2039typedef struct { 2039typedef struct {
2040 /* const parameters */ 2040 /* const parameters */
2041 int startc; /* '\0' or '{' or '(' */ 2041 int startc; /* '\0' or '{' or '(' */
2042 int endc; 2042 int endc;
2043 Var *v; 2043 Var *v;
2044 GNode *ctxt; 2044 GNode *ctxt;
2045 VarEvalFlags eflags; 2045 VarEvalFlags eflags;
2046 2046
2047 /* read-write */ 2047 /* read-write */
2048 char *nstr; 2048 char *nstr;
2049 const char *cp; /* The position where parsing continues 2049 const char *next; /* The position where parsing continues
2050 * after the current modifier. */ 2050 * after the current modifier. */
2051 char termc; /* Character which terminated scan */ 2051 char termc; /* Character which terminated scan */
2052 char missing_delim; /* For error reporting */ 2052 char missing_delim; /* For error reporting */
2053 2053
2054 Byte sep; /* Word separator in expansions */ 2054 Byte sep; /* Word separator in expansions */
2055 Boolean oneBigWord; /* TRUE if we will treat the variable as a 2055 Boolean oneBigWord; /* TRUE if we will treat the variable as a
2056 * single big word, even if it contains 2056 * single big word, even if it contains
2057 * embedded spaces (as opposed to the 2057 * embedded spaces (as opposed to the
2058 * usual behaviour of treating it as 2058 * usual behaviour of treating it as
2059 * several space-separated words). */ 2059 * several space-separated words). */
2060 2060
2061 /* result */ 2061 /* result */
2062 char *newStr; /* New value to return */ 2062 char *newStr; /* New value to return */
@@ -2075,43 +2075,43 @@ static inline Boolean @@ -2075,43 +2075,43 @@ static inline Boolean
2075ModMatchEq(const char *mod, const char *modname, char endc) 2075ModMatchEq(const char *mod, const char *modname, char endc)
2076{ 2076{
2077 size_t n = strlen(modname); 2077 size_t n = strlen(modname);
2078 return strncmp(mod, modname, n) == 0 && 2078 return strncmp(mod, modname, n) == 0 &&
2079 (mod[n] == endc || mod[n] == ':' || mod[n] == '='); 2079 (mod[n] == endc || mod[n] == ':' || mod[n] == '=');
2080} 2080}
2081 2081
2082/* :@var@...${var}...@ */ 2082/* :@var@...${var}...@ */
2083static Boolean 2083static Boolean
2084ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) { 2084ApplyModifier_Loop(const char *mod, ApplyModifiersState *st) {
2085 ModifyWord_LoopArgs args; 2085 ModifyWord_LoopArgs args;
2086 2086
2087 args.ctx = st->ctxt; 2087 args.ctx = st->ctxt;
2088 st->cp = mod + 1; 2088 st->next = mod + 1;
2089 char delim = '@'; 2089 char delim = '@';
2090 args.tvar = ParseModifierPart(&st->cp, delim, st->eflags & ~VARE_WANTRES, 2090 args.tvar = ParseModifierPart(&st->next, delim, st->eflags & ~VARE_WANTRES,
2091 st->ctxt, NULL, NULL, NULL); 2091 st->ctxt, NULL, NULL, NULL);
2092 if (args.tvar == NULL) { 2092 if (args.tvar == NULL) {
2093 st->missing_delim = delim; 2093 st->missing_delim = delim;
2094 return FALSE; 2094 return FALSE;
2095 } 2095 }
2096 2096
2097 args.str = ParseModifierPart(&st->cp, delim, st->eflags & ~VARE_WANTRES, 2097 args.str = ParseModifierPart(&st->next, delim, st->eflags & ~VARE_WANTRES,
2098 st->ctxt, NULL, NULL, NULL); 2098 st->ctxt, NULL, NULL, NULL);
2099 if (args.str == NULL) { 2099 if (args.str == NULL) {
2100 st->missing_delim = delim; 2100 st->missing_delim = delim;
2101 return FALSE; 2101 return FALSE;
2102 } 2102 }
2103 2103
2104 st->termc = *st->cp; 2104 st->termc = *st->next;
2105 2105
2106 args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES); 2106 args.eflags = st->eflags & (VARE_UNDEFERR | VARE_WANTRES);
2107 int prev_sep = st->sep; 2107 int prev_sep = st->sep;
2108 st->sep = ' '; /* XXX: this is inconsistent */ 2108 st->sep = ' '; /* XXX: this is inconsistent */
2109 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, 2109 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
2110 ModifyWord_Loop, &args); 2110 ModifyWord_Loop, &args);
2111 st->sep = prev_sep; 2111 st->sep = prev_sep;
2112 Var_Delete(args.tvar, st->ctxt); 2112 Var_Delete(args.tvar, st->ctxt);
2113 free(args.tvar); 2113 free(args.tvar);
2114 free(args.str); 2114 free(args.str);
2115 return TRUE; 2115 return TRUE;
2116} 2116}
2117 2117
@@ -2157,169 +2157,169 @@ ApplyModifier_Defined(const char *mod, A @@ -2157,169 +2157,169 @@ ApplyModifier_Defined(const char *mod, A
2157 int len; 2157 int len;
2158 void *freeIt; 2158 void *freeIt;
2159 2159
2160 cp2 = Var_Parse(p, st->ctxt, neflags, &len, &freeIt); 2160 cp2 = Var_Parse(p, st->ctxt, neflags, &len, &freeIt);
2161 Buf_AddStr(&buf, cp2); 2161 Buf_AddStr(&buf, cp2);
2162 free(freeIt); 2162 free(freeIt);
2163 p += len; 2163 p += len;
2164 } else { 2164 } else {
2165 Buf_AddByte(&buf, *p); 2165 Buf_AddByte(&buf, *p);
2166 p++; 2166 p++;
2167 } 2167 }
2168 } 2168 }
2169 2169
2170 st->cp = p; 2170 st->next = p;
2171 st->termc = *st->cp; 2171 st->termc = *st->next;
2172 2172
2173 if (st->v->flags & VAR_JUNK) 2173 if (st->v->flags & VAR_JUNK)
2174 st->v->flags |= VAR_KEEP; 2174 st->v->flags |= VAR_KEEP;
2175 if (neflags & VARE_WANTRES) { 2175 if (neflags & VARE_WANTRES) {
2176 st->newStr = Buf_Destroy(&buf, FALSE); 2176 st->newStr = Buf_Destroy(&buf, FALSE);
2177 } else { 2177 } else {
2178 st->newStr = st->nstr; 2178 st->newStr = st->nstr;
2179 Buf_Destroy(&buf, TRUE); 2179 Buf_Destroy(&buf, TRUE);
2180 } 2180 }
2181} 2181}
2182 2182
2183/* :gmtime */ 2183/* :gmtime */
2184static Boolean 2184static Boolean
2185ApplyModifier_Gmtime(const char *mod, ApplyModifiersState *st) 2185ApplyModifier_Gmtime(const char *mod, ApplyModifiersState *st)
2186{ 2186{
2187 if (!ModMatchEq(mod, "gmtime", st->endc)) { 2187 if (!ModMatchEq(mod, "gmtime", st->endc)) {
2188 st->cp = mod + 1; 2188 st->next = mod + 1;
2189 return FALSE; 2189 return FALSE;
2190 } 2190 }
2191 2191
2192 time_t utc; 2192 time_t utc;
2193 if (mod[6] == '=') { 2193 if (mod[6] == '=') {
2194 char *ep; 2194 char *ep;
2195 utc = strtoul(mod + 7, &ep, 10); 2195 utc = strtoul(mod + 7, &ep, 10);
2196 st->cp = ep; 2196 st->next = ep;
2197 } else { 2197 } else {
2198 utc = 0; 2198 utc = 0;
2199 st->cp = mod + 6; 2199 st->next = mod + 6;
2200 } 2200 }
2201 st->newStr = VarStrftime(st->nstr, 1, utc); 2201 st->newStr = VarStrftime(st->nstr, 1, utc);
2202 st->termc = *st->cp; 2202 st->termc = *st->next;
2203 return TRUE; 2203 return TRUE;
2204} 2204}
2205 2205
2206/* :localtime */ 2206/* :localtime */
2207static Boolean 2207static Boolean
2208ApplyModifier_Localtime(const char *mod, ApplyModifiersState *st) 2208ApplyModifier_Localtime(const char *mod, ApplyModifiersState *st)
2209{ 2209{
2210 if (!ModMatchEq(mod, "localtime", st->endc)) { 2210 if (!ModMatchEq(mod, "localtime", st->endc)) {
2211 st->cp = mod + 1; 2211 st->next = mod + 1;
2212 return FALSE; 2212 return FALSE;
2213 } 2213 }
2214 2214
2215 time_t utc; 2215 time_t utc;
2216 if (mod[9] == '=') { 2216 if (mod[9] == '=') {
2217 char *ep; 2217 char *ep;
2218 utc = strtoul(mod + 10, &ep, 10); 2218 utc = strtoul(mod + 10, &ep, 10);
2219 st->cp = ep; 2219 st->next = ep;
2220 } else { 2220 } else {
2221 utc = 0; 2221 utc = 0;
2222 st->cp = mod + 9; 2222 st->next = mod + 9;
2223 } 2223 }
2224 st->newStr = VarStrftime(st->nstr, 0, utc); 2224 st->newStr = VarStrftime(st->nstr, 0, utc);
2225 st->termc = *st->cp; 2225 st->termc = *st->next;
2226 return TRUE; 2226 return TRUE;
2227} 2227}
2228 2228
2229/* :hash */ 2229/* :hash */
2230static Boolean 2230static Boolean
2231ApplyModifier_Hash(const char *mod, ApplyModifiersState *st) 2231ApplyModifier_Hash(const char *mod, ApplyModifiersState *st)
2232{ 2232{
2233 if (!ModMatch(mod, "hash", st->endc)) { 2233 if (!ModMatch(mod, "hash", st->endc)) {
2234 st->cp = mod + 1; 2234 st->next = mod + 1;
2235 return FALSE; 2235 return FALSE;
2236 } 2236 }
2237 2237
2238 st->newStr = VarHash(st->nstr); 2238 st->newStr = VarHash(st->nstr);
2239 st->cp = mod + 4; 2239 st->next = mod + 4;
2240 st->termc = *st->cp; 2240 st->termc = *st->next;
2241 return TRUE; 2241 return TRUE;
2242} 2242}
2243 2243
2244/* :P */ 2244/* :P */
2245static void 2245static void
2246ApplyModifier_Path(const char *mod, ApplyModifiersState *st) 2246ApplyModifier_Path(const char *mod, ApplyModifiersState *st)
2247{ 2247{
2248 if (st->v->flags & VAR_JUNK) 2248 if (st->v->flags & VAR_JUNK)
2249 st->v->flags |= VAR_KEEP; 2249 st->v->flags |= VAR_KEEP;
2250 GNode *gn = Targ_FindNode(st->v->name, TARG_NOCREATE); 2250 GNode *gn = Targ_FindNode(st->v->name, TARG_NOCREATE);
2251 if (gn == NULL || gn->type & OP_NOPATH) { 2251 if (gn == NULL || gn->type & OP_NOPATH) {
2252 st->newStr = NULL; 2252 st->newStr = NULL;
2253 } else if (gn->path) { 2253 } else if (gn->path) {
2254 st->newStr = bmake_strdup(gn->path); 2254 st->newStr = bmake_strdup(gn->path);
2255 } else { 2255 } else {
2256 st->newStr = Dir_FindFile(st->v->name, Suff_FindPath(gn)); 2256 st->newStr = Dir_FindFile(st->v->name, Suff_FindPath(gn));
2257 } 2257 }
2258 if (!st->newStr) 2258 if (!st->newStr)
2259 st->newStr = bmake_strdup(st->v->name); 2259 st->newStr = bmake_strdup(st->v->name);
2260 st->cp = mod + 1; 2260 st->next = mod + 1;
2261 st->termc = *st->cp; 2261 st->termc = *st->next;
2262} 2262}
2263 2263
2264/* :!cmd! */ 2264/* :!cmd! */
2265static Boolean 2265static Boolean
2266ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st) 2266ApplyModifier_Exclam(const char *mod, ApplyModifiersState *st)
2267{ 2267{
2268 st->cp = mod + 1; 2268 st->next = mod + 1;
2269 char delim = '!'; 2269 char delim = '!';
2270 char *cmd = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2270 char *cmd = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2271 NULL, NULL, NULL); 2271 NULL, NULL, NULL);
2272 if (cmd == NULL) { 2272 if (cmd == NULL) {
2273 st->missing_delim = delim; 2273 st->missing_delim = delim;
2274 return FALSE; 2274 return FALSE;
2275 } 2275 }
2276 2276
2277 const char *emsg = NULL; 2277 const char *emsg = NULL;
2278 if (st->eflags & VARE_WANTRES) 2278 if (st->eflags & VARE_WANTRES)
2279 st->newStr = Cmd_Exec(cmd, &emsg); 2279 st->newStr = Cmd_Exec(cmd, &emsg);
2280 else 2280 else
2281 st->newStr = varNoError; 2281 st->newStr = varNoError;
2282 free(cmd); 2282 free(cmd);
2283 2283
2284 if (emsg) 2284 if (emsg)
2285 Error(emsg, st->nstr); 2285 Error(emsg, st->nstr);
2286 2286
2287 st->termc = *st->cp; 2287 st->termc = *st->next;
2288 if (st->v->flags & VAR_JUNK) 2288 if (st->v->flags & VAR_JUNK)
2289 st->v->flags |= VAR_KEEP; 2289 st->v->flags |= VAR_KEEP;
2290 return TRUE; 2290 return TRUE;
2291} 2291}
2292 2292
2293/* :range */ 2293/* :range */
2294static Boolean 2294static Boolean
2295ApplyModifier_Range(const char *mod, ApplyModifiersState *st) 2295ApplyModifier_Range(const char *mod, ApplyModifiersState *st)
2296{ 2296{
2297 if (!ModMatchEq(mod, "range", st->endc)) { 2297 if (!ModMatchEq(mod, "range", st->endc)) {
2298 st->cp = mod + 1; 2298 st->next = mod + 1;
2299 return FALSE; 2299 return FALSE;
2300 } 2300 }
2301 2301
2302 int n; 2302 int n;
2303 if (mod[5] == '=') { 2303 if (mod[5] == '=') {
2304 char *ep; 2304 char *ep;
2305 n = strtoul(mod + 6, &ep, 10); 2305 n = strtoul(mod + 6, &ep, 10);
2306 st->cp = ep; 2306 st->next = ep;
2307 } else { 2307 } else {
2308 n = 0; 2308 n = 0;
2309 st->cp = mod + 5; 2309 st->next = mod + 5;
2310 } 2310 }
2311 st->newStr = VarRange(st->nstr, n); 2311 st->newStr = VarRange(st->nstr, n);
2312 st->termc = *st->cp; 2312 st->termc = *st->next;
2313 return TRUE; 2313 return TRUE;
2314} 2314}
2315 2315
2316/* :Mpattern or :Npattern */ 2316/* :Mpattern or :Npattern */
2317static void 2317static void
2318ApplyModifier_Match(const char *mod, ApplyModifiersState *st) 2318ApplyModifier_Match(const char *mod, ApplyModifiersState *st)
2319{ 2319{
2320 Boolean copy = FALSE; /* pattern should be, or has been, copied */ 2320 Boolean copy = FALSE; /* pattern should be, or has been, copied */
2321 Boolean needSubst = FALSE; 2321 Boolean needSubst = FALSE;
2322 /* 2322 /*
2323 * In the loop below, ignore ':' unless we are at (or back to) the 2323 * In the loop below, ignore ':' unless we are at (or back to) the
2324 * original brace level. 2324 * original brace level.
2325 * XXX This will likely not work right if $() and ${} are intermixed. 2325 * XXX This will likely not work right if $() and ${} are intermixed.
@@ -2334,29 +2334,29 @@ ApplyModifier_Match(const char *mod, App @@ -2334,29 +2334,29 @@ ApplyModifier_Match(const char *mod, App
2334 p++; 2334 p++;
2335 continue; 2335 continue;
2336 } 2336 }
2337 if (*p == '$') 2337 if (*p == '$')
2338 needSubst = TRUE; 2338 needSubst = TRUE;
2339 if (*p == '(' || *p == '{') 2339 if (*p == '(' || *p == '{')
2340 ++nest; 2340 ++nest;
2341 if (*p == ')' || *p == '}') { 2341 if (*p == ')' || *p == '}') {
2342 --nest; 2342 --nest;
2343 if (nest == 0) 2343 if (nest == 0)
2344 break; 2344 break;
2345 } 2345 }
2346 } 2346 }
2347 st->cp = p; 2347 st->next = p;
2348 st->termc = *st->cp; 2348 st->termc = *st->next;
2349 const char *endpat = st->cp; 2349 const char *endpat = st->next;
2350 2350
2351 char *pattern; 2351 char *pattern;
2352 if (copy) { 2352 if (copy) {
2353 /* Compress the \:'s out of the pattern. */ 2353 /* Compress the \:'s out of the pattern. */
2354 pattern = bmake_malloc(endpat - (mod + 1) + 1); 2354 pattern = bmake_malloc(endpat - (mod + 1) + 1);
2355 char *dst = pattern; 2355 char *dst = pattern;
2356 const char *src = mod + 1; 2356 const char *src = mod + 1;
2357 for (; src < endpat; src++, dst++) { 2357 for (; src < endpat; src++, dst++) {
2358 if (src[0] == '\\' && src + 1 < endpat && 2358 if (src[0] == '\\' && src + 1 < endpat &&
2359 /* XXX: st->startc is missing here; see above */ 2359 /* XXX: st->startc is missing here; see above */
2360 (src[1] == ':' || src[1] == st->endc)) 2360 (src[1] == ':' || src[1] == st->endc))
2361 src++; 2361 src++;
2362 *dst = *src; 2362 *dst = *src;
@@ -2387,128 +2387,128 @@ ApplyModifier_Match(const char *mod, App @@ -2387,128 +2387,128 @@ ApplyModifier_Match(const char *mod, App
2387 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, 2387 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
2388 callback, pattern); 2388 callback, pattern);
2389 free(pattern); 2389 free(pattern);
2390} 2390}
2391 2391
2392/* :S,from,to, */ 2392/* :S,from,to, */
2393static Boolean 2393static Boolean
2394ApplyModifier_Subst(const char * const mod, ApplyModifiersState *st) 2394ApplyModifier_Subst(const char * const mod, ApplyModifiersState *st)
2395{ 2395{
2396 ModifyWord_SubstArgs args; 2396 ModifyWord_SubstArgs args;
2397 Boolean oneBigWord = st->oneBigWord; 2397 Boolean oneBigWord = st->oneBigWord;
2398 char delim = mod[1]; 2398 char delim = mod[1];
2399 2399
2400 st->cp = mod + 2; 2400 st->next = mod + 2;
2401 2401
2402 /* 2402 /*
2403 * If pattern begins with '^', it is anchored to the 2403 * If pattern begins with '^', it is anchored to the
2404 * start of the word -- skip over it and flag pattern. 2404 * start of the word -- skip over it and flag pattern.
2405 */ 2405 */
2406 args.pflags = 0; 2406 args.pflags = 0;
2407 if (*st->cp == '^') { 2407 if (*st->next == '^') {
2408 args.pflags |= VARP_ANCHOR_START; 2408 args.pflags |= VARP_ANCHOR_START;
2409 st->cp++; 2409 st->next++;
2410 } 2410 }
2411 2411
2412 char *lhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2412 char *lhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2413 &args.lhsLen, &args.pflags, NULL); 2413 &args.lhsLen, &args.pflags, NULL);
2414 if (lhs == NULL) { 2414 if (lhs == NULL) {
2415 st->missing_delim = delim; 2415 st->missing_delim = delim;
2416 return FALSE; 2416 return FALSE;
2417 } 2417 }
2418 args.lhs = lhs; 2418 args.lhs = lhs;
2419 2419
2420 char *rhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2420 char *rhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2421 &args.rhsLen, NULL, &args); 2421 &args.rhsLen, NULL, &args);
2422 if (rhs == NULL) { 2422 if (rhs == NULL) {
2423 st->missing_delim = delim; 2423 st->missing_delim = delim;
2424 return FALSE; 2424 return FALSE;
2425 } 2425 }
2426 args.rhs = rhs; 2426 args.rhs = rhs;
2427 2427
2428 /* 2428 /*
2429 * Check for global substitution. If 'g' after the final 2429 * Check for global substitution. If 'g' after the final
2430 * delimiter, substitution is global and is marked that 2430 * delimiter, substitution is global and is marked that
2431 * way. 2431 * way.
2432 */ 2432 */
2433 for (;; st->cp++) { 2433 for (;; st->next++) {
2434 switch (*st->cp) { 2434 switch (*st->next) {
2435 case 'g': 2435 case 'g':
2436 args.pflags |= VARP_SUB_GLOBAL; 2436 args.pflags |= VARP_SUB_GLOBAL;
2437 continue; 2437 continue;
2438 case '1': 2438 case '1':
2439 args.pflags |= VARP_SUB_ONE; 2439 args.pflags |= VARP_SUB_ONE;
2440 continue; 2440 continue;
2441 case 'W': 2441 case 'W':
2442 oneBigWord = TRUE; 2442 oneBigWord = TRUE;
2443 continue; 2443 continue;
2444 } 2444 }
2445 break; 2445 break;
2446 } 2446 }
2447 2447
2448 st->termc = *st->cp; 2448 st->termc = *st->next;
2449 st->newStr = ModifyWords(st->ctxt, st->sep, oneBigWord, st->nstr, 2449 st->newStr = ModifyWords(st->ctxt, st->sep, oneBigWord, st->nstr,
2450 ModifyWord_Subst, &args); 2450 ModifyWord_Subst, &args);
2451 2451
2452 free(lhs); 2452 free(lhs);
2453 free(rhs); 2453 free(rhs);
2454 return TRUE; 2454 return TRUE;
2455} 2455}
2456 2456
2457#ifndef NO_REGEX 2457#ifndef NO_REGEX
2458 2458
2459/* :C,from,to, */ 2459/* :C,from,to, */
2460static Boolean 2460static Boolean
2461ApplyModifier_Regex(const char *mod, ApplyModifiersState *st) 2461ApplyModifier_Regex(const char *mod, ApplyModifiersState *st)
2462{ 2462{
2463 ModifyWord_SubstRegexArgs args; 2463 ModifyWord_SubstRegexArgs args;
2464 2464
2465 args.pflags = 0; 2465 args.pflags = 0;
2466 Boolean oneBigWord = st->oneBigWord; 2466 Boolean oneBigWord = st->oneBigWord;
2467 char delim = mod[1]; 2467 char delim = mod[1];
2468 2468
2469 st->cp = mod + 2; 2469 st->next = mod + 2;
2470 2470
2471 char *re = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2471 char *re = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2472 NULL, NULL, NULL); 2472 NULL, NULL, NULL);
2473 if (re == NULL) { 2473 if (re == NULL) {
2474 st->missing_delim = delim; 2474 st->missing_delim = delim;
2475 return FALSE; 2475 return FALSE;
2476 } 2476 }
2477 2477
2478 args.replace = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2478 args.replace = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2479 NULL, NULL, NULL); 2479 NULL, NULL, NULL);
2480 if (args.replace == NULL) { 2480 if (args.replace == NULL) {
2481 free(re); 2481 free(re);
2482 st->missing_delim = delim; 2482 st->missing_delim = delim;
2483 return FALSE; 2483 return FALSE;
2484 } 2484 }
2485 2485
2486 for (;; st->cp++) { 2486 for (;; st->next++) {
2487 switch (*st->cp) { 2487 switch (*st->next) {
2488 case 'g': 2488 case 'g':
2489 args.pflags |= VARP_SUB_GLOBAL; 2489 args.pflags |= VARP_SUB_GLOBAL;
2490 continue; 2490 continue;
2491 case '1': 2491 case '1':
2492 args.pflags |= VARP_SUB_ONE; 2492 args.pflags |= VARP_SUB_ONE;
2493 continue; 2493 continue;
2494 case 'W': 2494 case 'W':
2495 oneBigWord = TRUE; 2495 oneBigWord = TRUE;
2496 continue; 2496 continue;
2497 } 2497 }
2498 break; 2498 break;
2499 } 2499 }
2500 2500
2501 st->termc = *st->cp; 2501 st->termc = *st->next;
2502 2502
2503 int error = regcomp(&args.re, re, REG_EXTENDED); 2503 int error = regcomp(&args.re, re, REG_EXTENDED);
2504 free(re); 2504 free(re);
2505 if (error) { 2505 if (error) {
2506 VarREError(error, &args.re, "RE substitution error"); 2506 VarREError(error, &args.re, "RE substitution error");
2507 free(args.replace); 2507 free(args.replace);
2508 return FALSE; 2508 return FALSE;
2509 } 2509 }
2510 2510
2511 args.nsub = args.re.re_nsub + 1; 2511 args.nsub = args.re.re_nsub + 1;
2512 if (args.nsub < 1) 2512 if (args.nsub < 1)
2513 args.nsub = 1; 2513 args.nsub = 1;
2514 if (args.nsub > 10) 2514 if (args.nsub > 10)
@@ -2524,132 +2524,132 @@ ApplyModifier_Regex(const char *mod, App @@ -2524,132 +2524,132 @@ ApplyModifier_Regex(const char *mod, App
2524static void 2524static void
2525ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 2525ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
2526{ 2526{
2527 SepBuf_AddStr(buf, word); 2527 SepBuf_AddStr(buf, word);
2528} 2528}
2529 2529
2530/* :ts<separator> */ 2530/* :ts<separator> */
2531static Boolean 2531static Boolean
2532ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st) 2532ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st)
2533{ 2533{
2534 if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) { 2534 if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
2535 /* ":ts<unrecognised><endc>" or ":ts<unrecognised>:" */ 2535 /* ":ts<unrecognised><endc>" or ":ts<unrecognised>:" */
2536 st->sep = sep[0]; 2536 st->sep = sep[0];
2537 st->cp = sep + 1; 2537 st->next = sep + 1;
2538 } else if (sep[0] == st->endc || sep[0] == ':') { 2538 } else if (sep[0] == st->endc || sep[0] == ':') {
2539 /* ":ts<endc>" or ":ts:" */ 2539 /* ":ts<endc>" or ":ts:" */
2540 st->sep = '\0'; /* no separator */ 2540 st->sep = '\0'; /* no separator */
2541 st->cp = sep; 2541 st->next = sep;
2542 } else if (sep[0] == '\\') { 2542 } else if (sep[0] == '\\') {
2543 const char *xp = sep + 1; 2543 const char *xp = sep + 1;
2544 int base = 8; /* assume octal */ 2544 int base = 8; /* assume octal */
2545 2545
2546 switch (sep[1]) { 2546 switch (sep[1]) {
2547 case 'n': 2547 case 'n':
2548 st->sep = '\n'; 2548 st->sep = '\n';
2549 st->cp = sep + 2; 2549 st->next = sep + 2;
2550 break; 2550 break;
2551 case 't': 2551 case 't':
2552 st->sep = '\t'; 2552 st->sep = '\t';
2553 st->cp = sep + 2; 2553 st->next = sep + 2;
2554 break; 2554 break;
2555 case 'x': 2555 case 'x':
2556 base = 16; 2556 base = 16;
2557 xp++; 2557 xp++;
2558 goto get_numeric; 2558 goto get_numeric;
2559 case '0': 2559 case '0':
2560 base = 0; 2560 base = 0;
2561 goto get_numeric; 2561 goto get_numeric;
2562 default: 2562 default:
2563 if (!isdigit((unsigned char)sep[1])) 2563 if (!isdigit((unsigned char)sep[1]))
2564 return FALSE; /* ":ts<backslash><unrecognised>". */ 2564 return FALSE; /* ":ts<backslash><unrecognised>". */
2565 2565
2566 char *end; 2566 char *end;
2567 get_numeric: 2567 get_numeric:
2568 st->sep = strtoul(sep + 1 + (sep[1] == 'x'), &end, base); 2568 st->sep = strtoul(sep + 1 + (sep[1] == 'x'), &end, base);
2569 if (*end != ':' && *end != st->endc) 2569 if (*end != ':' && *end != st->endc)
2570 return FALSE; 2570 return FALSE;
2571 st->cp = end; 2571 st->next = end;
2572 break; 2572 break;
2573 } 2573 }
2574 } else { 2574 } else {
2575 return FALSE; /* Found ":ts<unrecognised><unrecognised>". */ 2575 return FALSE; /* Found ":ts<unrecognised><unrecognised>". */
2576 } 2576 }
2577 2577
2578 st->termc = *st->cp; 2578 st->termc = *st->next;
2579 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, 2579 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
2580 ModifyWord_Copy, NULL); 2580 ModifyWord_Copy, NULL);
2581 return TRUE; 2581 return TRUE;
2582} 2582}
2583 2583
2584/* :tA, :tu, :tl, :ts<separator>, etc. */ 2584/* :tA, :tu, :tl, :ts<separator>, etc. */
2585static Boolean 2585static Boolean
2586ApplyModifier_To(const char *mod, ApplyModifiersState *st) 2586ApplyModifier_To(const char *mod, ApplyModifiersState *st)
2587{ 2587{
2588 st->cp = mod + 1; /* make sure it is set */ 2588 st->next = mod + 1; /* make sure it is set */
2589 if (mod[1] == st->endc || mod[1] == ':') 2589 if (mod[1] == st->endc || mod[1] == ':')
2590 return FALSE; /* Found ":t<endc>" or ":t:". */ 2590 return FALSE; /* Found ":t<endc>" or ":t:". */
2591 2591
2592 if (mod[1] == 's') 2592 if (mod[1] == 's')
2593 return ApplyModifier_ToSep(mod + 2, st); 2593 return ApplyModifier_ToSep(mod + 2, st);
2594 2594
2595 if (mod[2] != st->endc && mod[2] != ':') 2595 if (mod[2] != st->endc && mod[2] != ':')
2596 return FALSE; /* Found ":t<unrecognised><unrecognised>". */ 2596 return FALSE; /* Found ":t<unrecognised><unrecognised>". */
2597 2597
2598 /* Check for two-character options: ":tu", ":tl" */ 2598 /* Check for two-character options: ":tu", ":tl" */
2599 if (mod[1] == 'A') { /* absolute path */ 2599 if (mod[1] == 'A') { /* absolute path */
2600 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, 2600 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
2601 ModifyWord_Realpath, NULL); 2601 ModifyWord_Realpath, NULL);
2602 st->cp = mod + 2; 2602 st->next = mod + 2;
2603 st->termc = *st->cp; 2603 st->termc = *st->next;
2604 } else if (mod[1] == 'u') { 2604 } else if (mod[1] == 'u') {
2605 char *dp = bmake_strdup(st->nstr); 2605 char *dp = bmake_strdup(st->nstr);
2606 for (st->newStr = dp; *dp; dp++) 2606 for (st->newStr = dp; *dp; dp++)
2607 *dp = toupper((unsigned char)*dp); 2607 *dp = toupper((unsigned char)*dp);
2608 st->cp = mod + 2; 2608 st->next = mod + 2;
2609 st->termc = *st->cp; 2609 st->termc = *st->next;
2610 } else if (mod[1] == 'l') { 2610 } else if (mod[1] == 'l') {
2611 char *dp = bmake_strdup(st->nstr); 2611 char *dp = bmake_strdup(st->nstr);
2612 for (st->newStr = dp; *dp; dp++) 2612 for (st->newStr = dp; *dp; dp++)
2613 *dp = tolower((unsigned char)*dp); 2613 *dp = tolower((unsigned char)*dp);
2614 st->cp = mod + 2; 2614 st->next = mod + 2;
2615 st->termc = *st->cp; 2615 st->termc = *st->next;
2616 } else if (mod[1] == 'W' || mod[1] == 'w') { 2616 } else if (mod[1] == 'W' || mod[1] == 'w') {
2617 st->oneBigWord = mod[1] == 'W'; 2617 st->oneBigWord = mod[1] == 'W';
2618 st->newStr = st->nstr; 2618 st->newStr = st->nstr;
2619 st->cp = mod + 2; 2619 st->next = mod + 2;
2620 st->termc = *st->cp; 2620 st->termc = *st->next;
2621 } else { 2621 } else {
2622 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */ 2622 /* Found ":t<unrecognised>:" or ":t<unrecognised><endc>". */
2623 return FALSE; 2623 return FALSE;
2624 } 2624 }
2625 return TRUE; 2625 return TRUE;
2626} 2626}
2627 2627
2628/* :[#], :[1], etc. */ 2628/* :[#], :[1], etc. */
2629static int 2629static int
2630ApplyModifier_Words(const char *mod, ApplyModifiersState *st) 2630ApplyModifier_Words(const char *mod, ApplyModifiersState *st)
2631{ 2631{
2632 st->cp = mod + 1; /* point to char after '[' */ 2632 st->next = mod + 1; /* point to char after '[' */
2633 char delim = ']'; /* look for closing ']' */ 2633 char delim = ']'; /* look for closing ']' */
2634 char *estr = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2634 char *estr = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2635 NULL, NULL, NULL); 2635 NULL, NULL, NULL);
2636 if (estr == NULL) { 2636 if (estr == NULL) {
2637 st->missing_delim = delim; 2637 st->missing_delim = delim;
2638 return 'c'; 2638 return 'c';
2639 } 2639 }
2640 2640
2641 /* now st->cp points just after the closing ']' */ 2641 /* now st->next points just after the closing ']' */
2642 if (st->cp[0] != ':' && st->cp[0] != st->endc) 2642 if (st->next[0] != ':' && st->next[0] != st->endc)
2643 goto bad_modifier; /* Found junk after ']' */ 2643 goto bad_modifier; /* Found junk after ']' */
2644 2644
2645 if (estr[0] == '\0') 2645 if (estr[0] == '\0')
2646 goto bad_modifier; /* empty square brackets in ":[]". */ 2646 goto bad_modifier; /* empty square brackets in ":[]". */
2647 2647
2648 if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ 2648 if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */
2649 if (st->oneBigWord) { 2649 if (st->oneBigWord) {
2650 st->newStr = bmake_strdup("1"); 2650 st->newStr = bmake_strdup("1");
2651 } else { 2651 } else {
2652 /* XXX: brk_string() is a rather expensive 2652 /* XXX: brk_string() is a rather expensive
2653 * way of counting words. */ 2653 * way of counting words. */
2654 char *as; 2654 char *as;
2655 int ac; 2655 int ac;
@@ -2709,92 +2709,92 @@ ApplyModifier_Words(const char *mod, App @@ -2709,92 +2709,92 @@ ApplyModifier_Words(const char *mod, App
2709 st->oneBigWord = TRUE; 2709 st->oneBigWord = TRUE;
2710 st->newStr = st->nstr; 2710 st->newStr = st->nstr;
2711 goto ok; 2711 goto ok;
2712 } 2712 }
2713 2713
2714 /* ":[0..N]" or ":[N..0]" */ 2714 /* ":[0..N]" or ":[N..0]" */
2715 if (first == 0 || last == 0) 2715 if (first == 0 || last == 0)
2716 goto bad_modifier; 2716 goto bad_modifier;
2717 2717
2718 /* Normal case: select the words described by seldata. */ 2718 /* Normal case: select the words described by seldata. */
2719 st->newStr = VarSelectWords(st->sep, st->oneBigWord, st->nstr, first, last); 2719 st->newStr = VarSelectWords(st->sep, st->oneBigWord, st->nstr, first, last);
2720 2720
2721ok: 2721ok:
2722 st->termc = *st->cp; 2722 st->termc = *st->next;
2723 free(estr); 2723 free(estr);
2724 return 0; 2724 return 0;
2725 2725
2726bad_modifier: 2726bad_modifier:
2727 free(estr); 2727 free(estr);
2728 return 'b'; 2728 return 'b';
2729} 2729}
2730 2730
2731/* :O or :Ox */ 2731/* :O or :Ox */
2732static Boolean 2732static Boolean
2733ApplyModifier_Order(const char *mod, ApplyModifiersState *st) 2733ApplyModifier_Order(const char *mod, ApplyModifiersState *st)
2734{ 2734{
2735 char otype; 2735 char otype;
2736 2736
2737 st->cp = mod + 1; /* skip to the rest in any case */ 2737 st->next = mod + 1; /* skip to the rest in any case */
2738 if (mod[1] == st->endc || mod[1] == ':') { 2738 if (mod[1] == st->endc || mod[1] == ':') {
2739 otype = 's'; 2739 otype = 's';
2740 st->termc = *st->cp; 2740 st->termc = *st->next;
2741 } else if ((mod[1] == 'r' || mod[1] == 'x') && 2741 } else if ((mod[1] == 'r' || mod[1] == 'x') &&
2742 (mod[2] == st->endc || mod[2] == ':')) { 2742 (mod[2] == st->endc || mod[2] == ':')) {
2743 otype = mod[1]; 2743 otype = mod[1];
2744 st->cp = mod + 2; 2744 st->next = mod + 2;
2745 st->termc = *st->cp; 2745 st->termc = *st->next;
2746 } else { 2746 } else {
2747 return FALSE; 2747 return FALSE;
2748 } 2748 }
2749 st->newStr = VarOrder(st->nstr, otype); 2749 st->newStr = VarOrder(st->nstr, otype);
2750 return TRUE; 2750 return TRUE;
2751} 2751}
2752 2752
2753/* :? then : else */ 2753/* :? then : else */
2754static Boolean 2754static Boolean
2755ApplyModifier_IfElse(const char *mod, ApplyModifiersState *st) 2755ApplyModifier_IfElse(const char *mod, ApplyModifiersState *st)
2756{ 2756{
2757 Boolean value = FALSE; 2757 Boolean value = FALSE;
2758 int cond_rc = 0; 2758 int cond_rc = 0;
2759 VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES; 2759 VarEvalFlags then_eflags = st->eflags & ~VARE_WANTRES;
2760 VarEvalFlags else_eflags = st->eflags & ~VARE_WANTRES; 2760 VarEvalFlags else_eflags = st->eflags & ~VARE_WANTRES;
2761 2761
2762 if (st->eflags & VARE_WANTRES) { 2762 if (st->eflags & VARE_WANTRES) {
2763 cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE); 2763 cond_rc = Cond_EvalExpression(NULL, st->v->name, &value, 0, FALSE);
2764 if (cond_rc != COND_INVALID && value) 2764 if (cond_rc != COND_INVALID && value)
2765 then_eflags |= VARE_WANTRES; 2765 then_eflags |= VARE_WANTRES;
2766 if (cond_rc != COND_INVALID && !value) 2766 if (cond_rc != COND_INVALID && !value)
2767 else_eflags |= VARE_WANTRES; 2767 else_eflags |= VARE_WANTRES;
2768 } 2768 }
2769 2769
2770 st->cp = mod + 1; 2770 st->next = mod + 1;
2771 char delim = ':'; 2771 char delim = ':';
2772 char *then_expr = ParseModifierPart(&st->cp, delim, then_eflags, st->ctxt, 2772 char *then_expr = ParseModifierPart(&st->next, delim, then_eflags, st->ctxt,
2773 NULL, NULL, NULL); 2773 NULL, NULL, NULL);
2774 if (then_expr == NULL) { 2774 if (then_expr == NULL) {
2775 st->missing_delim = delim; 2775 st->missing_delim = delim;
2776 return FALSE; 2776 return FALSE;
2777 } 2777 }
2778 2778
2779 delim = st->endc; /* BRCLOSE or PRCLOSE */ 2779 delim = st->endc; /* BRCLOSE or PRCLOSE */
2780 char *else_expr = ParseModifierPart(&st->cp, delim, else_eflags, st->ctxt, 2780 char *else_expr = ParseModifierPart(&st->next, delim, else_eflags, st->ctxt,
2781 NULL, NULL, NULL); 2781 NULL, NULL, NULL);
2782 if (else_expr == NULL) { 2782 if (else_expr == NULL) {
2783 st->missing_delim = delim; 2783 st->missing_delim = delim;
2784 return FALSE; 2784 return FALSE;
2785 } 2785 }
2786 2786
2787 st->termc = *--st->cp; 2787 st->termc = *--st->next;
2788 if (cond_rc == COND_INVALID) { 2788 if (cond_rc == COND_INVALID) {
2789 Error("Bad conditional expression `%s' in %s?%s:%s", 2789 Error("Bad conditional expression `%s' in %s?%s:%s",
2790 st->v->name, st->v->name, then_expr, else_expr); 2790 st->v->name, st->v->name, then_expr, else_expr);
2791 return FALSE; 2791 return FALSE;
2792 } 2792 }
2793 2793
2794 if (value) { 2794 if (value) {
2795 st->newStr = then_expr; 2795 st->newStr = then_expr;
2796 free(else_expr); 2796 free(else_expr);
2797 } else { 2797 } else {
2798 st->newStr = else_expr; 2798 st->newStr = else_expr;
2799 free(then_expr); 2799 free(then_expr);
2800 } 2800 }
@@ -2848,47 +2848,47 @@ ApplyModifier_Assign(const char *mod, Ap @@ -2848,47 +2848,47 @@ ApplyModifier_Assign(const char *mod, Ap
2848 st->v->name = bmake_strdup(st->v->name); 2848 st->v->name = bmake_strdup(st->v->name);
2849 } else if (st->ctxt != VAR_GLOBAL) { 2849 } else if (st->ctxt != VAR_GLOBAL) {
2850 Var *gv = VarFind(st->v->name, st->ctxt, 0); 2850 Var *gv = VarFind(st->v->name, st->ctxt, 0);
2851 if (gv == NULL) 2851 if (gv == NULL)
2852 v_ctxt = VAR_GLOBAL; 2852 v_ctxt = VAR_GLOBAL;
2853 else 2853 else
2854 VarFreeEnv(gv, TRUE); 2854 VarFreeEnv(gv, TRUE);
2855 } 2855 }
2856 2856
2857 switch (op[0]) { 2857 switch (op[0]) {
2858 case '+': 2858 case '+':
2859 case '?': 2859 case '?':
2860 case '!': 2860 case '!':
2861 st->cp = mod + 3; 2861 st->next = mod + 3;
2862 break; 2862 break;
2863 default: 2863 default:
2864 st->cp = mod + 2; 2864 st->next = mod + 2;
2865 break; 2865 break;
2866 } 2866 }
2867 2867
2868 char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE; 2868 char delim = st->startc == PROPEN ? PRCLOSE : BRCLOSE;
2869 char *val = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2869 char *val = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2870 NULL, NULL, NULL); 2870 NULL, NULL, NULL);
2871 if (st->v->flags & VAR_JUNK) { 2871 if (st->v->flags & VAR_JUNK) {
2872 /* restore original name */ 2872 /* restore original name */
2873 free(st->v->name); 2873 free(st->v->name);
2874 st->v->name = sv_name; 2874 st->v->name = sv_name;
2875 } 2875 }
2876 if (val == NULL) { 2876 if (val == NULL) {
2877 st->missing_delim = delim; 2877 st->missing_delim = delim;
2878 return 'c'; 2878 return 'c';
2879 } 2879 }
2880 2880
2881 st->termc = *--st->cp; 2881 st->termc = *--st->next;
2882 2882
2883 if (st->eflags & VARE_WANTRES) { 2883 if (st->eflags & VARE_WANTRES) {
2884 switch (op[0]) { 2884 switch (op[0]) {
2885 case '+': 2885 case '+':
2886 Var_Append(st->v->name, val, v_ctxt); 2886 Var_Append(st->v->name, val, v_ctxt);
2887 break; 2887 break;
2888 case '!': { 2888 case '!': {
2889 const char *emsg; 2889 const char *emsg;
2890 st->newStr = Cmd_Exec(val, &emsg); 2890 st->newStr = Cmd_Exec(val, &emsg);
2891 if (emsg) 2891 if (emsg)
2892 Error(emsg, st->nstr); 2892 Error(emsg, st->nstr);
2893 else 2893 else
2894 Var_Set(st->v->name, st->newStr, v_ctxt); 2894 Var_Set(st->v->name, st->newStr, v_ctxt);
@@ -2904,95 +2904,95 @@ ApplyModifier_Assign(const char *mod, Ap @@ -2904,95 +2904,95 @@ ApplyModifier_Assign(const char *mod, Ap
2904 break; 2904 break;
2905 } 2905 }
2906 } 2906 }
2907 free(val); 2907 free(val);
2908 st->newStr = varNoError; 2908 st->newStr = varNoError;
2909 return 0; 2909 return 0;
2910} 2910}
2911 2911
2912/* remember current value */ 2912/* remember current value */
2913static Boolean 2913static Boolean
2914ApplyModifier_Remember(const char *mod, ApplyModifiersState *st) 2914ApplyModifier_Remember(const char *mod, ApplyModifiersState *st)
2915{ 2915{
2916 if (!ModMatchEq(mod, "_", st->endc)) { 2916 if (!ModMatchEq(mod, "_", st->endc)) {
2917 st->cp = mod + 1; 2917 st->next = mod + 1;
2918 return FALSE; 2918 return FALSE;
2919 } 2919 }
2920 2920
2921 if (mod[1] == '=') { 2921 if (mod[1] == '=') {
2922 size_t n = strcspn(mod + 2, ":)}"); 2922 size_t n = strcspn(mod + 2, ":)}");
2923 char *name = bmake_strndup(mod + 2, n); 2923 char *name = bmake_strndup(mod + 2, n);
2924 Var_Set(name, st->nstr, st->ctxt); 2924 Var_Set(name, st->nstr, st->ctxt);
2925 free(name); 2925 free(name);
2926 st->cp = mod + 2 + n; 2926 st->next = mod + 2 + n;
2927 } else { 2927 } else {
2928 Var_Set("_", st->nstr, st->ctxt); 2928 Var_Set("_", st->nstr, st->ctxt);
2929 st->cp = mod + 1; 2929 st->next = mod + 1;
2930 } 2930 }
2931 st->newStr = st->nstr; 2931 st->newStr = st->nstr;
2932 st->termc = *st->cp; 2932 st->termc = *st->next;
2933 return TRUE; 2933 return TRUE;
2934} 2934}
2935 2935
2936#ifdef SYSVVARSUB 2936#ifdef SYSVVARSUB
2937/* :from=to */ 2937/* :from=to */
2938static int 2938static int
2939ApplyModifier_SysV(const char *mod, ApplyModifiersState *st) 2939ApplyModifier_SysV(const char *mod, ApplyModifiersState *st)
2940{ 2940{
2941 Boolean eqFound = FALSE; 2941 Boolean eqFound = FALSE;
2942 2942
2943 /* 2943 /*
2944 * First we make a pass through the string trying 2944 * First we make a pass through the string trying
2945 * to verify it is a SYSV-make-style translation: 2945 * to verify it is a SYSV-make-style translation:
2946 * it must be: <string1>=<string2>) 2946 * it must be: <string1>=<string2>)
2947 */ 2947 */
2948 st->cp = mod; 2948 st->next = mod;
2949 int nest = 1; 2949 int nest = 1;
2950 while (*st->cp != '\0' && nest > 0) { 2950 while (*st->next != '\0' && nest > 0) {
2951 if (*st->cp == '=') { 2951 if (*st->next == '=') {
2952 eqFound = TRUE; 2952 eqFound = TRUE;
2953 /* continue looking for st->endc */ 2953 /* continue looking for st->endc */
2954 } else if (*st->cp == st->endc) 2954 } else if (*st->next == st->endc)
2955 nest--; 2955 nest--;
2956 else if (*st->cp == st->startc) 2956 else if (*st->next == st->startc)
2957 nest++; 2957 nest++;
2958 if (nest > 0) 2958 if (nest > 0)
2959 st->cp++; 2959 st->next++;
2960 } 2960 }
2961 if (*st->cp != st->endc || !eqFound) 2961 if (*st->next != st->endc || !eqFound)
2962 return 0; 2962 return 0;
2963 2963
2964 char delim = '='; 2964 char delim = '=';
2965 st->cp = mod; 2965 st->next = mod;
2966 char *lhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2966 char *lhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2967 NULL, NULL, NULL); 2967 NULL, NULL, NULL);
2968 if (lhs == NULL) { 2968 if (lhs == NULL) {
2969 st->missing_delim = delim; 2969 st->missing_delim = delim;
2970 return 'c'; 2970 return 'c';
2971 } 2971 }
2972 2972
2973 delim = st->endc; 2973 delim = st->endc;
2974 char *rhs = ParseModifierPart(&st->cp, delim, st->eflags, st->ctxt, 2974 char *rhs = ParseModifierPart(&st->next, delim, st->eflags, st->ctxt,
2975 NULL, NULL, NULL); 2975 NULL, NULL, NULL);
2976 if (rhs == NULL) { 2976 if (rhs == NULL) {
2977 st->missing_delim = delim; 2977 st->missing_delim = delim;
2978 return 'c'; 2978 return 'c';
2979 } 2979 }
2980 2980
2981 /* 2981 /*
2982 * SYSV modifications happen through the whole 2982 * SYSV modifications happen through the whole
2983 * string. Note the pattern is anchored at the end. 2983 * string. Note the pattern is anchored at the end.
2984 */ 2984 */
2985 st->termc = *--st->cp; 2985 st->termc = *--st->next;
2986 if (lhs[0] == '\0' && *st->nstr == '\0') { 2986 if (lhs[0] == '\0' && *st->nstr == '\0') {
2987 st->newStr = st->nstr; /* special case */ 2987 st->newStr = st->nstr; /* special case */
2988 } else { 2988 } else {
2989 ModifyWord_SYSVSubstArgs args = { st->ctxt, lhs, rhs }; 2989 ModifyWord_SYSVSubstArgs args = { st->ctxt, lhs, rhs };
2990 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr, 2990 st->newStr = ModifyWords(st->ctxt, st->sep, st->oneBigWord, st->nstr,
2991 ModifyWord_SYSVSubst, &args); 2991 ModifyWord_SYSVSubst, &args);
2992 } 2992 }
2993 free(lhs); 2993 free(lhs);
2994 free(rhs); 2994 free(rhs);
2995 return '='; 2995 return '=';
2996} 2996}
2997#endif 2997#endif
2998 2998
@@ -3154,28 +3154,28 @@ ApplyModifiers(char *nstr, const char *  @@ -3154,28 +3154,28 @@ ApplyModifiers(char *nstr, const char *
3154 case '_': 3154 case '_':
3155 if (!ApplyModifier_Remember(p, &st)) 3155 if (!ApplyModifier_Remember(p, &st))
3156 goto default_case; 3156 goto default_case;
3157 break; 3157 break;
3158 case 'D': 3158 case 'D':
3159 case 'U': 3159 case 'U':
3160 ApplyModifier_Defined(p, &st); 3160 ApplyModifier_Defined(p, &st);
3161 break; 3161 break;
3162 case 'L': 3162 case 'L':
3163 { 3163 {
3164 if (st.v->flags & VAR_JUNK) 3164 if (st.v->flags & VAR_JUNK)
3165 st.v->flags |= VAR_KEEP; 3165 st.v->flags |= VAR_KEEP;
3166 st.newStr = bmake_strdup(st.v->name); 3166 st.newStr = bmake_strdup(st.v->name);
3167 st.cp = p + 1; 3167 st.next = p + 1;
3168 st.termc = *st.cp; 3168 st.termc = *st.next;
3169 break; 3169 break;
3170 } 3170 }
3171 case 'P': 3171 case 'P':
3172 ApplyModifier_Path(p, &st); 3172 ApplyModifier_Path(p, &st);
3173 break; 3173 break;
3174 case '!': 3174 case '!':
3175 if (!ApplyModifier_Exclam(p, &st)) 3175 if (!ApplyModifier_Exclam(p, &st))
3176 goto cleanup; 3176 goto cleanup;
3177 break; 3177 break;
3178 case '[': 3178 case '[':
3179 { 3179 {
3180 int res = ApplyModifier_Words(p, &st); 3180 int res = ApplyModifier_Words(p, &st);
3181 if (res == 'b') 3181 if (res == 'b')
@@ -3212,153 +3212,154 @@ ApplyModifiers(char *nstr, const char *  @@ -3212,153 +3212,154 @@ ApplyModifiers(char *nstr, const char *
3212 if (!ApplyModifier_IfElse(p, &st)) 3212 if (!ApplyModifier_IfElse(p, &st))
3213 goto cleanup; 3213 goto cleanup;
3214 break; 3214 break;
3215#ifndef NO_REGEX 3215#ifndef NO_REGEX
3216 case 'C': 3216 case 'C':
3217 if (!ApplyModifier_Regex(p, &st)) 3217 if (!ApplyModifier_Regex(p, &st))
3218 goto cleanup; 3218 goto cleanup;
3219 break; 3219 break;
3220#endif 3220#endif
3221 case 'q': 3221 case 'q':
3222 case 'Q': 3222 case 'Q':
3223 if (p[1] == st.endc || p[1] == ':') { 3223 if (p[1] == st.endc || p[1] == ':') {
3224 st.newStr = VarQuote(st.nstr, modifier == 'q'); 3224 st.newStr = VarQuote(st.nstr, modifier == 'q');
3225 st.cp = p + 1; 3225 st.next = p + 1;
3226 st.termc = *st.cp; 3226 st.termc = *st.next;
3227 break; 3227 break;
3228 } 3228 }
3229 goto default_case; 3229 goto default_case;
3230 case 'T': 3230 case 'T':
3231 if (p[1] == st.endc || p[1] == ':') { 3231 if (p[1] == st.endc || p[1] == ':') {
3232 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord, 3232 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
3233 st.nstr, ModifyWord_Tail, NULL); 3233 st.nstr, ModifyWord_Tail, NULL);
3234 st.cp = p + 1; 3234 st.next = p + 1;
3235 st.termc = *st.cp; 3235 st.termc = *st.next;
3236 break; 3236 break;
3237 } 3237 }
3238 goto default_case; 3238 goto default_case;
3239 case 'H': 3239 case 'H':
3240 if (p[1] == st.endc || p[1] == ':') { 3240 if (p[1] == st.endc || p[1] == ':') {
3241 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord, 3241 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
3242 st.nstr, ModifyWord_Head, NULL); 3242 st.nstr, ModifyWord_Head, NULL);
3243 st.cp = p + 1; 3243 st.next = p + 1;
3244 st.termc = *st.cp; 3244 st.termc = *st.next;
3245 break; 3245 break;
3246 } 3246 }
3247 goto default_case; 3247 goto default_case;
3248 case 'E': 3248 case 'E':
3249 if (p[1] == st.endc || p[1] == ':') { 3249 if (p[1] == st.endc || p[1] == ':') {
3250 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord, 3250 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
3251 st.nstr, ModifyWord_Suffix, NULL); 3251 st.nstr, ModifyWord_Suffix, NULL);
3252 st.cp = p + 1; 3252 st.next = p + 1;
3253 st.termc = *st.cp; 3253 st.termc = *st.next;
3254 break; 3254 break;
3255 } 3255 }
3256 goto default_case; 3256 goto default_case;
3257 case 'R': 3257 case 'R':
3258 if (p[1] == st.endc || p[1] == ':') { 3258 if (p[1] == st.endc || p[1] == ':') {
3259 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord, 3259 st.newStr = ModifyWords(st.ctxt, st.sep, st.oneBigWord,
3260 st.nstr, ModifyWord_Root, NULL); 3260 st.nstr, ModifyWord_Root, NULL);
3261 st.cp = p + 1; 3261 st.next = p + 1;
3262 st.termc = *st.cp; 3262 st.termc = *st.next;
3263 break; 3263 break;
3264 } 3264 }
3265 goto default_case; 3265 goto default_case;
3266 case 'r': 3266 case 'r':
3267 if (!ApplyModifier_Range(p, &st)) 3267 if (!ApplyModifier_Range(p, &st))
3268 goto default_case; 3268 goto default_case;
3269 break; 3269 break;
3270 case 'O': 3270 case 'O':
3271 if (!ApplyModifier_Order(p, &st)) 3271 if (!ApplyModifier_Order(p, &st))
3272 goto bad_modifier; 3272 goto bad_modifier;
3273 break; 3273 break;
3274 case 'u': 3274 case 'u':
3275 if (p[1] == st.endc || p[1] == ':') { 3275 if (p[1] == st.endc || p[1] == ':') {
3276 st.newStr = VarUniq(st.nstr); 3276 st.newStr = VarUniq(st.nstr);
3277 st.cp = p + 1; 3277 st.next = p + 1;
3278 st.termc = *st.cp; 3278 st.termc = *st.next;
3279 break; 3279 break;
3280 } 3280 }
3281 goto default_case; 3281 goto default_case;
3282#ifdef SUNSHCMD 3282#ifdef SUNSHCMD
3283 case 's': 3283 case 's':
3284 if (p[1] == 'h' && (p[2] == st.endc || p[2] == ':')) { 3284 if (p[1] == 'h' && (p[2] == st.endc || p[2] == ':')) {
3285 const char *emsg; 3285 const char *emsg;
3286 if (st.eflags & VARE_WANTRES) { 3286 if (st.eflags & VARE_WANTRES) {
3287 st.newStr = Cmd_Exec(st.nstr, &emsg); 3287 st.newStr = Cmd_Exec(st.nstr, &emsg);
3288 if (emsg) 3288 if (emsg)
3289 Error(emsg, st.nstr); 3289 Error(emsg, st.nstr);
3290 } else 3290 } else
3291 st.newStr = varNoError; 3291 st.newStr = varNoError;
3292 st.cp = p + 2; 3292 st.next = p + 2;
3293 st.termc = *st.cp; 3293 st.termc = *st.next;
3294 break; 3294 break;
3295 } 3295 }
3296 goto default_case; 3296 goto default_case;
3297#endif 3297#endif
3298 default: 3298 default:
3299 default_case: 3299 default_case:
3300 { 3300 {
3301#ifdef SYSVVARSUB 3301#ifdef SYSVVARSUB
3302 int res = ApplyModifier_SysV(p, &st); 3302 int res = ApplyModifier_SysV(p, &st);
3303 if (res == 'c') 3303 if (res == 'c')
3304 goto cleanup; 3304 goto cleanup;
3305 if (res != '=') 3305 if (res != '=')
3306#endif 3306#endif
3307 { 3307 {
3308 Error("Unknown modifier '%c'", *p); 3308 Error("Unknown modifier '%c'", *p);
3309 for (st.cp = p + 1; 3309 for (st.next = p + 1;
3310 *st.cp != ':' && *st.cp != st.endc && *st.cp != '\0'; 3310 *st.next != ':' && *st.next != st.endc &&
3311 st.cp++) 3311 *st.next != '\0';
 3312 st.next++)
3312 continue; 3313 continue;
3313 st.termc = *st.cp; 3314 st.termc = *st.next;
3314 st.newStr = var_Error; 3315 st.newStr = var_Error;
3315 } 3316 }
3316 } 3317 }
3317 } 3318 }
3318 if (DEBUG(VAR)) { 3319 if (DEBUG(VAR)) {
3319 fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n", 3320 fprintf(debug_file, "Result[%s] of :%c is \"%s\"\n",
3320 st.v->name, modifier, st.newStr); 3321 st.v->name, modifier, st.newStr);
3321 } 3322 }
3322 3323
3323 if (st.newStr != st.nstr) { 3324 if (st.newStr != st.nstr) {
3324 if (*freePtr) { 3325 if (*freePtr) {
3325 free(st.nstr); 3326 free(st.nstr);
3326 *freePtr = NULL; 3327 *freePtr = NULL;
3327 } 3328 }
3328 st.nstr = st.newStr; 3329 st.nstr = st.newStr;
3329 if (st.nstr != var_Error && st.nstr != varNoError) { 3330 if (st.nstr != var_Error && st.nstr != varNoError) {
3330 *freePtr = st.nstr; 3331 *freePtr = st.nstr;
3331 } 3332 }
3332 } 3333 }
3333 if (st.termc == '\0' && st.endc != '\0') { 3334 if (st.termc == '\0' && st.endc != '\0') {
3334 Error("Unclosed variable specification (expecting '%c') " 3335 Error("Unclosed variable specification (expecting '%c') "
3335 "for \"%s\" (value \"%s\") modifier %c", 3336 "for \"%s\" (value \"%s\") modifier %c",
3336 st.endc, st.v->name, st.nstr, modifier); 3337 st.endc, st.v->name, st.nstr, modifier);
3337 } else if (st.termc == ':') { 3338 } else if (st.termc == ':') {
3338 st.cp++; 3339 st.next++;
3339 } 3340 }
3340 p = st.cp; 3341 p = st.next;
3341 } 3342 }
3342out: 3343out:
3343 *lengthPtr = p - tstr; 3344 *lengthPtr = p - tstr;
3344 return st.nstr; 3345 return st.nstr;
3345 3346
3346bad_modifier: 3347bad_modifier:
3347 Error("Bad modifier `:%.*s' for %s", 3348 Error("Bad modifier `:%.*s' for %s",
3348 (int)strcspn(p, ":)}"), p, st.v->name); 3349 (int)strcspn(p, ":)}"), p, st.v->name);
3349 3350
3350cleanup: 3351cleanup:
3351 *lengthPtr = st.cp - tstr; 3352 *lengthPtr = st.next - tstr;
3352 if (st.missing_delim != '\0') 3353 if (st.missing_delim != '\0')
3353 Error("Unclosed substitution for %s (%c missing)", 3354 Error("Unclosed substitution for %s (%c missing)",
3354 st.v->name, st.missing_delim); 3355 st.v->name, st.missing_delim);
3355 free(*freePtr); 3356 free(*freePtr);
3356 *freePtr = NULL; 3357 *freePtr = NULL;
3357 return var_Error; 3358 return var_Error;
3358} 3359}
3359 3360
3360static Boolean 3361static Boolean
3361VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen) 3362VarIsDynamic(GNode *ctxt, const char *varname, size_t namelen)
3362{ 3363{
3363 if ((namelen == 1 || 3364 if ((namelen == 1 ||
3364 (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) && 3365 (namelen == 2 && (varname[1] == 'F' || varname[1] == 'D'))) &&