Sun Jul 26 15:09:10 2020 UTC ()
make(1): add Buffer functions for common tasks

Adding a string or a substring to a buffer are common tasks when handling
variables.  There is no need to spell out the strlen call or the pointer
subtraction at every call site.

Subtracting pointers results in a ptrdiff_t, which would have to be
converted to an int in each case for WARNS=6. Having this conversion in a
single place keeps the code clean.


(rillig)
diff -r1.27 -r1.28 src/usr.bin/make/buf.c
diff -r1.20 -r1.21 src/usr.bin/make/buf.h
diff -r1.312 -r1.313 src/usr.bin/make/var.c

cvs diff -r1.27 -r1.28 src/usr.bin/make/buf.c (expand / switch to unified diff)

--- src/usr.bin/make/buf.c 2020/07/26 13:39:30 1.27
+++ src/usr.bin/make/buf.c 2020/07/26 15:09:10 1.28
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: buf.c,v 1.27 2020/07/26 13:39:30 rillig Exp $ */ 1/* $NetBSD: buf.c,v 1.28 2020/07/26 15:09:10 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * All rights reserved. 5 * 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.
@@ -60,34 +60,34 @@ @@ -60,34 +60,34 @@
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE. 69 * SUCH DAMAGE.
70 */ 70 */
71 71
72#ifndef MAKE_NATIVE 72#ifndef MAKE_NATIVE
73static char rcsid[] = "$NetBSD: buf.c,v 1.27 2020/07/26 13:39:30 rillig Exp $"; 73static char rcsid[] = "$NetBSD: buf.c,v 1.28 2020/07/26 15:09:10 rillig Exp $";
74#else 74#else
75#include <sys/cdefs.h> 75#include <sys/cdefs.h>
76#ifndef lint 76#ifndef lint
77#if 0 77#if 0
78static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93"; 78static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93";
79#else 79#else
80__RCSID("$NetBSD: buf.c,v 1.27 2020/07/26 13:39:30 rillig Exp $"); 80__RCSID("$NetBSD: buf.c,v 1.28 2020/07/26 15:09:10 rillig Exp $");
81#endif 81#endif
82#endif /* not lint */ 82#endif /* not lint */
83#endif 83#endif
84 84
85/*- 85/*-
86 * buf.c -- 86 * buf.c --
87 * Functions for automatically-expanded NUL-terminated buffers. 87 * Functions for automatically-expanded NUL-terminated buffers.
88 */ 88 */
89 89
90#include <limits.h> 90#include <limits.h>
91#include "make.h" 91#include "make.h"
92#include "buf.h" 92#include "buf.h"
93 93
@@ -131,26 +131,38 @@ Buf_AddBytes(Buffer *bp, int numBytes, c @@ -131,26 +131,38 @@ Buf_AddBytes(Buffer *bp, int numBytes, c
131 Byte *ptr; 131 Byte *ptr;
132 132
133 if (__predict_false(count + numBytes >= bp->size)) { 133 if (__predict_false(count + numBytes >= bp->size)) {
134 bp->size += max(bp->size, numBytes + 16); 134 bp->size += max(bp->size, numBytes + 16);
135 bp->buffer = bmake_realloc(bp->buffer, bp->size); 135 bp->buffer = bmake_realloc(bp->buffer, bp->size);
136 } 136 }
137 137
138 ptr = bp->buffer + count; 138 ptr = bp->buffer + count;
139 bp->count = count + numBytes; 139 bp->count = count + numBytes;
140 ptr[numBytes] = 0; 140 ptr[numBytes] = 0;
141 memcpy(ptr, bytesPtr, numBytes); 141 memcpy(ptr, bytesPtr, numBytes);
142} 142}
143 143
 144void
 145Buf_AddBytesBetween(Buffer *bp, const char *start, const char *end)
 146{
 147 Buf_AddBytes(bp, (int)(end - start), start);
 148}
 149
 150void
 151Buf_AddStr(Buffer *bp, const char *str)
 152{
 153 Buf_AddBytes(bp, (int)strlen(str), str);
 154}
 155
144/*- 156/*-
145 *----------------------------------------------------------------------- 157 *-----------------------------------------------------------------------
146 * Buf_AddInt -- 158 * Buf_AddInt --
147 * Add the given number to the buffer. 159 * Add the given number to the buffer.
148 * 160 *
149 *----------------------------------------------------------------------- 161 *-----------------------------------------------------------------------
150 */ 162 */
151void 163void
152Buf_AddInt(Buffer *bp, int n) 164Buf_AddInt(Buffer *bp, int n)
153{ 165{
154 /* 166 /*
155 * We need enough space for the decimal representation of an int. 167 * We need enough space for the decimal representation of an int.
156 * We calculate the space needed for the octal representation, and 168 * We calculate the space needed for the octal representation, and

cvs diff -r1.20 -r1.21 src/usr.bin/make/buf.h (expand / switch to unified diff)

--- src/usr.bin/make/buf.h 2020/07/26 13:39:30 1.20
+++ src/usr.bin/make/buf.h 2020/07/26 15:09:10 1.21
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: buf.h,v 1.20 2020/07/26 13:39:30 rillig Exp $ */ 1/* $NetBSD: buf.h,v 1.21 2020/07/26 15:09:10 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * 5 *
6 * This code is derived from software contributed to Berkeley by 6 * This code is derived from software contributed to Berkeley by
7 * Adam de Boor. 7 * Adam de Boor.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -100,21 +100,23 @@ typedef struct Buffer { @@ -100,21 +100,23 @@ typedef struct Buffer {
100 if (__predict_false(_count >= (bp)->size)) \ 100 if (__predict_false(_count >= (bp)->size)) \
101 Buf_Expand_1(bp); \ 101 Buf_Expand_1(bp); \
102 _ptr = (bp)->buffer + _count; \ 102 _ptr = (bp)->buffer + _count; \
103 _ptr[-1] = (byte); \ 103 _ptr[-1] = (byte); \
104 _ptr[0] = 0; \ 104 _ptr[0] = 0; \
105 } while (0) 105 } while (0)
106 106
107#define BUF_ERROR 256 107#define BUF_ERROR 256
108 108
109#define Buf_Size(bp) ((bp)->count) 109#define Buf_Size(bp) ((bp)->count)
110 110
111void Buf_Expand_1(Buffer *); 111void Buf_Expand_1(Buffer *);
112void Buf_AddBytes(Buffer *, int, const Byte *); 112void Buf_AddBytes(Buffer *, int, const Byte *);
 113void Buf_AddBytesBetween(Buffer *, const Byte *, const Byte *);
 114void Buf_AddStr(Buffer *, const char *);
113void Buf_AddInt(Buffer *, int); 115void Buf_AddInt(Buffer *, int);
114Byte *Buf_GetAll(Buffer *, int *); 116Byte *Buf_GetAll(Buffer *, int *);
115void Buf_Empty(Buffer *); 117void Buf_Empty(Buffer *);
116void Buf_Init(Buffer *, int); 118void Buf_Init(Buffer *, int);
117Byte *Buf_Destroy(Buffer *, Boolean); 119Byte *Buf_Destroy(Buffer *, Boolean);
118Byte *Buf_DestroyCompact(Buffer *); 120Byte *Buf_DestroyCompact(Buffer *);
119 121
120#endif /* MAKE_BUF_H */ 122#endif /* MAKE_BUF_H */

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

--- src/usr.bin/make/var.c 2020/07/26 13:39:30 1.312
+++ src/usr.bin/make/var.c 2020/07/26 15:09:10 1.313
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.312 2020/07/26 13:39:30 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.313 2020/07/26 15:09:10 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.312 2020/07/26 13:39:30 rillig Exp $"; 72static char rcsid[] = "$NetBSD: var.c,v 1.313 2020/07/26 15:09:10 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.312 2020/07/26 13:39:30 rillig Exp $"); 79__RCSID("$NetBSD: var.c,v 1.313 2020/07/26 15:09:10 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 *
@@ -269,29 +269,26 @@ typedef enum { @@ -269,29 +269,26 @@ typedef enum {
269 * FIND_ENV look in the environment as well 269 * FIND_ENV look in the environment as well
270 * 270 *
271 * Results: 271 * Results:
272 * A pointer to the structure describing the desired variable or 272 * A pointer to the structure describing the desired variable or
273 * NULL if the variable does not exist. 273 * NULL if the variable does not exist.
274 * 274 *
275 * Side Effects: 275 * Side Effects:
276 * None 276 * None
277 *----------------------------------------------------------------------- 277 *-----------------------------------------------------------------------
278 */ 278 */
279static Var * 279static Var *
280VarFind(const char *name, GNode *ctxt, VarFindFlags flags) 280VarFind(const char *name, GNode *ctxt, VarFindFlags flags)
281{ 281{
282 Hash_Entry *var; 
283 Var *v; 
284 
285 /* 282 /*
286 * If the variable name begins with a '.', it could very well be one of 283 * If the variable name begins with a '.', it could very well be one of
287 * the local ones. We check the name against all the local variables 284 * the local ones. We check the name against all the local variables
288 * and substitute the short version in for 'name' if it matches one of 285 * and substitute the short version in for 'name' if it matches one of
289 * them. 286 * them.
290 */ 287 */
291 if (*name == '.' && isupper((unsigned char) name[1])) { 288 if (*name == '.' && isupper((unsigned char) name[1])) {
292 switch (name[1]) { 289 switch (name[1]) {
293 case 'A': 290 case 'A':
294 if (strcmp(name, ".ALLSRC") == 0) 291 if (strcmp(name, ".ALLSRC") == 0)
295 name = ALLSRC; 292 name = ALLSRC;
296 if (strcmp(name, ".ARCHIVE") == 0) 293 if (strcmp(name, ".ARCHIVE") == 0)
297 name = ARCHIVE; 294 name = ARCHIVE;
@@ -320,51 +317,48 @@ VarFind(const char *name, GNode *ctxt, V @@ -320,51 +317,48 @@ VarFind(const char *name, GNode *ctxt, V
320 } 317 }
321 318
322#ifdef notyet 319#ifdef notyet
323 /* for compatibility with gmake */ 320 /* for compatibility with gmake */
324 if (name[0] == '^' && name[1] == '\0') 321 if (name[0] == '^' && name[1] == '\0')
325 name = ALLSRC; 322 name = ALLSRC;
326#endif 323#endif
327 324
328 /* 325 /*
329 * First look for the variable in the given context. If it's not there, 326 * First look for the variable in the given context. If it's not there,
330 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order, 327 * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
331 * depending on the FIND_* flags in 'flags' 328 * depending on the FIND_* flags in 'flags'
332 */ 329 */
333 var = Hash_FindEntry(&ctxt->context, name); 330 Hash_Entry *var = Hash_FindEntry(&ctxt->context, name);
334 331
335 if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) { 332 if (var == NULL && (flags & FIND_CMD) && ctxt != VAR_CMD) {
336 var = Hash_FindEntry(&VAR_CMD->context, name); 333 var = Hash_FindEntry(&VAR_CMD->context, name);
337 } 334 }
338 if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) && 335 if (!checkEnvFirst && var == NULL && (flags & FIND_GLOBAL) &&
339 ctxt != VAR_GLOBAL) 336 ctxt != VAR_GLOBAL)
340 { 337 {
341 var = Hash_FindEntry(&VAR_GLOBAL->context, name); 338 var = Hash_FindEntry(&VAR_GLOBAL->context, name);
342 if (var == NULL && ctxt != VAR_INTERNAL) { 339 if (var == NULL && ctxt != VAR_INTERNAL) {
343 /* VAR_INTERNAL is subordinate to VAR_GLOBAL */ 340 /* VAR_INTERNAL is subordinate to VAR_GLOBAL */
344 var = Hash_FindEntry(&VAR_INTERNAL->context, name); 341 var = Hash_FindEntry(&VAR_INTERNAL->context, name);
345 } 342 }
346 } 343 }
347 if (var == NULL && (flags & FIND_ENV)) { 344 if (var == NULL && (flags & FIND_ENV)) {
348 char *env; 345 char *env;
349 346
350 if ((env = getenv(name)) != NULL) { 347 if ((env = getenv(name)) != NULL) {
351 int len; 348 Var *v = bmake_malloc(sizeof(Var));
352 
353 v = bmake_malloc(sizeof(Var)); 
354 v->name = bmake_strdup(name); 349 v->name = bmake_strdup(name);
355 350
356 len = strlen(env); 351 int len = (int)strlen(env);
357 
358 Buf_Init(&v->val, len + 1); 352 Buf_Init(&v->val, len + 1);
359 Buf_AddBytes(&v->val, len, env); 353 Buf_AddBytes(&v->val, len, env);
360 354
361 v->flags = VAR_FROM_ENV; 355 v->flags = VAR_FROM_ENV;
362 return v; 356 return v;
363 } else if (checkEnvFirst && (flags & FIND_GLOBAL) && 357 } else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
364 ctxt != VAR_GLOBAL) 358 ctxt != VAR_GLOBAL)
365 { 359 {
366 var = Hash_FindEntry(&VAR_GLOBAL->context, name); 360 var = Hash_FindEntry(&VAR_GLOBAL->context, name);
367 if (var == NULL && ctxt != VAR_INTERNAL) { 361 if (var == NULL && ctxt != VAR_INTERNAL) {
368 var = Hash_FindEntry(&VAR_INTERNAL->context, name); 362 var = Hash_FindEntry(&VAR_INTERNAL->context, name);
369 } 363 }
370 if (var == NULL) { 364 if (var == NULL) {
@@ -418,39 +412,35 @@ VarFreeEnv(Var *v, Boolean destroy) @@ -418,39 +412,35 @@ VarFreeEnv(Var *v, Boolean destroy)
418 * name name of variable to add 412 * name name of variable to add
419 * val value to set it to 413 * val value to set it to
420 * ctxt context in which to set it 414 * ctxt context in which to set it
421 * 415 *
422 * Side Effects: 416 * Side Effects:
423 * The new variable is placed at the front of the given context 417 * The new variable is placed at the front of the given context
424 * The name and val arguments are duplicated so they may 418 * The name and val arguments are duplicated so they may
425 * safely be freed. 419 * safely be freed.
426 *----------------------------------------------------------------------- 420 *-----------------------------------------------------------------------
427 */ 421 */
428static void 422static void
429VarAdd(const char *name, const char *val, GNode *ctxt) 423VarAdd(const char *name, const char *val, GNode *ctxt)
430{ 424{
431 Var *v; 425 Var *v = bmake_malloc(sizeof(Var));
432 int len; 
433 Hash_Entry *h; 
434 
435 v = bmake_malloc(sizeof(Var)); 
436 426
437 len = val != NULL ? strlen(val) : 0; 427 int len = val != NULL ? (int)strlen(val) : 0;
438 Buf_Init(&v->val, len + 1); 428 Buf_Init(&v->val, len + 1);
439 Buf_AddBytes(&v->val, len, val); 429 Buf_AddBytes(&v->val, len, val);
440 430
441 v->flags = 0; 431 v->flags = 0;
442 432
443 h = Hash_CreateEntry(&ctxt->context, name, NULL); 433 Hash_Entry *h = Hash_CreateEntry(&ctxt->context, name, NULL);
444 Hash_SetValue(h, v); 434 Hash_SetValue(h, v);
445 v->name = h->name; 435 v->name = h->name;
446 if (DEBUG(VAR) && !(ctxt->flags & INTERNAL)) { 436 if (DEBUG(VAR) && !(ctxt->flags & INTERNAL)) {
447 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val); 437 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
448 } 438 }
449} 439}
450 440
451/*- 441/*-
452 *----------------------------------------------------------------------- 442 *-----------------------------------------------------------------------
453 * Var_Delete -- 443 * Var_Delete --
454 * Remove a variable from a context. 444 * Remove a variable from a context.
455 * 445 *
456 * Side Effects: 446 * Side Effects:
@@ -828,27 +818,27 @@ Var_Set_with_flags(const char *name, con @@ -828,27 +818,27 @@ Var_Set_with_flags(const char *name, con
828 if (v == NULL) { 818 if (v == NULL) {
829 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) { 819 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
830 /* 820 /*
831 * This var would normally prevent the same name being added 821 * This var would normally prevent the same name being added
832 * to VAR_GLOBAL, so delete it from there if needed. 822 * to VAR_GLOBAL, so delete it from there if needed.
833 * Otherwise -V name may show the wrong value. 823 * Otherwise -V name may show the wrong value.
834 */ 824 */
835 Var_Delete(name, VAR_GLOBAL); 825 Var_Delete(name, VAR_GLOBAL);
836 } 826 }
837 VarAdd(name, val, ctxt); 827 VarAdd(name, val, ctxt);
838 } else { 828 } else {
839 Buf_Empty(&v->val); 829 Buf_Empty(&v->val);
840 if (val) 830 if (val)
841 Buf_AddBytes(&v->val, strlen(val), val); 831 Buf_AddStr(&v->val, val);
842 832
843 if (DEBUG(VAR)) { 833 if (DEBUG(VAR)) {
844 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val); 834 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
845 } 835 }
846 if ((v->flags & VAR_EXPORTED)) { 836 if ((v->flags & VAR_EXPORTED)) {
847 Var_Export1(name, VAR_EXPORT_PARENT); 837 Var_Export1(name, VAR_EXPORT_PARENT);
848 } 838 }
849 } 839 }
850 /* 840 /*
851 * Any variables given on the command line are automatically exported 841 * Any variables given on the command line are automatically exported
852 * to the environment (as per POSIX standard) 842 * to the environment (as per POSIX standard)
853 */ 843 */
854 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) { 844 if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
@@ -950,27 +940,27 @@ Var_Append(const char *name, const char  @@ -950,27 +940,27 @@ Var_Append(const char *name, const char
950 } 940 }
951 free(expanded_name); 941 free(expanded_name);
952 return; 942 return;
953 } 943 }
954 name = expanded_name; 944 name = expanded_name;
955 } 945 }
956 946
957 v = VarFind(name, ctxt, ctxt == VAR_GLOBAL ? (FIND_CMD | FIND_ENV) : 0); 947 v = VarFind(name, ctxt, ctxt == VAR_GLOBAL ? (FIND_CMD | FIND_ENV) : 0);
958 948
959 if (v == NULL) { 949 if (v == NULL) {
960 Var_Set(name, val, ctxt); 950 Var_Set(name, val, ctxt);
961 } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) { 951 } else if (ctxt == VAR_CMD || !(v->flags & VAR_FROM_CMD)) {
962 Buf_AddByte(&v->val, ' '); 952 Buf_AddByte(&v->val, ' ');
963 Buf_AddBytes(&v->val, strlen(val), val); 953 Buf_AddStr(&v->val, val);
964 954
965 if (DEBUG(VAR)) { 955 if (DEBUG(VAR)) {
966 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, 956 fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name,
967 Buf_GetAll(&v->val, NULL)); 957 Buf_GetAll(&v->val, NULL));
968 } 958 }
969 959
970 if (v->flags & VAR_FROM_ENV) { 960 if (v->flags & VAR_FROM_ENV) {
971 /* 961 /*
972 * If the original variable came from the environment, we 962 * If the original variable came from the environment, we
973 * have to install it in the global context (we could place 963 * have to install it in the global context (we could place
974 * it in the environment, but then we should provide a way to 964 * it in the environment, but then we should provide a way to
975 * export other variables...) 965 * export other variables...)
976 */ 966 */
@@ -1690,27 +1680,27 @@ VarOrder(const char *str, const char oty @@ -1690,27 +1680,27 @@ VarOrder(const char *str, const char oty
1690 * 0 with probability 1). 1680 * 0 with probability 1).
1691 */ 1681 */
1692 for (i = ac - 1; i > 0; i--) { 1682 for (i = ac - 1; i > 0; i--) {
1693 int rndidx = random() % (i + 1); 1683 int rndidx = random() % (i + 1);
1694 char *t = av[i]; 1684 char *t = av[i];
1695 av[i] = av[rndidx]; 1685 av[i] = av[rndidx];
1696 av[rndidx] = t; 1686 av[rndidx] = t;
1697 } 1687 }
1698 } 1688 }
1699 } 1689 }
1700 } 1690 }
1701 1691
1702 for (i = 0; i < ac; i++) { 1692 for (i = 0; i < ac; i++) {
1703 Buf_AddBytes(&buf, strlen(av[i]), av[i]); 1693 Buf_AddStr(&buf, av[i]);
1704 if (i != ac - 1) 1694 if (i != ac - 1)
1705 Buf_AddByte(&buf, ' '); 1695 Buf_AddByte(&buf, ' ');
1706 } 1696 }
1707 1697
1708 free(as); 1698 free(as);
1709 free(av); 1699 free(av);
1710 1700
1711 return Buf_Destroy(&buf, FALSE); 1701 return Buf_Destroy(&buf, FALSE);
1712} 1702}
1713 1703
1714 1704
1715/*- 1705/*-
1716 *----------------------------------------------------------------------- 1706 *-----------------------------------------------------------------------
@@ -1737,27 +1727,27 @@ VarUniq(const char *str) @@ -1737,27 +1727,27 @@ VarUniq(const char *str)
1737 int ac, i, j; 1727 int ac, i, j;
1738 1728
1739 Buf_Init(&buf, 0); 1729 Buf_Init(&buf, 0);
1740 av = brk_string(str, &ac, FALSE, &as); 1730 av = brk_string(str, &ac, FALSE, &as);
1741 1731
1742 if (ac > 1) { 1732 if (ac > 1) {
1743 for (j = 0, i = 1; i < ac; i++) 1733 for (j = 0, i = 1; i < ac; i++)
1744 if (strcmp(av[i], av[j]) != 0 && (++j != i)) 1734 if (strcmp(av[i], av[j]) != 0 && (++j != i))
1745 av[j] = av[i]; 1735 av[j] = av[i];
1746 ac = j + 1; 1736 ac = j + 1;
1747 } 1737 }
1748 1738
1749 for (i = 0; i < ac; i++) { 1739 for (i = 0; i < ac; i++) {
1750 Buf_AddBytes(&buf, strlen(av[i]), av[i]); 1740 Buf_AddStr(&buf, av[i]);
1751 if (i != ac - 1) 1741 if (i != ac - 1)
1752 Buf_AddByte(&buf, ' '); 1742 Buf_AddByte(&buf, ' ');
1753 } 1743 }
1754 1744
1755 free(as); 1745 free(as);
1756 free(av); 1746 free(av);
1757 1747
1758 return Buf_Destroy(&buf, FALSE); 1748 return Buf_Destroy(&buf, FALSE);
1759} 1749}
1760 1750
1761/*- 1751/*-
1762 *----------------------------------------------------------------------- 1752 *-----------------------------------------------------------------------
1763 * VarRange -- 1753 * VarRange --
@@ -1852,51 +1842,51 @@ ParseModifierPart(GNode *ctxt, const cha @@ -1852,51 +1842,51 @@ ParseModifierPart(GNode *ctxt, const cha
1852 } else { 1842 } else {
1853 if (!(eflags & VARE_NOSUBST)) { 1843 if (!(eflags & VARE_NOSUBST)) {
1854 char *cp2; 1844 char *cp2;
1855 int len; 1845 int len;
1856 void *freeIt; 1846 void *freeIt;
1857 1847
1858 /* 1848 /*
1859 * If unescaped dollar sign not before the 1849 * If unescaped dollar sign not before the
1860 * delimiter, assume it's a variable 1850 * delimiter, assume it's a variable
1861 * substitution and recurse. 1851 * substitution and recurse.
1862 */ 1852 */
1863 cp2 = Var_Parse(cp, ctxt, errnum | (eflags & VARE_WANTRES), 1853 cp2 = Var_Parse(cp, ctxt, errnum | (eflags & VARE_WANTRES),
1864 &len, &freeIt); 1854 &len, &freeIt);
1865 Buf_AddBytes(&buf, strlen(cp2), cp2); 1855 Buf_AddStr(&buf, cp2);
1866 free(freeIt); 1856 free(freeIt);
1867 cp += len - 1; 1857 cp += len - 1;
1868 } else { 1858 } else {
1869 const char *cp2 = &cp[1]; 1859 const char *cp2 = &cp[1];
1870 1860
1871 if (*cp2 == PROPEN || *cp2 == BROPEN) { 1861 if (*cp2 == PROPEN || *cp2 == BROPEN) {
1872 /* 1862 /*
1873 * Find the end of this variable reference 1863 * Find the end of this variable reference
1874 * and suck it in without further ado. 1864 * and suck it in without further ado.
1875 * It will be interpreted later. 1865 * It will be interpreted later.
1876 */ 1866 */
1877 int have = *cp2; 1867 int have = *cp2;
1878 int want = (*cp2 == PROPEN) ? PRCLOSE : BRCLOSE; 1868 int want = (*cp2 == PROPEN) ? PRCLOSE : BRCLOSE;
1879 int depth = 1; 1869 int depth = 1;
1880 1870
1881 for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) { 1871 for (++cp2; *cp2 != '\0' && depth > 0; ++cp2) {
1882 if (cp2[-1] != '\\') { 1872 if (cp2[-1] != '\\') {
1883 if (*cp2 == have) 1873 if (*cp2 == have)
1884 ++depth; 1874 ++depth;
1885 if (*cp2 == want) 1875 if (*cp2 == want)
1886 --depth; 1876 --depth;
1887 } 1877 }
1888 } 1878 }
1889 Buf_AddBytes(&buf, cp2 - cp, cp); 1879 Buf_AddBytesBetween(&buf, cp, cp2);
1890 cp = --cp2; 1880 cp = --cp2;
1891 } else 1881 } else
1892 Buf_AddByte(&buf, *cp); 1882 Buf_AddByte(&buf, *cp);
1893 } 1883 }
1894 } 1884 }
1895 } else if (subst != NULL && *cp == '&') 1885 } else if (subst != NULL && *cp == '&')
1896 Buf_AddBytes(&buf, subst->lhsLen, subst->lhs); 1886 Buf_AddBytes(&buf, subst->lhsLen, subst->lhs);
1897 else 1887 else
1898 Buf_AddByte(&buf, *cp); 1888 Buf_AddByte(&buf, *cp);
1899 } 1889 }
1900 1890
1901 if (*cp != delim) { 1891 if (*cp != delim) {
1902 *tstr = cp; 1892 *tstr = cp;
@@ -1927,34 +1917,34 @@ ParseModifierPart(GNode *ctxt, const cha @@ -1927,34 +1917,34 @@ ParseModifierPart(GNode *ctxt, const cha
1927 *----------------------------------------------------------------------- 1917 *-----------------------------------------------------------------------
1928 */ 1918 */
1929static char * 1919static char *
1930VarQuote(char *str, Boolean quoteDollar) 1920VarQuote(char *str, Boolean quoteDollar)
1931{ 1921{
1932 Buffer buf; 1922 Buffer buf;
1933 Buf_Init(&buf, 0); 1923 Buf_Init(&buf, 0);
1934 1924
1935 for (; *str != '\0'; str++) { 1925 for (; *str != '\0'; str++) {
1936 if (*str == '\n') { 1926 if (*str == '\n') {
1937 const char *newline = Shell_GetNewline(); 1927 const char *newline = Shell_GetNewline();
1938 if (newline == NULL) 1928 if (newline == NULL)
1939 newline = "\\\n"; 1929 newline = "\\\n";
1940 Buf_AddBytes(&buf, strlen(newline), newline); 1930 Buf_AddStr(&buf, newline);
1941 continue; 1931 continue;
1942 } 1932 }
1943 if (isspace((unsigned char)*str) || ismeta((unsigned char)*str)) 1933 if (isspace((unsigned char)*str) || ismeta((unsigned char)*str))
1944 Buf_AddByte(&buf, '\\'); 1934 Buf_AddByte(&buf, '\\');
1945 Buf_AddByte(&buf, *str); 1935 Buf_AddByte(&buf, *str);
1946 if (quoteDollar && *str == '$') 1936 if (quoteDollar && *str == '$')
1947 Buf_AddBytes(&buf, 2, "\\$"); 1937 Buf_AddStr(&buf, "\\$");
1948 } 1938 }
1949 1939
1950 str = Buf_Destroy(&buf, FALSE); 1940 str = Buf_Destroy(&buf, FALSE);
1951 if (DEBUG(VAR)) 1941 if (DEBUG(VAR))
1952 fprintf(debug_file, "QuoteMeta: [%s]\n", str); 1942 fprintf(debug_file, "QuoteMeta: [%s]\n", str);
1953 return str; 1943 return str;
1954} 1944}
1955 1945
1956/*- 1946/*-
1957 *----------------------------------------------------------------------- 1947 *-----------------------------------------------------------------------
1958 * VarHash -- 1948 * VarHash --
1959 * Hash the string using the MurmurHash3 algorithm. 1949 * Hash the string using the MurmurHash3 algorithm.
1960 * Output is computed using 32bit Little Endian arithmetic. 1950 * Output is computed using 32bit Little Endian arithmetic.
@@ -2155,27 +2145,27 @@ ApplyModifier_Defined(const char *mod, A @@ -2155,27 +2145,27 @@ ApplyModifier_Defined(const char *mod, A
2155 st->cp[1] == '\\')) { 2145 st->cp[1] == '\\')) {
2156 Buf_AddByte(&buf, st->cp[1]); 2146 Buf_AddByte(&buf, st->cp[1]);
2157 st->cp++; 2147 st->cp++;
2158 } else if (*st->cp == '$') { 2148 } else if (*st->cp == '$') {
2159 /* 2149 /*
2160 * If unescaped dollar sign, assume it's a 2150 * If unescaped dollar sign, assume it's a
2161 * variable substitution and recurse. 2151 * variable substitution and recurse.
2162 */ 2152 */
2163 char *cp2; 2153 char *cp2;
2164 int len; 2154 int len;
2165 void *freeIt; 2155 void *freeIt;
2166 2156
2167 cp2 = Var_Parse(st->cp, st->ctxt, neflags, &len, &freeIt); 2157 cp2 = Var_Parse(st->cp, st->ctxt, neflags, &len, &freeIt);
2168 Buf_AddBytes(&buf, strlen(cp2), cp2); 2158 Buf_AddStr(&buf, cp2);
2169 free(freeIt); 2159 free(freeIt);
2170 st->cp += len - 1; 2160 st->cp += len - 1;
2171 } else { 2161 } else {
2172 Buf_AddByte(&buf, *st->cp); 2162 Buf_AddByte(&buf, *st->cp);
2173 } 2163 }
2174 } 2164 }
2175 2165
2176 st->termc = *st->cp; 2166 st->termc = *st->cp;
2177 2167
2178 if (st->v->flags & VAR_JUNK) 2168 if (st->v->flags & VAR_JUNK)
2179 st->v->flags |= VAR_KEEP; 2169 st->v->flags |= VAR_KEEP;
2180 if (neflags & VARE_WANTRES) { 2170 if (neflags & VARE_WANTRES) {
2181 st->newStr = Buf_Destroy(&buf, FALSE); 2171 st->newStr = Buf_Destroy(&buf, FALSE);
@@ -3487,27 +3477,27 @@ Var_Parse(const char *str, GNode *ctxt,  @@ -3487,27 +3477,27 @@ Var_Parse(const char *str, GNode *ctxt,
3487 depth++; 3477 depth++;
3488 if (*tstr == endc) { 3478 if (*tstr == endc) {
3489 if (--depth == 0) 3479 if (--depth == 0)
3490 break; 3480 break;
3491 } 3481 }
3492 if (depth == 1 && *tstr == ':') 3482 if (depth == 1 && *tstr == ':')
3493 break; 3483 break;
3494 /* A variable inside a variable, expand. */ 3484 /* A variable inside a variable, expand. */
3495 if (*tstr == '$') { 3485 if (*tstr == '$') {
3496 int rlen; 3486 int rlen;
3497 void *freeIt; 3487 void *freeIt;
3498 char *rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt); 3488 char *rval = Var_Parse(tstr, ctxt, flags, &rlen, &freeIt);
3499 if (rval != NULL) 3489 if (rval != NULL)
3500 Buf_AddBytes(&buf, strlen(rval), rval); 3490 Buf_AddStr(&buf, rval);
3501 free(freeIt); 3491 free(freeIt);
3502 tstr += rlen - 1; 3492 tstr += rlen - 1;
3503 } else 3493 } else
3504 Buf_AddByte(&buf, *tstr); 3494 Buf_AddByte(&buf, *tstr);
3505 } 3495 }
3506 if (*tstr == ':') { 3496 if (*tstr == ':') {
3507 haveModifier = TRUE; 3497 haveModifier = TRUE;
3508 } else if (*tstr == endc) { 3498 } else if (*tstr == endc) {
3509 haveModifier = FALSE; 3499 haveModifier = FALSE;
3510 } else { 3500 } else {
3511 /* 3501 /*
3512 * If we never did find the end character, return NULL 3502 * If we never did find the end character, return NULL
3513 * right now, setting the length to be the distance to 3503 * right now, setting the length to be the distance to
@@ -3757,27 +3747,27 @@ Var_Subst(const char *var, const char *s @@ -3757,27 +3747,27 @@ Var_Subst(const char *var, const char *s
3757 Buf_AddByte(&buf, *str); 3747 Buf_AddByte(&buf, *str);
3758 str++; 3748 str++;
3759 Buf_AddByte(&buf, *str); 3749 Buf_AddByte(&buf, *str);
3760 str++; 3750 str++;
3761 } else if (*str != '$') { 3751 } else if (*str != '$') {
3762 /* 3752 /*
3763 * Skip as many characters as possible -- either to the end of 3753 * Skip as many characters as possible -- either to the end of
3764 * the string or to the next dollar sign (variable invocation). 3754 * the string or to the next dollar sign (variable invocation).
3765 */ 3755 */
3766 const char *cp; 3756 const char *cp;
3767 3757
3768 for (cp = str++; *str != '$' && *str != '\0'; str++) 3758 for (cp = str++; *str != '$' && *str != '\0'; str++)
3769 continue; 3759 continue;
3770 Buf_AddBytes(&buf, str - cp, cp); 3760 Buf_AddBytesBetween(&buf, cp, str);
3771 } else { 3761 } else {
3772 if (var != NULL) { 3762 if (var != NULL) {
3773 int expand; 3763 int expand;
3774 for (;;) { 3764 for (;;) {
3775 if (str[1] == '\0') { 3765 if (str[1] == '\0') {
3776 /* A trailing $ is kind of a special case */ 3766 /* A trailing $ is kind of a special case */
3777 Buf_AddByte(&buf, str[0]); 3767 Buf_AddByte(&buf, str[0]);
3778 str++; 3768 str++;
3779 expand = FALSE; 3769 expand = FALSE;
3780 } else if (str[1] != PROPEN && str[1] != BROPEN) { 3770 } else if (str[1] != PROPEN && str[1] != BROPEN) {
3781 if (str[1] != *var || strlen(var) > 1) { 3771 if (str[1] != *var || strlen(var) > 1) {
3782 Buf_AddBytes(&buf, 2, str); 3772 Buf_AddBytes(&buf, 2, str);
3783 str += 2; 3773 str += 2;
@@ -3789,40 +3779,40 @@ Var_Subst(const char *var, const char *s @@ -3789,40 +3779,40 @@ Var_Subst(const char *var, const char *s
3789 const char *p; 3779 const char *p;
3790 3780
3791 /* Scan up to the end of the variable name. */ 3781 /* Scan up to the end of the variable name. */
3792 for (p = &str[2]; *p && 3782 for (p = &str[2]; *p &&
3793 *p != ':' && *p != PRCLOSE && *p != BRCLOSE; p++) 3783 *p != ':' && *p != PRCLOSE && *p != BRCLOSE; p++)
3794 if (*p == '$') 3784 if (*p == '$')
3795 break; 3785 break;
3796 /* 3786 /*
3797 * A variable inside the variable. We cannot expand 3787 * A variable inside the variable. We cannot expand
3798 * the external variable yet, so we try again with 3788 * the external variable yet, so we try again with
3799 * the nested one 3789 * the nested one
3800 */ 3790 */
3801 if (*p == '$') { 3791 if (*p == '$') {
3802 Buf_AddBytes(&buf, p - str, str); 3792 Buf_AddBytesBetween(&buf, str, p);
3803 str = p; 3793 str = p;
3804 continue; 3794 continue;
3805 } 3795 }
3806 3796
3807 if (strncmp(var, str + 2, p - str - 2) != 0 || 3797 if (strncmp(var, str + 2, p - str - 2) != 0 ||
3808 var[p - str - 2] != '\0') { 3798 var[p - str - 2] != '\0') {
3809 /* 3799 /*
3810 * Not the variable we want to expand, scan 3800 * Not the variable we want to expand, scan
3811 * until the next variable 3801 * until the next variable
3812 */ 3802 */
3813 for (; *p != '$' && *p != '\0'; p++) 3803 for (; *p != '$' && *p != '\0'; p++)
3814 continue; 3804 continue;
3815 Buf_AddBytes(&buf, p - str, str); 3805 Buf_AddBytesBetween(&buf, str, p);
3816 str = p; 3806 str = p;
3817 expand = FALSE; 3807 expand = FALSE;
3818 } else 3808 } else
3819 expand = TRUE; 3809 expand = TRUE;
3820 break; 3810 break;
3821 } 3811 }
3822 } 3812 }
3823 if (!expand) 3813 if (!expand)
3824 continue; 3814 continue;
3825 } 3815 }
3826 3816
3827 val = Var_Parse(str, ctxt, flags, &length, &freeIt); 3817 val = Var_Parse(str, ctxt, flags, &length, &freeIt);
3828 3818