Sun Jul 26 15:26:27 2020 UTC ()
make(1): add convenience functions for adding to a SepBuf


(rillig)
diff -r1.313 -r1.314 src/usr.bin/make/var.c

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

--- src/usr.bin/make/var.c 2020/07/26 15:09:10 1.313
+++ src/usr.bin/make/var.c 2020/07/26 15:26:27 1.314
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.313 2020/07/26 15:09:10 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.314 2020/07/26 15:26:27 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.313 2020/07/26 15:09:10 rillig Exp $"; 72static char rcsid[] = "$NetBSD: var.c,v 1.314 2020/07/26 15:26:27 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.313 2020/07/26 15:09:10 rillig Exp $"); 79__RCSID("$NetBSD: var.c,v 1.314 2020/07/26 15:26:27 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 *
@@ -1049,112 +1049,124 @@ SepBuf_Init(SepBuf *buf, char sep) @@ -1049,112 +1049,124 @@ SepBuf_Init(SepBuf *buf, char sep)
1049{ 1049{
1050 Buf_Init(&buf->buf, 32 /* bytes */); 1050 Buf_Init(&buf->buf, 32 /* bytes */);
1051 buf->needSep = FALSE; 1051 buf->needSep = FALSE;
1052 buf->sep = sep; 1052 buf->sep = sep;
1053} 1053}
1054 1054
1055static void 1055static void
1056SepBuf_Sep(SepBuf *buf) 1056SepBuf_Sep(SepBuf *buf)
1057{ 1057{
1058 buf->needSep = TRUE; 1058 buf->needSep = TRUE;
1059} 1059}
1060 1060
1061static void 1061static void
1062SepBuf_AddBytes(SepBuf *buf, const void *mem, size_t mem_size) 1062SepBuf_AddBytes(SepBuf *buf, const char *mem, size_t mem_size)
1063{ 1063{
1064 if (mem_size == 0) 1064 if (mem_size == 0)
1065 return; 1065 return;
1066 if (buf->needSep && buf->sep != '\0') { 1066 if (buf->needSep && buf->sep != '\0') {
1067 Buf_AddByte(&buf->buf, buf->sep); 1067 Buf_AddByte(&buf->buf, buf->sep);
1068 buf->needSep = FALSE; 1068 buf->needSep = FALSE;
1069 } 1069 }
1070 Buf_AddBytes(&buf->buf, mem_size, mem); 1070 Buf_AddBytes(&buf->buf, mem_size, mem);
1071} 1071}
1072 1072
 1073static void
 1074SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end)
 1075{
 1076 SepBuf_AddBytes(buf, start, (size_t)(end - start));
 1077}
 1078
 1079static void
 1080SepBuf_AddStr(SepBuf *buf, const char *str)
 1081{
 1082 SepBuf_AddBytes(buf, str, strlen(str));
 1083}
 1084
1073static char * 1085static char *
1074SepBuf_Destroy(SepBuf *buf, Boolean free_buf) 1086SepBuf_Destroy(SepBuf *buf, Boolean free_buf)
1075{ 1087{
1076 return Buf_Destroy(&buf->buf, free_buf); 1088 return Buf_Destroy(&buf->buf, free_buf);
1077} 1089}
1078 1090
1079 1091
1080/* This callback for ModifyWords gets a single word from an expression and 1092/* This callback for ModifyWords gets a single word from an expression and
1081 * typically adds a modification of this word to the buffer. It may also do 1093 * typically adds a modification of this word to the buffer. It may also do
1082 * nothing or add several words. */ 1094 * nothing or add several words. */
1083typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data); 1095typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data);
1084 1096
1085 1097
1086/* Callback for ModifyWords to implement the :H modifier. 1098/* Callback for ModifyWords to implement the :H modifier.
1087 * Add the dirname of the given word to the buffer. */ 1099 * Add the dirname of the given word to the buffer. */
1088static void 1100static void
1089ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1101ModifyWord_Head(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1090{ 1102{
1091 const char *slash = strrchr(word, '/'); 1103 const char *slash = strrchr(word, '/');
1092 if (slash != NULL) 1104 if (slash != NULL)
1093 SepBuf_AddBytes(buf, word, slash - word); 1105 SepBuf_AddBytesBetween(buf, word, slash);
1094 else 1106 else
1095 SepBuf_AddBytes(buf, ".", 1); 1107 SepBuf_AddStr(buf, ".");
1096} 1108}
1097 1109
1098/* Callback for ModifyWords to implement the :T modifier. 1110/* Callback for ModifyWords to implement the :T modifier.
1099 * Add the basename of the given word to the buffer. */ 1111 * Add the basename of the given word to the buffer. */
1100static void 1112static void
1101ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1113ModifyWord_Tail(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1102{ 1114{
1103 const char *slash = strrchr(word, '/'); 1115 const char *slash = strrchr(word, '/');
1104 const char *base = slash != NULL ? slash + 1 : word; 1116 const char *base = slash != NULL ? slash + 1 : word;
1105 SepBuf_AddBytes(buf, base, strlen(base)); 1117 SepBuf_AddStr(buf, base);
1106} 1118}
1107 1119
1108/* Callback for ModifyWords to implement the :E modifier. 1120/* Callback for ModifyWords to implement the :E modifier.
1109 * Add the filename suffix of the given word to the buffer, if it exists. */ 1121 * Add the filename suffix of the given word to the buffer, if it exists. */
1110static void 1122static void
1111ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1123ModifyWord_Suffix(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1112{ 1124{
1113 const char *dot = strrchr(word, '.'); 1125 const char *dot = strrchr(word, '.');
1114 if (dot != NULL) 1126 if (dot != NULL)
1115 SepBuf_AddBytes(buf, dot + 1, strlen(dot + 1)); 1127 SepBuf_AddStr(buf, dot + 1);
1116} 1128}
1117 1129
1118/* Callback for ModifyWords to implement the :R modifier. 1130/* Callback for ModifyWords to implement the :R modifier.
1119 * Add the basename of the given word to the buffer. */ 1131 * Add the basename of the given word to the buffer. */
1120static void 1132static void
1121ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED) 1133ModifyWord_Root(const char *word, SepBuf *buf, void *dummy MAKE_ATTR_UNUSED)
1122{ 1134{
1123 char *dot = strrchr(word, '.'); 1135 const char *dot = strrchr(word, '.');
1124 size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word); 1136 size_t len = dot != NULL ? (size_t)(dot - word) : strlen(word);
1125 SepBuf_AddBytes(buf, word, len); 1137 SepBuf_AddBytes(buf, word, len);
1126} 1138}
1127 1139
1128/* Callback for ModifyWords to implement the :M modifier. 1140/* Callback for ModifyWords to implement the :M modifier.
1129 * Place the word in the buffer if it matches the given pattern. */ 1141 * Place the word in the buffer if it matches the given pattern. */
1130static void 1142static void
1131ModifyWord_Match(const char *word, SepBuf *buf, void *data) 1143ModifyWord_Match(const char *word, SepBuf *buf, void *data)
1132{ 1144{
1133 const char *pattern = data; 1145 const char *pattern = data;
1134 if (DEBUG(VAR)) 1146 if (DEBUG(VAR))
1135 fprintf(debug_file, "VarMatch [%s] [%s]\n", word, pattern); 1147 fprintf(debug_file, "VarMatch [%s] [%s]\n", word, pattern);
1136 if (Str_Match(word, pattern)) 1148 if (Str_Match(word, pattern))
1137 SepBuf_AddBytes(buf, word, strlen(word)); 1149 SepBuf_AddStr(buf, word);
1138} 1150}
1139 1151
1140/* Callback for ModifyWords to implement the :N modifier. 1152/* Callback for ModifyWords to implement the :N modifier.
1141 * Place the word in the buffer if it doesn't match the given pattern. */ 1153 * Place the word in the buffer if it doesn't match the given pattern. */
1142static void 1154static void
1143ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data) 1155ModifyWord_NoMatch(const char *word, SepBuf *buf, void *data)
1144{ 1156{
1145 const char *pattern = data; 1157 const char *pattern = data;
1146 if (!Str_Match(word, pattern)) 1158 if (!Str_Match(word, pattern))
1147 SepBuf_AddBytes(buf, word, strlen(word)); 1159 SepBuf_AddStr(buf, word);
1148} 1160}
1149 1161
1150#ifdef SYSVVARSUB 1162#ifdef SYSVVARSUB
1151/*- 1163/*-
1152 *----------------------------------------------------------------------- 1164 *-----------------------------------------------------------------------
1153 * Str_SYSVMatch -- 1165 * Str_SYSVMatch --
1154 * Check word against pattern for a match (% is wild), 1166 * Check word against pattern for a match (% is wild),
1155 * 1167 *
1156 * Input: 1168 * Input:
1157 * word Word to examine 1169 * word Word to examine
1158 * pattern Pattern to examine against 1170 * pattern Pattern to examine against
1159 * len Number of characters to substitute 1171 * len Number of characters to substitute
1160 * 1172 *
@@ -1221,61 +1233,61 @@ Str_SYSVMatch(const char *word, const ch @@ -1221,61 +1233,61 @@ Str_SYSVMatch(const char *word, const ch
1221 * 1233 *
1222 * Side Effects: 1234 * Side Effects:
1223 * Places result on buf 1235 * Places result on buf
1224 *----------------------------------------------------------------------- 1236 *-----------------------------------------------------------------------
1225 */ 1237 */
1226static void 1238static void
1227Str_SYSVSubst(SepBuf *buf, const char *pat, const char *src, size_t len, 1239Str_SYSVSubst(SepBuf *buf, const char *pat, const char *src, size_t len,
1228 Boolean lhsHasPercent) 1240 Boolean lhsHasPercent)
1229{ 1241{
1230 const char *m; 1242 const char *m;
1231 1243
1232 if ((m = strchr(pat, '%')) != NULL && lhsHasPercent) { 1244 if ((m = strchr(pat, '%')) != NULL && lhsHasPercent) {
1233 /* Copy the prefix */ 1245 /* Copy the prefix */
1234 SepBuf_AddBytes(buf, pat, m - pat); 1246 SepBuf_AddBytesBetween(buf, pat, m);
1235 /* skip the % */ 1247 /* skip the % */
1236 pat = m + 1; 1248 pat = m + 1;
1237 } 1249 }
1238 if (m != NULL || !lhsHasPercent) { 1250 if (m != NULL || !lhsHasPercent) {
1239 /* Copy the pattern */ 1251 /* Copy the pattern */
1240 SepBuf_AddBytes(buf, src, len); 1252 SepBuf_AddBytes(buf, src, len);
1241 } 1253 }
1242 1254
1243 /* append the rest */ 1255 /* append the rest */
1244 SepBuf_AddBytes(buf, pat, strlen(pat)); 1256 SepBuf_AddStr(buf, pat);
1245} 1257}
1246 1258
1247 1259
1248typedef struct { 1260typedef struct {
1249 GNode *ctx; 1261 GNode *ctx;
1250 const char *lhs; 1262 const char *lhs;
1251 const char *rhs; 1263 const char *rhs;
1252} ModifyWord_SYSVSubstArgs; 1264} ModifyWord_SYSVSubstArgs;
1253 1265
1254/* Callback for ModifyWords to implement the :%.from=%.to modifier. */ 1266/* Callback for ModifyWords to implement the :%.from=%.to modifier. */
1255static void 1267static void
1256ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data) 1268ModifyWord_SYSVSubst(const char *word, SepBuf *buf, void *data)
1257{ 1269{
1258 const ModifyWord_SYSVSubstArgs *args = data; 1270 const ModifyWord_SYSVSubstArgs *args = data;
1259 1271
1260 size_t len; 1272 size_t len;
1261 Boolean hasPercent; 1273 Boolean hasPercent;
1262 const char *ptr = Str_SYSVMatch(word, args->lhs, &len, &hasPercent); 1274 const char *ptr = Str_SYSVMatch(word, args->lhs, &len, &hasPercent);
1263 if (ptr != NULL) { 1275 if (ptr != NULL) {
1264 char *varexp = Var_Subst(NULL, args->rhs, args->ctx, VARE_WANTRES); 1276 char *varexp = Var_Subst(NULL, args->rhs, args->ctx, VARE_WANTRES);
1265 Str_SYSVSubst(buf, varexp, ptr, len, hasPercent); 1277 Str_SYSVSubst(buf, varexp, ptr, len, hasPercent);
1266 free(varexp); 1278 free(varexp);
1267 } else { 1279 } else {
1268 SepBuf_AddBytes(buf, word, strlen(word)); 1280 SepBuf_AddStr(buf, word);
1269 } 1281 }
1270} 1282}
1271#endif 1283#endif
1272 1284
1273 1285
1274typedef struct { 1286typedef struct {
1275 const char *lhs; 1287 const char *lhs;
1276 size_t lhsLen; 1288 size_t lhsLen;
1277 const char *rhs; 1289 const char *rhs;
1278 size_t rhsLen; 1290 size_t rhsLen;
1279 VarPatternFlags pflags; 1291 VarPatternFlags pflags;
1280} ModifyWord_SubstArgs; 1292} ModifyWord_SubstArgs;
1281 1293
@@ -1307,36 +1319,36 @@ ModifyWord_Subst(const char *word, SepBu @@ -1307,36 +1319,36 @@ ModifyWord_Subst(const char *word, SepBu
1307 SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen); 1319 SepBuf_AddBytes(buf, word + args->lhsLen, wordLen - args->lhsLen);
1308 args->pflags |= VARP_SUB_MATCHED; 1320 args->pflags |= VARP_SUB_MATCHED;
1309 } 1321 }
1310 return; 1322 return;
1311 } 1323 }
1312 1324
1313 if (args->pflags & VARP_ANCHOR_END) { 1325 if (args->pflags & VARP_ANCHOR_END) {
1314 if (wordLen < args->lhsLen) 1326 if (wordLen < args->lhsLen)
1315 goto nosub; 1327 goto nosub;
1316 const char *start = word + (wordLen - args->lhsLen); 1328 const char *start = word + (wordLen - args->lhsLen);
1317 if (memcmp(start, args->lhs, args->lhsLen) != 0) 1329 if (memcmp(start, args->lhs, args->lhsLen) != 0)
1318 goto nosub; 1330 goto nosub;
1319 1331
1320 SepBuf_AddBytes(buf, word, start - word); 1332 SepBuf_AddBytesBetween(buf, word, start);
1321 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1333 SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1322 args->pflags |= VARP_SUB_MATCHED; 1334 args->pflags |= VARP_SUB_MATCHED;
1323 return; 1335 return;
1324 } 1336 }
1325 1337
1326 /* unanchored */ 1338 /* unanchored */
1327 const char *cp; 1339 const char *cp;
1328 while ((cp = Str_FindSubstring(word, args->lhs)) != NULL) { 1340 while ((cp = Str_FindSubstring(word, args->lhs)) != NULL) {
1329 SepBuf_AddBytes(buf, word, cp - word); 1341 SepBuf_AddBytesBetween(buf, word, cp);
1330 SepBuf_AddBytes(buf, args->rhs, args->rhsLen); 1342 SepBuf_AddBytes(buf, args->rhs, args->rhsLen);
1331 args->pflags |= VARP_SUB_MATCHED; 1343 args->pflags |= VARP_SUB_MATCHED;
1332 wordLen -= (cp - word) + args->lhsLen; 1344 wordLen -= (cp - word) + args->lhsLen;
1333 word = cp + args->lhsLen; 1345 word = cp + args->lhsLen;
1334 if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL)) 1346 if (wordLen == 0 || !(args->pflags & VARP_SUB_GLOBAL))
1335 break; 1347 break;
1336 } 1348 }
1337nosub: 1349nosub:
1338 SepBuf_AddBytes(buf, word, wordLen); 1350 SepBuf_AddBytes(buf, word, wordLen);
1339} 1351}
1340 1352
1341#ifndef NO_REGEX 1353#ifndef NO_REGEX
1342/*- 1354/*-
@@ -1408,54 +1420,54 @@ tryagain: @@ -1408,54 +1420,54 @@ tryagain:
1408 } else { 1420 } else {
1409 n = rp[1] - '0'; 1421 n = rp[1] - '0';
1410 errstr[0] = '\\'; 1422 errstr[0] = '\\';
1411 errstr[1] = rp[1]; 1423 errstr[1] = rp[1];
1412 errstr[2] = '\0'; 1424 errstr[2] = '\0';
1413 rp++; 1425 rp++;
1414 } 1426 }
1415 1427
1416 if (n >= args->nsub) { 1428 if (n >= args->nsub) {
1417 Error("No subexpression %s", errstr); 1429 Error("No subexpression %s", errstr);
1418 } else if (m[n].rm_so == -1 && m[n].rm_eo == -1) { 1430 } else if (m[n].rm_so == -1 && m[n].rm_eo == -1) {
1419 Error("No match for subexpression %s", errstr); 1431 Error("No match for subexpression %s", errstr);
1420 } else { 1432 } else {
1421 SepBuf_AddBytes(buf, wp + m[n].rm_so, 1433 SepBuf_AddBytesBetween(buf, wp + m[n].rm_so,
1422 m[n].rm_eo - m[n].rm_so); 1434 wp + m[n].rm_eo);
1423 } 1435 }
1424 1436
1425 } else { 1437 } else {
1426 SepBuf_AddBytes(buf, rp, 1); 1438 SepBuf_AddBytes(buf, rp, 1);
1427 } 1439 }
1428 } 1440 }
1429 wp += m[0].rm_eo; 1441 wp += m[0].rm_eo;
1430 if (args->pflags & VARP_SUB_GLOBAL) { 1442 if (args->pflags & VARP_SUB_GLOBAL) {
1431 flags |= REG_NOTBOL; 1443 flags |= REG_NOTBOL;
1432 if (m[0].rm_so == 0 && m[0].rm_eo == 0) { 1444 if (m[0].rm_so == 0 && m[0].rm_eo == 0) {
1433 SepBuf_AddBytes(buf, wp, 1); 1445 SepBuf_AddBytes(buf, wp, 1);
1434 wp++; 1446 wp++;
1435 } 1447 }
1436 if (*wp) 1448 if (*wp)
1437 goto tryagain; 1449 goto tryagain;
1438 } 1450 }
1439 if (*wp) { 1451 if (*wp) {
1440 SepBuf_AddBytes(buf, wp, strlen(wp)); 1452 SepBuf_AddStr(buf, wp);
1441 } 1453 }
1442 break; 1454 break;
1443 default: 1455 default:
1444 VarREError(xrv, &args->re, "Unexpected regex error"); 1456 VarREError(xrv, &args->re, "Unexpected regex error");
1445 /* fall through */ 1457 /* fall through */
1446 case REG_NOMATCH: 1458 case REG_NOMATCH:
1447 nosub: 1459 nosub:
1448 SepBuf_AddBytes(buf, wp, strlen(wp)); 1460 SepBuf_AddStr(buf, wp);
1449 break; 1461 break;
1450 } 1462 }
1451} 1463}
1452#endif 1464#endif
1453 1465
1454 1466
1455typedef struct { 1467typedef struct {
1456 GNode *ctx; 1468 GNode *ctx;
1457 char *tvar; /* name of temporary variable */ 1469 char *tvar; /* name of temporary variable */
1458 char *str; /* string to expand */ 1470 char *str; /* string to expand */
1459 VarEvalFlags eflags; 1471 VarEvalFlags eflags;
1460} ModifyWord_LoopArgs; 1472} ModifyWord_LoopArgs;
1461 1473
@@ -1470,27 +1482,27 @@ ModifyWord_Loop(const char *word, SepBuf @@ -1470,27 +1482,27 @@ ModifyWord_Loop(const char *word, SepBuf
1470 Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT); 1482 Var_Set_with_flags(args->tvar, word, args->ctx, VAR_NO_EXPORT);
1471 char *s = Var_Subst(NULL, args->str, args->ctx, args->eflags); 1483 char *s = Var_Subst(NULL, args->str, args->ctx, args->eflags);
1472 if (DEBUG(VAR)) { 1484 if (DEBUG(VAR)) {
1473 fprintf(debug_file, 1485 fprintf(debug_file,
1474 "ModifyWord_Loop: in \"%s\", replace \"%s\" with \"%s\" " 1486 "ModifyWord_Loop: in \"%s\", replace \"%s\" with \"%s\" "
1475 "to \"%s\"\n", 1487 "to \"%s\"\n",
1476 word, args->tvar, args->str, s ? s : "(null)"); 1488 word, args->tvar, args->str, s ? s : "(null)");
1477 } 1489 }
1478 1490
1479 if (s != NULL && s[0] != '\0') { 1491 if (s != NULL && s[0] != '\0') {
1480 if (s[0] == '\n' || (buf->buf.count > 0 && 1492 if (s[0] == '\n' || (buf->buf.count > 0 &&
1481 buf->buf.buffer[buf->buf.count - 1] == '\n')) 1493 buf->buf.buffer[buf->buf.count - 1] == '\n'))
1482 buf->needSep = FALSE; 1494 buf->needSep = FALSE;
1483 SepBuf_AddBytes(buf, s, strlen(s)); 1495 SepBuf_AddStr(buf, s);
1484 } 1496 }
1485 free(s); 1497 free(s);
1486} 1498}
1487 1499
1488 1500
1489/*- 1501/*-
1490 * Implements the :[first..last] modifier. 1502 * Implements the :[first..last] modifier.
1491 * This is a special case of ModifyWords since we want to be able 1503 * This is a special case of ModifyWords since we want to be able
1492 * to scan the list backwards if first > last. 1504 * to scan the list backwards if first > last.
1493 */ 1505 */
1494static char * 1506static char *
1495VarSelectWords(Byte sep, Boolean oneBigWord, const char *str, int first, 1507VarSelectWords(Byte sep, Boolean oneBigWord, const char *str, int first,
1496 int last) 1508 int last)
@@ -1529,50 +1541,50 @@ VarSelectWords(Byte sep, Boolean oneBigW @@ -1529,50 +1541,50 @@ VarSelectWords(Byte sep, Boolean oneBigW
1529 * We avoid scanning more of the list than we need to. 1541 * We avoid scanning more of the list than we need to.
1530 */ 1542 */
1531 if (first > last) { 1543 if (first > last) {
1532 start = MIN(ac, first) - 1; 1544 start = MIN(ac, first) - 1;
1533 end = MAX(0, last - 1); 1545 end = MAX(0, last - 1);
1534 step = -1; 1546 step = -1;
1535 } else { 1547 } else {
1536 start = MAX(0, first - 1); 1548 start = MAX(0, first - 1);
1537 end = MIN(ac, last); 1549 end = MIN(ac, last);
1538 step = 1; 1550 step = 1;
1539 } 1551 }
1540 1552
1541 for (i = start; (step < 0) == (i >= end); i += step) { 1553 for (i = start; (step < 0) == (i >= end); i += step) {
1542 SepBuf_AddBytes(&buf, av[i], strlen(av[i])); 1554 SepBuf_AddStr(&buf, av[i]);
1543 SepBuf_Sep(&buf); 1555 SepBuf_Sep(&buf);
1544 } 1556 }
1545 1557
1546 free(as); 1558 free(as);
1547 free(av); 1559 free(av);
1548 1560
1549 return SepBuf_Destroy(&buf, FALSE); 1561 return SepBuf_Destroy(&buf, FALSE);
1550} 1562}
1551 1563
1552 1564
1553/* Callback for ModifyWords to implement the :tA modifier. 1565/* Callback for ModifyWords to implement the :tA modifier.
1554 * Replace each word with the result of realpath() if successful. */ 1566 * Replace each word with the result of realpath() if successful. */
1555static void 1567static void
1556ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 1568ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
1557{ 1569{
1558 struct stat st; 1570 struct stat st;
1559 char rbuf[MAXPATHLEN]; 1571 char rbuf[MAXPATHLEN];
1560 1572
1561 char *rp = cached_realpath(word, rbuf); 1573 const char *rp = cached_realpath(word, rbuf);
1562 if (rp != NULL && *rp == '/' && stat(rp, &st) == 0) 1574 if (rp != NULL && *rp == '/' && stat(rp, &st) == 0)
1563 word = rp; 1575 word = rp;
1564 1576
1565 SepBuf_AddBytes(buf, word, strlen(word)); 1577 SepBuf_AddStr(buf, word);
1566} 1578}
1567 1579
1568/*- 1580/*-
1569 *----------------------------------------------------------------------- 1581 *-----------------------------------------------------------------------
1570 * Modify each of the words of the passed string using the given function. 1582 * Modify each of the words of the passed string using the given function.
1571 * 1583 *
1572 * Input: 1584 * Input:
1573 * str String whose words should be modified 1585 * str String whose words should be modified
1574 * modifyWord Function that modifies a single word 1586 * modifyWord Function that modifies a single word
1575 * data Custom data for modifyWord 1587 * data Custom data for modifyWord
1576 * 1588 *
1577 * Results: 1589 * Results:
1578 * A string of all the words modified appropriately. 1590 * A string of all the words modified appropriately.
@@ -2511,27 +2523,27 @@ ApplyModifier_Regex(const char *mod, App @@ -2511,27 +2523,27 @@ ApplyModifier_Regex(const char *mod, App
2511 if (args.nsub > 10) 2523 if (args.nsub > 10)
2512 args.nsub = 10; 2524 args.nsub = 10;
2513 st->newStr = ModifyWords(st->ctxt, st->sep, oneBigWord, st->nstr, 2525 st->newStr = ModifyWords(st->ctxt, st->sep, oneBigWord, st->nstr,
2514 ModifyWord_SubstRegex, &args); 2526 ModifyWord_SubstRegex, &args);
2515 regfree(&args.re); 2527 regfree(&args.re);
2516 free(args.replace); 2528 free(args.replace);
2517 return TRUE; 2529 return TRUE;
2518} 2530}
2519#endif 2531#endif
2520 2532
2521static void 2533static void
2522ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) 2534ModifyWord_Copy(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED)
2523{ 2535{
2524 SepBuf_AddBytes(buf, word, strlen(word)); 2536 SepBuf_AddStr(buf, word);
2525} 2537}
2526 2538
2527/* :ts<separator> */ 2539/* :ts<separator> */
2528static Boolean 2540static Boolean
2529ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st) 2541ApplyModifier_ToSep(const char *sep, ApplyModifiersState *st)
2530{ 2542{
2531 if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) { 2543 if (sep[0] != st->endc && (sep[1] == st->endc || sep[1] == ':')) {
2532 /* ":ts<unrecognised><endc>" or ":ts<unrecognised>:" */ 2544 /* ":ts<unrecognised><endc>" or ":ts<unrecognised>:" */
2533 st->sep = sep[0]; 2545 st->sep = sep[0];
2534 st->cp = sep + 1; 2546 st->cp = sep + 1;
2535 } else if (sep[0] == st->endc || sep[0] == ':') { 2547 } else if (sep[0] == st->endc || sep[0] == ':') {
2536 /* ":ts<endc>" or ":ts:" */ 2548 /* ":ts<endc>" or ":ts:" */
2537 st->sep = '\0'; /* no separator */ 2549 st->sep = '\0'; /* no separator */