make(1): split Buf_Destroy into Buf_Done and Buf_DoneData In all cases except one, the boolean argument to Buf_Destroy was constant. Removing that argument by splitting the function into two separate functions makes the intention clearer on the call site. It also removes the possibility for using the return value of Buf_Done, which would have made no sense. The function Buf_Done now pairs with Buf_Init, just as in HashTable and Lst. Even though Buf_Done is essentially a no-op, it is kept as a function, both for symmetry with Buf_Init and for clearing the Buffer members after use (this will be done only in CLEANUP mode, in a follow-up commit).diff -r1.47 -r1.48 src/usr.bin/make/buf.c
(rillig)
--- src/usr.bin/make/buf.c 2020/12/30 10:03:16 1.47
+++ src/usr.bin/make/buf.c 2021/01/30 20:53:29 1.48
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: buf.c,v 1.47 2020/12/30 10:03:16 rillig Exp $ */ | 1 | /* $NetBSD: buf.c,v 1.48 2021/01/30 20:53:29 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. | |
@@ -65,27 +65,27 @@ | @@ -65,27 +65,27 @@ | |||
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 | /* Automatically-expanding null-terminated character buffers. */ | 72 | /* Automatically-expanding null-terminated character buffers. */ | |
73 | 73 | |||
74 | #include <limits.h> | 74 | #include <limits.h> | |
75 | #include "make.h" | 75 | #include "make.h" | |
76 | 76 | |||
77 | /* "@(#)buf.c 8.1 (Berkeley) 6/6/93" */ | 77 | /* "@(#)buf.c 8.1 (Berkeley) 6/6/93" */ | |
78 | MAKE_RCSID("$NetBSD: buf.c,v 1.47 2020/12/30 10:03:16 rillig Exp $"); | 78 | MAKE_RCSID("$NetBSD: buf.c,v 1.48 2021/01/30 20:53:29 rillig Exp $"); | |
79 | 79 | |||
80 | /* Make space in the buffer for adding at least 16 more bytes. */ | 80 | /* Make space in the buffer for adding at least 16 more bytes. */ | |
81 | void | 81 | void | |
82 | Buf_Expand(Buffer *buf) | 82 | Buf_Expand(Buffer *buf) | |
83 | { | 83 | { | |
84 | buf->cap += buf->cap > 16 ? buf->cap : 16; | 84 | buf->cap += buf->cap > 16 ? buf->cap : 16; | |
85 | buf->data = bmake_realloc(buf->data, buf->cap); | 85 | buf->data = bmake_realloc(buf->data, buf->cap); | |
86 | } | 86 | } | |
87 | 87 | |||
88 | /* Add the bytes to the buffer. */ | 88 | /* Add the bytes to the buffer. */ | |
89 | void | 89 | void | |
90 | Buf_AddBytes(Buffer *buf, const char *bytes, size_t bytes_len) | 90 | Buf_AddBytes(Buffer *buf, const char *bytes, size_t bytes_len) | |
91 | { | 91 | { | |
@@ -165,57 +165,66 @@ Buf_InitSize(Buffer *buf, size_t cap) | @@ -165,57 +165,66 @@ Buf_InitSize(Buffer *buf, size_t cap) | |||
165 | buf->cap = cap; | 165 | buf->cap = cap; | |
166 | buf->len = 0; | 166 | buf->len = 0; | |
167 | buf->data = bmake_malloc(cap); | 167 | buf->data = bmake_malloc(cap); | |
168 | buf->data[0] = '\0'; | 168 | buf->data[0] = '\0'; | |
169 | } | 169 | } | |
170 | 170 | |||
171 | void | 171 | void | |
172 | Buf_Init(Buffer *buf) | 172 | Buf_Init(Buffer *buf) | |
173 | { | 173 | { | |
174 | Buf_InitSize(buf, 256); | 174 | Buf_InitSize(buf, 256); | |
175 | } | 175 | } | |
176 | 176 | |||
177 | /* | 177 | /* | |
178 | * Reset the buffer. | 178 | * Free the data from the buffer. | |
179 | * If freeData is TRUE, the data from the buffer is freed as well. | 179 | * The buffer is left in an indeterminate state. | |
180 | * Otherwise it is kept and returned. | 180 | */ | |
181 | void | |||
182 | Buf_Done(Buffer *buf) | |||
183 | { | |||
184 | free(buf->data); | |||
185 | ||||
186 | buf->cap = 0; | |||
187 | buf->len = 0; | |||
188 | buf->data = NULL; | |||
189 | } | |||
190 | ||||
191 | /* | |||
192 | * Return the data from the buffer. | |||
193 | * The buffer is left in an indeterminate state. | |||
181 | */ | 194 | */ | |
182 | char * | 195 | char * | |
183 | Buf_Destroy(Buffer *buf, Boolean freeData) | 196 | Buf_DoneData(Buffer *buf) | |
184 | { | 197 | { | |
185 | char *data = buf->data; | 198 | char *data = buf->data; | |
186 | if (freeData) { | |||
187 | free(data); | |||
188 | data = NULL; | |||
189 | } | |||
190 | 199 | |||
191 | buf->cap = 0; | 200 | buf->cap = 0; | |
192 | buf->len = 0; | 201 | buf->len = 0; | |
193 | buf->data = NULL; | 202 | buf->data = NULL; | |
194 | 203 | |||
195 | return data; | 204 | return data; | |
196 | } | 205 | } | |
197 | 206 | |||
198 | #ifndef BUF_COMPACT_LIMIT | 207 | #ifndef BUF_COMPACT_LIMIT | |
199 | # define BUF_COMPACT_LIMIT 128 /* worthwhile saving */ | 208 | # define BUF_COMPACT_LIMIT 128 /* worthwhile saving */ | |
200 | #endif | 209 | #endif | |
201 | 210 | |||
202 | /* | 211 | /* | |
203 | * Reset the buffer and return its data. | 212 | * Reset the buffer and return its data. | |
204 | * | 213 | * | |
205 | * If the buffer size is much greater than its content, | 214 | * If the buffer size is much greater than its content, | |
206 | * a new buffer will be allocated and the old one freed. | 215 | * a new buffer will be allocated and the old one freed. | |
207 | */ | 216 | */ | |
208 | char * | 217 | char * | |
209 | Buf_DestroyCompact(Buffer *buf) | 218 | Buf_DoneDataCompact(Buffer *buf) | |
210 | { | 219 | { | |
211 | #if BUF_COMPACT_LIMIT > 0 | 220 | #if BUF_COMPACT_LIMIT > 0 | |
212 | if (buf->cap - buf->len >= BUF_COMPACT_LIMIT) { | 221 | if (buf->cap - buf->len >= BUF_COMPACT_LIMIT) { | |
213 | /* We trust realloc to be smart */ | 222 | /* We trust realloc to be smart */ | |
214 | char *data = bmake_realloc(buf->data, buf->len + 1); | 223 | char *data = bmake_realloc(buf->data, buf->len + 1); | |
215 | data[buf->len] = '\0'; /* XXX: unnecessary */ | 224 | data[buf->len] = '\0'; /* XXX: unnecessary */ | |
216 | Buf_Destroy(buf, FALSE); | 225 | Buf_DoneData(buf); | |
217 | return data; | 226 | return data; | |
218 | } | 227 | } | |
219 | #endif | 228 | #endif | |
220 | return Buf_Destroy(buf, FALSE); | 229 | return Buf_DoneData(buf); | |
221 | } | 230 | } |
--- src/usr.bin/make/buf.h 2020/12/28 15:42:53 1.38
+++ src/usr.bin/make/buf.h 2021/01/30 20:53:29 1.39
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: buf.h,v 1.38 2020/12/28 15:42:53 rillig Exp $ */ | 1 | /* $NetBSD: buf.h,v 1.39 2021/01/30 20:53:29 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 | |
@@ -116,17 +116,18 @@ MAKE_INLINE Boolean | @@ -116,17 +116,18 @@ MAKE_INLINE Boolean | |||
116 | Buf_EndsWith(const Buffer *buf, char ch) | 116 | Buf_EndsWith(const Buffer *buf, char ch) | |
117 | { | 117 | { | |
118 | return buf->len > 0 && buf->data[buf->len - 1] == ch; | 118 | return buf->len > 0 && buf->data[buf->len - 1] == ch; | |
119 | } | 119 | } | |
120 | 120 | |||
121 | void Buf_AddBytes(Buffer *, const char *, size_t); | 121 | void Buf_AddBytes(Buffer *, const char *, size_t); | |
122 | void Buf_AddBytesBetween(Buffer *, const char *, const char *); | 122 | void Buf_AddBytesBetween(Buffer *, const char *, const char *); | |
123 | void Buf_AddStr(Buffer *, const char *); | 123 | void Buf_AddStr(Buffer *, const char *); | |
124 | void Buf_AddInt(Buffer *, int); | 124 | void Buf_AddInt(Buffer *, int); | |
125 | char *Buf_GetAll(Buffer *, size_t *); | 125 | char *Buf_GetAll(Buffer *, size_t *); | |
126 | void Buf_Empty(Buffer *); | 126 | void Buf_Empty(Buffer *); | |
127 | void Buf_Init(Buffer *); | 127 | void Buf_Init(Buffer *); | |
128 | void Buf_InitSize(Buffer *, size_t); | 128 | void Buf_InitSize(Buffer *, size_t); | |
129 | char *Buf_Destroy(Buffer *, Boolean); | 129 | void Buf_Done(Buffer *); | |
130 | char *Buf_DestroyCompact(Buffer *); | 130 | char *Buf_DoneData(Buffer *); | |
131 | char *Buf_DoneDataCompact(Buffer *); | |||
131 | 132 | |||
132 | #endif /* MAKE_BUF_H */ | 133 | #endif /* MAKE_BUF_H */ |
--- src/usr.bin/make/cond.c 2021/01/22 00:12:01 1.253
+++ src/usr.bin/make/cond.c 2021/01/30 20:53:29 1.254
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: cond.c,v 1.253 2021/01/22 00:12:01 rillig Exp $ */ | 1 | /* $NetBSD: cond.c,v 1.254 2021/01/30 20:53:29 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. | |
@@ -85,27 +85,27 @@ | @@ -85,27 +85,27 @@ | |||
85 | * Cond_restore_depth | 85 | * Cond_restore_depth | |
86 | * Save and restore the nesting of the conditions, at | 86 | * Save and restore the nesting of the conditions, at | |
87 | * the start and end of including another makefile, to | 87 | * the start and end of including another makefile, to | |
88 | * ensure that in each makefile the conditional | 88 | * ensure that in each makefile the conditional | |
89 | * directives are well-balanced. | 89 | * directives are well-balanced. | |
90 | */ | 90 | */ | |
91 | 91 | |||
92 | #include <errno.h> | 92 | #include <errno.h> | |
93 | 93 | |||
94 | #include "make.h" | 94 | #include "make.h" | |
95 | #include "dir.h" | 95 | #include "dir.h" | |
96 | 96 | |||
97 | /* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ | 97 | /* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ | |
98 | MAKE_RCSID("$NetBSD: cond.c,v 1.253 2021/01/22 00:12:01 rillig Exp $"); | 98 | MAKE_RCSID("$NetBSD: cond.c,v 1.254 2021/01/30 20:53:29 rillig Exp $"); | |
99 | 99 | |||
100 | /* | 100 | /* | |
101 | * The parsing of conditional expressions is based on this grammar: | 101 | * The parsing of conditional expressions is based on this grammar: | |
102 | * Or -> And '||' Or | 102 | * Or -> And '||' Or | |
103 | * Or -> And | 103 | * Or -> And | |
104 | * And -> Term '&&' And | 104 | * And -> Term '&&' And | |
105 | * And -> Term | 105 | * And -> Term | |
106 | * Term -> Function '(' Argument ')' | 106 | * Term -> Function '(' Argument ')' | |
107 | * Term -> Leaf Operator Leaf | 107 | * Term -> Leaf Operator Leaf | |
108 | * Term -> Leaf | 108 | * Term -> Leaf | |
109 | * Term -> '(' Or ')' | 109 | * Term -> '(' Or ')' | |
110 | * Term -> '!' Term | 110 | * Term -> '!' Term | |
111 | * Leaf -> "string" | 111 | * Leaf -> "string" | |
@@ -272,28 +272,28 @@ ParseFuncArg(CondParser *par, const char | @@ -272,28 +272,28 @@ ParseFuncArg(CondParser *par, const char | |||
272 | /* TODO: handle errors */ | 272 | /* TODO: handle errors */ | |
273 | Buf_AddStr(&argBuf, nestedVal.str); | 273 | Buf_AddStr(&argBuf, nestedVal.str); | |
274 | FStr_Done(&nestedVal); | 274 | FStr_Done(&nestedVal); | |
275 | continue; | 275 | continue; | |
276 | } | 276 | } | |
277 | if (ch == '(') | 277 | if (ch == '(') | |
278 | paren_depth++; | 278 | paren_depth++; | |
279 | else if (ch == ')' && --paren_depth < 0) | 279 | else if (ch == ')' && --paren_depth < 0) | |
280 | break; | 280 | break; | |
281 | Buf_AddByte(&argBuf, *p); | 281 | Buf_AddByte(&argBuf, *p); | |
282 | p++; | 282 | p++; | |
283 | } | 283 | } | |
284 | 284 | |||
285 | *out_arg = Buf_GetAll(&argBuf, &argLen); | 285 | argLen = argBuf.len; | |
286 | Buf_Destroy(&argBuf, FALSE); | 286 | *out_arg = Buf_DoneData(&argBuf); | |
287 | 287 | |||
288 | cpp_skip_hspace(&p); | 288 | cpp_skip_hspace(&p); | |
289 | 289 | |||
290 | if (func != NULL && *p++ != ')') { | 290 | if (func != NULL && *p++ != ')') { | |
291 | Parse_Error(PARSE_FATAL, | 291 | Parse_Error(PARSE_FATAL, | |
292 | "Missing closing parenthesis for %s()", func); | 292 | "Missing closing parenthesis for %s()", func); | |
293 | par->printedError = TRUE; | 293 | par->printedError = TRUE; | |
294 | return 0; | 294 | return 0; | |
295 | } | 295 | } | |
296 | 296 | |||
297 | *pp = p; | 297 | *pp = p; | |
298 | return argLen; | 298 | return argLen; | |
299 | } | 299 | } | |
@@ -529,29 +529,29 @@ CondParser_String(CondParser *par, Boole | @@ -529,29 +529,29 @@ CondParser_String(CondParser *par, Boole | |||
529 | /* | 529 | /* | |
530 | * The left-hand side must be quoted, | 530 | * The left-hand side must be quoted, | |
531 | * a variable reference or a number. | 531 | * a variable reference or a number. | |
532 | */ | 532 | */ | |
533 | str = FStr_InitRefer(NULL); | 533 | str = FStr_InitRefer(NULL); | |
534 | goto cleanup; | 534 | goto cleanup; | |
535 | } | 535 | } | |
536 | Buf_AddByte(&buf, par->p[0]); | 536 | Buf_AddByte(&buf, par->p[0]); | |
537 | par->p++; | 537 | par->p++; | |
538 | continue; | 538 | continue; | |
539 | } | 539 | } | |
540 | } | 540 | } | |
541 | got_str: | 541 | got_str: | |
542 | str = FStr_InitOwn(Buf_GetAll(&buf, NULL)); | 542 | str = FStr_InitOwn(buf.data); | |
543 | cleanup: | 543 | cleanup: | |
544 | Buf_Destroy(&buf, FALSE); | 544 | Buf_DoneData(&buf); | |
545 | *out_str = str; | 545 | *out_str = str; | |
546 | } | 546 | } | |
547 | 547 | |||
548 | static Boolean | 548 | static Boolean | |
549 | If_Eval(const CondParser *par, const char *arg, size_t arglen) | 549 | If_Eval(const CondParser *par, const char *arg, size_t arglen) | |
550 | { | 550 | { | |
551 | Boolean res = par->evalBare(arglen, arg); | 551 | Boolean res = par->evalBare(arglen, arg); | |
552 | return par->negateEvalBare ? !res : res; | 552 | return par->negateEvalBare ? !res : res; | |
553 | } | 553 | } | |
554 | 554 | |||
555 | /* | 555 | /* | |
556 | * Evaluate a "comparison without operator", such as in ".if ${VAR}" or | 556 | * Evaluate a "comparison without operator", such as in ".if ${VAR}" or | |
557 | * ".if 0". | 557 | * ".if 0". |
--- src/usr.bin/make/dir.c 2021/01/24 20:11:55 1.264
+++ src/usr.bin/make/dir.c 2021/01/30 20:53:29 1.265
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: dir.c,v 1.264 2021/01/24 20:11:55 rillig Exp $ */ | 1 | /* $NetBSD: dir.c,v 1.265 2021/01/30 20:53:29 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. | |
@@ -128,27 +128,27 @@ | @@ -128,27 +128,27 @@ | |||
128 | */ | 128 | */ | |
129 | 129 | |||
130 | #include <sys/types.h> | 130 | #include <sys/types.h> | |
131 | #include <sys/stat.h> | 131 | #include <sys/stat.h> | |
132 | 132 | |||
133 | #include <dirent.h> | 133 | #include <dirent.h> | |
134 | #include <errno.h> | 134 | #include <errno.h> | |
135 | 135 | |||
136 | #include "make.h" | 136 | #include "make.h" | |
137 | #include "dir.h" | 137 | #include "dir.h" | |
138 | #include "job.h" | 138 | #include "job.h" | |
139 | 139 | |||
140 | /* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ | 140 | /* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ | |
141 | MAKE_RCSID("$NetBSD: dir.c,v 1.264 2021/01/24 20:11:55 rillig Exp $"); | 141 | MAKE_RCSID("$NetBSD: dir.c,v 1.265 2021/01/30 20:53:29 rillig Exp $"); | |
142 | 142 | |||
143 | /* | 143 | /* | |
144 | * A search path is a list of CachedDir structures. A CachedDir has in it the | 144 | * A search path is a list of CachedDir structures. A CachedDir has in it the | |
145 | * name of the directory and the names of all the files in the directory. | 145 | * name of the directory and the names of all the files in the directory. | |
146 | * This is used to cut down on the number of system calls necessary to find | 146 | * This is used to cut down on the number of system calls necessary to find | |
147 | * implicit dependents and their like. Since these searches are made before | 147 | * implicit dependents and their like. Since these searches are made before | |
148 | * any actions are taken, we need not worry about the directory changing due | 148 | * any actions are taken, we need not worry about the directory changing due | |
149 | * to creation commands. If this hampers the style of some makefiles, they | 149 | * to creation commands. If this hampers the style of some makefiles, they | |
150 | * must be changed. | 150 | * must be changed. | |
151 | * | 151 | * | |
152 | * All previously-read directories are kept in openDirs, which is checked | 152 | * All previously-read directories are kept in openDirs, which is checked | |
153 | * first before a directory is opened. | 153 | * first before a directory is opened. | |
154 | * | 154 | * | |
@@ -1635,27 +1635,27 @@ SearchPath_ToFlags(SearchPath *path, con | @@ -1635,27 +1635,27 @@ SearchPath_ToFlags(SearchPath *path, con | |||
1635 | SearchPathNode *ln; | 1635 | SearchPathNode *ln; | |
1636 | 1636 | |||
1637 | Buf_Init(&buf); | 1637 | Buf_Init(&buf); | |
1638 | 1638 | |||
1639 | if (path != NULL) { | 1639 | if (path != NULL) { | |
1640 | for (ln = path->dirs.first; ln != NULL; ln = ln->next) { | 1640 | for (ln = path->dirs.first; ln != NULL; ln = ln->next) { | |
1641 | CachedDir *dir = ln->datum; | 1641 | CachedDir *dir = ln->datum; | |
1642 | Buf_AddStr(&buf, " "); | 1642 | Buf_AddStr(&buf, " "); | |
1643 | Buf_AddStr(&buf, flag); | 1643 | Buf_AddStr(&buf, flag); | |
1644 | Buf_AddStr(&buf, dir->name); | 1644 | Buf_AddStr(&buf, dir->name); | |
1645 | } | 1645 | } | |
1646 | } | 1646 | } | |
1647 | 1647 | |||
1648 | return Buf_Destroy(&buf, FALSE); | 1648 | return Buf_DoneData(&buf); | |
1649 | } | 1649 | } | |
1650 | 1650 | |||
1651 | /* Free the search path and all directories mentioned in it. */ | 1651 | /* Free the search path and all directories mentioned in it. */ | |
1652 | void | 1652 | void | |
1653 | SearchPath_Free(SearchPath *path) | 1653 | SearchPath_Free(SearchPath *path) | |
1654 | { | 1654 | { | |
1655 | SearchPathNode *ln; | 1655 | SearchPathNode *ln; | |
1656 | 1656 | |||
1657 | for (ln = path->dirs.first; ln != NULL; ln = ln->next) { | 1657 | for (ln = path->dirs.first; ln != NULL; ln = ln->next) { | |
1658 | CachedDir *dir = ln->datum; | 1658 | CachedDir *dir = ln->datum; | |
1659 | CachedDir_Unref(dir); | 1659 | CachedDir_Unref(dir); | |
1660 | } | 1660 | } | |
1661 | Lst_Done(&path->dirs); | 1661 | Lst_Done(&path->dirs); |
--- src/usr.bin/make/for.c 2021/01/25 19:39:34 1.138
+++ src/usr.bin/make/for.c 2021/01/30 20:53:29 1.139
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: for.c,v 1.138 2021/01/25 19:39:34 rillig Exp $ */ | 1 | /* $NetBSD: for.c,v 1.139 2021/01/30 20:53:29 rillig Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1992, The Regents of the University of California. | 4 | * Copyright (c) 1992, The Regents of the University of California. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -48,27 +48,27 @@ | @@ -48,27 +48,27 @@ | |||
48 | * body is scanned for variable expressions, and those that match the variable | 48 | * body is scanned for variable expressions, and those that match the variable | |
49 | * names are replaced with expressions of the form ${:U...} or $(:U...). | 49 | * names are replaced with expressions of the form ${:U...} or $(:U...). | |
50 | * After that, the body is treated like a file from an .include directive. | 50 | * After that, the body is treated like a file from an .include directive. | |
51 | * | 51 | * | |
52 | * Interface: | 52 | * Interface: | |
53 | * For_Eval Evaluate the loop in the passed line. | 53 | * For_Eval Evaluate the loop in the passed line. | |
54 | * | 54 | * | |
55 | * For_Run Run accumulated loop | 55 | * For_Run Run accumulated loop | |
56 | */ | 56 | */ | |
57 | 57 | |||
58 | #include "make.h" | 58 | #include "make.h" | |
59 | 59 | |||
60 | /* "@(#)for.c 8.1 (Berkeley) 6/6/93" */ | 60 | /* "@(#)for.c 8.1 (Berkeley) 6/6/93" */ | |
61 | MAKE_RCSID("$NetBSD: for.c,v 1.138 2021/01/25 19:39:34 rillig Exp $"); | 61 | MAKE_RCSID("$NetBSD: for.c,v 1.139 2021/01/30 20:53:29 rillig Exp $"); | |
62 | 62 | |||
63 | 63 | |||
64 | /* One of the variables to the left of the "in" in a .for loop. */ | 64 | /* One of the variables to the left of the "in" in a .for loop. */ | |
65 | typedef struct ForVar { | 65 | typedef struct ForVar { | |
66 | char *name; | 66 | char *name; | |
67 | size_t nameLen; | 67 | size_t nameLen; | |
68 | } ForVar; | 68 | } ForVar; | |
69 | 69 | |||
70 | typedef struct ForLoop { | 70 | typedef struct ForLoop { | |
71 | Buffer body; /* Unexpanded body of the loop */ | 71 | Buffer body; /* Unexpanded body of the loop */ | |
72 | Vector /* of ForVar */ vars; /* Iteration variables */ | 72 | Vector /* of ForVar */ vars; /* Iteration variables */ | |
73 | Words items; /* Substitution items */ | 73 | Words items; /* Substitution items */ | |
74 | Buffer curBody; /* Expanded body of the current iteration */ | 74 | Buffer curBody; /* Expanded body of the current iteration */ | |
@@ -93,36 +93,36 @@ ForLoop_New(void) | @@ -93,36 +93,36 @@ ForLoop_New(void) | |||
93 | Vector_Init(&f->vars, sizeof(ForVar)); | 93 | Vector_Init(&f->vars, sizeof(ForVar)); | |
94 | f->items.words = NULL; | 94 | f->items.words = NULL; | |
95 | f->items.freeIt = NULL; | 95 | f->items.freeIt = NULL; | |
96 | Buf_Init(&f->curBody); | 96 | Buf_Init(&f->curBody); | |
97 | f->short_var = FALSE; | 97 | f->short_var = FALSE; | |
98 | f->sub_next = 0; | 98 | f->sub_next = 0; | |
99 | 99 | |||
100 | return f; | 100 | return f; | |
101 | } | 101 | } | |
102 | 102 | |||
103 | static void | 103 | static void | |
104 | ForLoop_Free(ForLoop *f) | 104 | ForLoop_Free(ForLoop *f) | |
105 | { | 105 | { | |
106 | Buf_Destroy(&f->body, TRUE); | 106 | Buf_Done(&f->body); | |
107 | 107 | |||
108 | while (f->vars.len > 0) { | 108 | while (f->vars.len > 0) { | |
109 | ForVar *var = Vector_Pop(&f->vars); | 109 | ForVar *var = Vector_Pop(&f->vars); | |
110 | free(var->name); | 110 | free(var->name); | |
111 | } | 111 | } | |
112 | Vector_Done(&f->vars); | 112 | Vector_Done(&f->vars); | |
113 | 113 | |||
114 | Words_Free(f->items); | 114 | Words_Free(f->items); | |
115 | Buf_Destroy(&f->curBody, TRUE); | 115 | Buf_Done(&f->curBody); | |
116 | 116 | |||
117 | free(f); | 117 | free(f); | |
118 | } | 118 | } | |
119 | 119 | |||
120 | static void | 120 | static void | |
121 | ForLoop_AddVar(ForLoop *f, const char *name, size_t len) | 121 | ForLoop_AddVar(ForLoop *f, const char *name, size_t len) | |
122 | { | 122 | { | |
123 | ForVar *var = Vector_Push(&f->vars); | 123 | ForVar *var = Vector_Push(&f->vars); | |
124 | var->name = bmake_strldup(name, len); | 124 | var->name = bmake_strldup(name, len); | |
125 | var->nameLen = len; | 125 | var->nameLen = len; | |
126 | } | 126 | } | |
127 | 127 | |||
128 | static Boolean | 128 | static Boolean |
--- src/usr.bin/make/main.c 2021/01/24 20:11:55 1.517
+++ src/usr.bin/make/main.c 2021/01/30 20:53:29 1.518
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: main.c,v 1.517 2021/01/24 20:11:55 rillig Exp $ */ | 1 | /* $NetBSD: main.c,v 1.518 2021/01/30 20:53:29 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. | |
@@ -100,27 +100,27 @@ | @@ -100,27 +100,27 @@ | |||
100 | 100 | |||
101 | #include <errno.h> | 101 | #include <errno.h> | |
102 | #include <signal.h> | 102 | #include <signal.h> | |
103 | #include <stdarg.h> | 103 | #include <stdarg.h> | |
104 | #include <time.h> | 104 | #include <time.h> | |
105 | 105 | |||
106 | #include "make.h" | 106 | #include "make.h" | |
107 | #include "dir.h" | 107 | #include "dir.h" | |
108 | #include "job.h" | 108 | #include "job.h" | |
109 | #include "pathnames.h" | 109 | #include "pathnames.h" | |
110 | #include "trace.h" | 110 | #include "trace.h" | |
111 | 111 | |||
112 | /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ | 112 | /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ | |
113 | MAKE_RCSID("$NetBSD: main.c,v 1.517 2021/01/24 20:11:55 rillig Exp $"); | 113 | MAKE_RCSID("$NetBSD: main.c,v 1.518 2021/01/30 20:53:29 rillig Exp $"); | |
114 | #if defined(MAKE_NATIVE) && !defined(lint) | 114 | #if defined(MAKE_NATIVE) && !defined(lint) | |
115 | __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " | 115 | __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " | |
116 | "The Regents of the University of California. " | 116 | "The Regents of the University of California. " | |
117 | "All rights reserved."); | 117 | "All rights reserved."); | |
118 | #endif | 118 | #endif | |
119 | 119 | |||
120 | CmdOpts opts; | 120 | CmdOpts opts; | |
121 | time_t now; /* Time at start of make */ | 121 | time_t now; /* Time at start of make */ | |
122 | GNode *defaultNode; /* .DEFAULT node */ | 122 | GNode *defaultNode; /* .DEFAULT node */ | |
123 | Boolean allPrecious; /* .PRECIOUS given on line by itself */ | 123 | Boolean allPrecious; /* .PRECIOUS given on line by itself */ | |
124 | Boolean deleteOnError; /* .DELETE_ON_ERROR: set */ | 124 | Boolean deleteOnError; /* .DELETE_ON_ERROR: set */ | |
125 | 125 | |||
126 | static int maxJobTokens; /* -j argument */ | 126 | static int maxJobTokens; /* -j argument */ | |
@@ -1831,27 +1831,27 @@ Cmd_Exec(const char *cmd, const char **e | @@ -1831,27 +1831,27 @@ Cmd_Exec(const char *cmd, const char **e | |||
1831 | Buf_AddBytes(&buf, result, (size_t)bytes_read); | 1831 | Buf_AddBytes(&buf, result, (size_t)bytes_read); | |
1832 | } while (bytes_read > 0 || | 1832 | } while (bytes_read > 0 || | |
1833 | (bytes_read == -1 && errno == EINTR)); | 1833 | (bytes_read == -1 && errno == EINTR)); | |
1834 | if (bytes_read == -1) | 1834 | if (bytes_read == -1) | |
1835 | savederr = errno; | 1835 | savederr = errno; | |
1836 | 1836 | |||
1837 | (void)close(pipefds[0]); /* Close the input side of the pipe. */ | 1837 | (void)close(pipefds[0]); /* Close the input side of the pipe. */ | |
1838 | 1838 | |||
1839 | /* Wait for the process to exit. */ | 1839 | /* Wait for the process to exit. */ | |
1840 | while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0) | 1840 | while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0) | |
1841 | JobReapChild(pid, status, FALSE); | 1841 | JobReapChild(pid, status, FALSE); | |
1842 | 1842 | |||
1843 | res_len = Buf_Len(&buf); | 1843 | res_len = Buf_Len(&buf); | |
1844 | res = Buf_Destroy(&buf, FALSE); | 1844 | res = Buf_DoneData(&buf); | |
1845 | 1845 | |||
1846 | if (savederr != 0) | 1846 | if (savederr != 0) | |
1847 | *errfmt = "Couldn't read shell's output for \"%s\""; | 1847 | *errfmt = "Couldn't read shell's output for \"%s\""; | |
1848 | 1848 | |||
1849 | if (WIFSIGNALED(status)) | 1849 | if (WIFSIGNALED(status)) | |
1850 | *errfmt = "\"%s\" exited on a signal"; | 1850 | *errfmt = "\"%s\" exited on a signal"; | |
1851 | else if (WEXITSTATUS(status) != 0) | 1851 | else if (WEXITSTATUS(status) != 0) | |
1852 | *errfmt = "\"%s\" returned non-zero status"; | 1852 | *errfmt = "\"%s\" returned non-zero status"; | |
1853 | 1853 | |||
1854 | /* Convert newlines to spaces. A final newline is just stripped */ | 1854 | /* Convert newlines to spaces. A final newline is just stripped */ | |
1855 | if (res_len > 0 && res[res_len - 1] == '\n') | 1855 | if (res_len > 0 && res[res_len - 1] == '\n') | |
1856 | res[res_len - 1] = '\0'; | 1856 | res[res_len - 1] = '\0'; | |
1857 | for (cp = res; *cp != '\0'; cp++) | 1857 | for (cp = res; *cp != '\0'; cp++) | |
@@ -2017,27 +2017,27 @@ execDie(const char *af, const char *av) | @@ -2017,27 +2017,27 @@ execDie(const char *af, const char *av) | |||
2017 | 2017 | |||
2018 | Buf_Init(&buf); | 2018 | Buf_Init(&buf); | |
2019 | Buf_AddStr(&buf, progname); | 2019 | Buf_AddStr(&buf, progname); | |
2020 | Buf_AddStr(&buf, ": "); | 2020 | Buf_AddStr(&buf, ": "); | |
2021 | Buf_AddStr(&buf, af); | 2021 | Buf_AddStr(&buf, af); | |
2022 | Buf_AddStr(&buf, "("); | 2022 | Buf_AddStr(&buf, "("); | |
2023 | Buf_AddStr(&buf, av); | 2023 | Buf_AddStr(&buf, av); | |
2024 | Buf_AddStr(&buf, ") failed ("); | 2024 | Buf_AddStr(&buf, ") failed ("); | |
2025 | Buf_AddStr(&buf, strerror(errno)); | 2025 | Buf_AddStr(&buf, strerror(errno)); | |
2026 | Buf_AddStr(&buf, ")\n"); | 2026 | Buf_AddStr(&buf, ")\n"); | |
2027 | 2027 | |||
2028 | write_all(STDERR_FILENO, Buf_GetAll(&buf, NULL), Buf_Len(&buf)); | 2028 | write_all(STDERR_FILENO, Buf_GetAll(&buf, NULL), Buf_Len(&buf)); | |
2029 | 2029 | |||
2030 | Buf_Destroy(&buf, TRUE); | 2030 | Buf_Done(&buf); | |
2031 | _exit(1); | 2031 | _exit(1); | |
2032 | } | 2032 | } | |
2033 | 2033 | |||
2034 | /* purge any relative paths */ | 2034 | /* purge any relative paths */ | |
2035 | static void | 2035 | static void | |
2036 | purge_relative_cached_realpaths(void) | 2036 | purge_relative_cached_realpaths(void) | |
2037 | { | 2037 | { | |
2038 | HashEntry *he, *nhe; | 2038 | HashEntry *he, *nhe; | |
2039 | HashIter hi; | 2039 | HashIter hi; | |
2040 | 2040 | |||
2041 | HashIter_Init(&hi, &cached_realpaths); | 2041 | HashIter_Init(&hi, &cached_realpaths); | |
2042 | he = HashIter_Next(&hi); | 2042 | he = HashIter_Next(&hi); | |
2043 | while (he != NULL) { | 2043 | while (he != NULL) { |
--- src/usr.bin/make/parse.c 2021/01/27 00:02:38 1.533
+++ src/usr.bin/make/parse.c 2021/01/30 20:53:29 1.534
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: parse.c,v 1.533 2021/01/27 00:02:38 rillig Exp $ */ | 1 | /* $NetBSD: parse.c,v 1.534 2021/01/30 20:53:29 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. | |
@@ -99,27 +99,27 @@ | @@ -99,27 +99,27 @@ | |||
99 | 99 | |||
100 | #include <sys/types.h> | 100 | #include <sys/types.h> | |
101 | #include <sys/stat.h> | 101 | #include <sys/stat.h> | |
102 | #include <errno.h> | 102 | #include <errno.h> | |
103 | #include <stdarg.h> | 103 | #include <stdarg.h> | |
104 | #include <stdint.h> | 104 | #include <stdint.h> | |
105 | 105 | |||
106 | #include "make.h" | 106 | #include "make.h" | |
107 | #include "dir.h" | 107 | #include "dir.h" | |
108 | #include "job.h" | 108 | #include "job.h" | |
109 | #include "pathnames.h" | 109 | #include "pathnames.h" | |
110 | 110 | |||
111 | /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ | 111 | /* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ | |
112 | MAKE_RCSID("$NetBSD: parse.c,v 1.533 2021/01/27 00:02:38 rillig Exp $"); | 112 | MAKE_RCSID("$NetBSD: parse.c,v 1.534 2021/01/30 20:53:29 rillig Exp $"); | |
113 | 113 | |||
114 | /* types and constants */ | 114 | /* types and constants */ | |
115 | 115 | |||
116 | /* | 116 | /* | |
117 | * Structure for a file being read ("included file") | 117 | * Structure for a file being read ("included file") | |
118 | */ | 118 | */ | |
119 | typedef struct IFile { | 119 | typedef struct IFile { | |
120 | char *fname; /* name of file (relative? absolute?) */ | 120 | char *fname; /* name of file (relative? absolute?) */ | |
121 | Boolean fromForLoop; /* simulated .include by the .for loop */ | 121 | Boolean fromForLoop; /* simulated .include by the .for loop */ | |
122 | int lineno; /* current line number in file */ | 122 | int lineno; /* current line number in file */ | |
123 | int first_lineno; /* line number of start of text */ | 123 | int first_lineno; /* line number of start of text */ | |
124 | unsigned int cond_depth; /* 'if' nesting when file opened */ | 124 | unsigned int cond_depth; /* 'if' nesting when file opened */ | |
125 | Boolean depending; /* state of doing_depend on EOF */ | 125 | Boolean depending; /* state of doing_depend on EOF */ | |
@@ -445,27 +445,27 @@ loadfile(const char *path, int fd) | @@ -445,27 +445,27 @@ loadfile(const char *path, int fd) | |||
445 | buf.len += (size_t)n; | 445 | buf.len += (size_t)n; | |
446 | } | 446 | } | |
447 | assert(buf.len <= buf.cap); | 447 | assert(buf.len <= buf.cap); | |
448 | 448 | |||
449 | if (!Buf_EndsWith(&buf, '\n')) | 449 | if (!Buf_EndsWith(&buf, '\n')) | |
450 | Buf_AddByte(&buf, '\n'); | 450 | Buf_AddByte(&buf, '\n'); | |
451 | 451 | |||
452 | if (path != NULL) | 452 | if (path != NULL) | |
453 | close(fd); | 453 | close(fd); | |
454 | 454 | |||
455 | { | 455 | { | |
456 | struct loadedfile *lf = loadedfile_create(path, | 456 | struct loadedfile *lf = loadedfile_create(path, | |
457 | buf.data, buf.len); | 457 | buf.data, buf.len); | |
458 | Buf_Destroy(&buf, FALSE); | 458 | Buf_DoneData(&buf); | |
459 | return lf; | 459 | return lf; | |
460 | } | 460 | } | |
461 | } | 461 | } | |
462 | 462 | |||
463 | static void | 463 | static void | |
464 | PrintStackTrace(void) | 464 | PrintStackTrace(void) | |
465 | { | 465 | { | |
466 | const IFile *entries; | 466 | const IFile *entries; | |
467 | size_t i, n; | 467 | size_t i, n; | |
468 | 468 | |||
469 | if (!(DEBUG(PARSE))) | 469 | if (!(DEBUG(PARSE))) | |
470 | return; | 470 | return; | |
471 | 471 |
--- src/usr.bin/make/var.c 2021/01/30 15:48:42 1.783
+++ src/usr.bin/make/var.c 2021/01/30 20:53:29 1.784
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: var.c,v 1.783 2021/01/30 15:48:42 rillig Exp $ */ | 1 | /* $NetBSD: var.c,v 1.784 2021/01/30 20:53:29 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. | |
@@ -121,27 +121,27 @@ | @@ -121,27 +121,27 @@ | |||
121 | #include <regex.h> | 121 | #include <regex.h> | |
122 | #endif | 122 | #endif | |
123 | #include <errno.h> | 123 | #include <errno.h> | |
124 | #include <inttypes.h> | 124 | #include <inttypes.h> | |
125 | #include <limits.h> | 125 | #include <limits.h> | |
126 | #include <time.h> | 126 | #include <time.h> | |
127 | 127 | |||
128 | #include "make.h" | 128 | #include "make.h" | |
129 | #include "dir.h" | 129 | #include "dir.h" | |
130 | #include "job.h" | 130 | #include "job.h" | |
131 | #include "metachar.h" | 131 | #include "metachar.h" | |
132 | 132 | |||
133 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | 133 | /* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ | |
134 | MAKE_RCSID("$NetBSD: var.c,v 1.783 2021/01/30 15:48:42 rillig Exp $"); | 134 | MAKE_RCSID("$NetBSD: var.c,v 1.784 2021/01/30 20:53:29 rillig Exp $"); | |
135 | 135 | |||
136 | typedef enum VarFlags { | 136 | typedef enum VarFlags { | |
137 | VAR_NONE = 0, | 137 | VAR_NONE = 0, | |
138 | 138 | |||
139 | /* | 139 | /* | |
140 | * The variable's value is currently being used by Var_Parse or | 140 | * The variable's value is currently being used by Var_Parse or | |
141 | * Var_Subst. This marker is used to avoid endless recursion. | 141 | * Var_Subst. This marker is used to avoid endless recursion. | |
142 | */ | 142 | */ | |
143 | VAR_IN_USE = 0x01, | 143 | VAR_IN_USE = 0x01, | |
144 | 144 | |||
145 | /* | 145 | /* | |
146 | * The variable comes from the environment. | 146 | * The variable comes from the environment. | |
147 | * These variables are not registered in any GNode, therefore they | 147 | * These variables are not registered in any GNode, therefore they | |
@@ -446,27 +446,30 @@ VarFind(const char *name, GNode *ctxt, B | @@ -446,27 +446,30 @@ VarFind(const char *name, GNode *ctxt, B | |||
446 | * v the variable | 446 | * v the variable | |
447 | * freeValue true if the variable value should be freed as well | 447 | * freeValue true if the variable value should be freed as well | |
448 | * | 448 | * | |
449 | * Results: | 449 | * Results: | |
450 | * TRUE if it is an environment variable, FALSE otherwise. | 450 | * TRUE if it is an environment variable, FALSE otherwise. | |
451 | */ | 451 | */ | |
452 | static Boolean | 452 | static Boolean | |
453 | VarFreeEnv(Var *v, Boolean freeValue) | 453 | VarFreeEnv(Var *v, Boolean freeValue) | |
454 | { | 454 | { | |
455 | if (!(v->flags & VAR_FROM_ENV)) | 455 | if (!(v->flags & VAR_FROM_ENV)) | |
456 | return FALSE; | 456 | return FALSE; | |
457 | 457 | |||
458 | FStr_Done(&v->name); | 458 | FStr_Done(&v->name); | |
459 | Buf_Destroy(&v->val, freeValue); | 459 | if (freeValue) | |
460 | Buf_Done(&v->val); | |||
461 | else | |||
462 | Buf_DoneData(&v->val); | |||
460 | free(v); | 463 | free(v); | |
461 | return TRUE; | 464 | return TRUE; | |
462 | } | 465 | } | |
463 | 466 | |||
464 | /* | 467 | /* | |
465 | * Add a new variable of the given name and value to the given context. | 468 | * Add a new variable of the given name and value to the given context. | |
466 | * The name and val arguments are duplicated so they may safely be freed. | 469 | * The name and val arguments are duplicated so they may safely be freed. | |
467 | */ | 470 | */ | |
468 | static void | 471 | static void | |
469 | VarAdd(const char *name, const char *val, GNode *ctxt, VarSetFlags flags) | 472 | VarAdd(const char *name, const char *val, GNode *ctxt, VarSetFlags flags) | |
470 | { | 473 | { | |
471 | HashEntry *he = HashTable_CreateEntry(&ctxt->vars, name, NULL); | 474 | HashEntry *he = HashTable_CreateEntry(&ctxt->vars, name, NULL); | |
472 | Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), val, | 475 | Var *v = VarNew(FStr_InitRefer(/* aliased to */ he->key), val, | |
@@ -489,27 +492,27 @@ Var_DeleteVar(const char *varname, GNode | @@ -489,27 +492,27 @@ Var_DeleteVar(const char *varname, GNode | |||
489 | if (he == NULL) { | 492 | if (he == NULL) { | |
490 | DEBUG2(VAR, "%s:delete %s (not found)\n", ctxt->name, varname); | 493 | DEBUG2(VAR, "%s:delete %s (not found)\n", ctxt->name, varname); | |
491 | return; | 494 | return; | |
492 | } | 495 | } | |
493 | 496 | |||
494 | DEBUG2(VAR, "%s:delete %s\n", ctxt->name, varname); | 497 | DEBUG2(VAR, "%s:delete %s\n", ctxt->name, varname); | |
495 | v = HashEntry_Get(he); | 498 | v = HashEntry_Get(he); | |
496 | if (v->flags & VAR_EXPORTED) | 499 | if (v->flags & VAR_EXPORTED) | |
497 | unsetenv(v->name.str); | 500 | unsetenv(v->name.str); | |
498 | if (strcmp(v->name.str, MAKE_EXPORTED) == 0) | 501 | if (strcmp(v->name.str, MAKE_EXPORTED) == 0) | |
499 | var_exportedVars = VAR_EXPORTED_NONE; | 502 | var_exportedVars = VAR_EXPORTED_NONE; | |
500 | assert(v->name.freeIt == NULL); | 503 | assert(v->name.freeIt == NULL); | |
501 | HashTable_DeleteEntry(&ctxt->vars, he); | 504 | HashTable_DeleteEntry(&ctxt->vars, he); | |
502 | Buf_Destroy(&v->val, TRUE); | 505 | Buf_Done(&v->val); | |
503 | free(v); | 506 | free(v); | |
504 | } | 507 | } | |
505 | 508 | |||
506 | /* | 509 | /* | |
507 | * Remove a variable from a context, freeing all related memory as well. | 510 | * Remove a variable from a context, freeing all related memory as well. | |
508 | * The variable name is expanded once. | 511 | * The variable name is expanded once. | |
509 | */ | 512 | */ | |
510 | void | 513 | void | |
511 | Var_Delete(const char *name, GNode *ctxt) | 514 | Var_Delete(const char *name, GNode *ctxt) | |
512 | { | 515 | { | |
513 | FStr varname = FStr_InitRefer(name); | 516 | FStr varname = FStr_InitRefer(name); | |
514 | 517 | |||
515 | if (strchr(varname.str, '$') != NULL) { | 518 | if (strchr(varname.str, '$') != NULL) { | |
@@ -1204,29 +1207,29 @@ SepBuf_AddBytes(SepBuf *buf, const char | @@ -1204,29 +1207,29 @@ SepBuf_AddBytes(SepBuf *buf, const char | |||
1204 | static void | 1207 | static void | |
1205 | SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end) | 1208 | SepBuf_AddBytesBetween(SepBuf *buf, const char *start, const char *end) | |
1206 | { | 1209 | { | |
1207 | SepBuf_AddBytes(buf, start, (size_t)(end - start)); | 1210 | SepBuf_AddBytes(buf, start, (size_t)(end - start)); | |
1208 | } | 1211 | } | |
1209 | 1212 | |||
1210 | static void | 1213 | static void | |
1211 | SepBuf_AddStr(SepBuf *buf, const char *str) | 1214 | SepBuf_AddStr(SepBuf *buf, const char *str) | |
1212 | { | 1215 | { | |
1213 | SepBuf_AddBytes(buf, str, strlen(str)); | 1216 | SepBuf_AddBytes(buf, str, strlen(str)); | |
1214 | } | 1217 | } | |
1215 | 1218 | |||
1216 | static char * | 1219 | static char * | |
1217 | SepBuf_Destroy(SepBuf *buf, Boolean free_buf) | 1220 | SepBuf_DoneData(SepBuf *buf) | |
1218 | { | 1221 | { | |
1219 | return Buf_Destroy(&buf->buf, free_buf); | 1222 | return Buf_DoneData(&buf->buf); | |
1220 | } | 1223 | } | |
1221 | 1224 | |||
1222 | 1225 | |||
1223 | /* | 1226 | /* | |
1224 | * This callback for ModifyWords gets a single word from a variable expression | 1227 | * This callback for ModifyWords gets a single word from a variable expression | |
1225 | * and typically adds a modification of this word to the buffer. It may also | 1228 | * and typically adds a modification of this word to the buffer. It may also | |
1226 | * do nothing or add several words. | 1229 | * do nothing or add several words. | |
1227 | * | 1230 | * | |
1228 | * For example, in ${:Ua b c:M*2}, the callback is called 3 times, once for | 1231 | * For example, in ${:Ua b c:M*2}, the callback is called 3 times, once for | |
1229 | * each word of "a b c". | 1232 | * each word of "a b c". | |
1230 | */ | 1233 | */ | |
1231 | typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data); | 1234 | typedef void (*ModifyWordsCallback)(const char *word, SepBuf *buf, void *data); | |
1232 | 1235 | |||
@@ -1676,27 +1679,27 @@ VarSelectWords(char sep, Boolean oneBigW | @@ -1676,27 +1679,27 @@ VarSelectWords(char sep, Boolean oneBigW | |||
1676 | } else { | 1679 | } else { | |
1677 | start = first < 1 ? 0 : first - 1; | 1680 | start = first < 1 ? 0 : first - 1; | |
1678 | end = last > len ? len : last; | 1681 | end = last > len ? len : last; | |
1679 | step = 1; | 1682 | step = 1; | |
1680 | } | 1683 | } | |
1681 | 1684 | |||
1682 | for (i = start; (step < 0) == (i >= end); i += step) { | 1685 | for (i = start; (step < 0) == (i >= end); i += step) { | |
1683 | SepBuf_AddStr(&buf, words.words[i]); | 1686 | SepBuf_AddStr(&buf, words.words[i]); | |
1684 | SepBuf_Sep(&buf); | 1687 | SepBuf_Sep(&buf); | |
1685 | } | 1688 | } | |
1686 | 1689 | |||
1687 | Words_Free(words); | 1690 | Words_Free(words); | |
1688 | 1691 | |||
1689 | return SepBuf_Destroy(&buf, FALSE); | 1692 | return SepBuf_DoneData(&buf); | |
1690 | } | 1693 | } | |
1691 | 1694 | |||
1692 | 1695 | |||
1693 | /* | 1696 | /* | |
1694 | * Callback for ModifyWords to implement the :tA modifier. | 1697 | * Callback for ModifyWords to implement the :tA modifier. | |
1695 | * Replace each word with the result of realpath() if successful. | 1698 | * Replace each word with the result of realpath() if successful. | |
1696 | */ | 1699 | */ | |
1697 | /*ARGSUSED*/ | 1700 | /*ARGSUSED*/ | |
1698 | static void | 1701 | static void | |
1699 | ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) | 1702 | ModifyWord_Realpath(const char *word, SepBuf *buf, void *data MAKE_ATTR_UNUSED) | |
1700 | { | 1703 | { | |
1701 | struct stat st; | 1704 | struct stat st; | |
1702 | char rbuf[MAXPATHLEN]; | 1705 | char rbuf[MAXPATHLEN]; | |
@@ -1721,67 +1724,67 @@ ModifyWord_Realpath(const char *word, Se | @@ -1721,67 +1724,67 @@ ModifyWord_Realpath(const char *word, Se | |||
1721 | */ | 1724 | */ | |
1722 | static char * | 1725 | static char * | |
1723 | ModifyWords(const char *str, | 1726 | ModifyWords(const char *str, | |
1724 | ModifyWordsCallback modifyWord, void *modifyWord_args, | 1727 | ModifyWordsCallback modifyWord, void *modifyWord_args, | |
1725 | Boolean oneBigWord, char sep) | 1728 | Boolean oneBigWord, char sep) | |
1726 | { | 1729 | { | |
1727 | SepBuf result; | 1730 | SepBuf result; | |
1728 | Words words; | 1731 | Words words; | |
1729 | size_t i; | 1732 | size_t i; | |
1730 | 1733 | |||
1731 | if (oneBigWord) { | 1734 | if (oneBigWord) { | |
1732 | SepBuf_Init(&result, sep); | 1735 | SepBuf_Init(&result, sep); | |
1733 | modifyWord(str, &result, modifyWord_args); | 1736 | modifyWord(str, &result, modifyWord_args); | |
1734 | return SepBuf_Destroy(&result, FALSE); | 1737 | return SepBuf_DoneData(&result); | |
1735 | } | 1738 | } | |
1736 | 1739 | |||
1737 | SepBuf_Init(&result, sep); | 1740 | SepBuf_Init(&result, sep); | |
1738 | 1741 | |||
1739 | words = Str_Words(str, FALSE); | 1742 | words = Str_Words(str, FALSE); | |
1740 | 1743 | |||
1741 | DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n", | 1744 | DEBUG2(VAR, "ModifyWords: split \"%s\" into %u words\n", | |
1742 | str, (unsigned)words.len); | 1745 | str, (unsigned)words.len); | |
1743 | 1746 | |||
1744 | for (i = 0; i < words.len; i++) { | 1747 | for (i = 0; i < words.len; i++) { | |
1745 | modifyWord(words.words[i], &result, modifyWord_args); | 1748 | modifyWord(words.words[i], &result, modifyWord_args); | |
1746 | if (Buf_Len(&result.buf) > 0) | 1749 | if (Buf_Len(&result.buf) > 0) | |
1747 | SepBuf_Sep(&result); | 1750 | SepBuf_Sep(&result); | |
1748 | } | 1751 | } | |
1749 | 1752 | |||
1750 | Words_Free(words); | 1753 | Words_Free(words); | |
1751 | 1754 | |||
1752 | return SepBuf_Destroy(&result, FALSE); | 1755 | return SepBuf_DoneData(&result); | |
1753 | } | 1756 | } | |
1754 | 1757 | |||
1755 | 1758 | |||
1756 | static char * | 1759 | static char * | |
1757 | Words_JoinFree(Words words) | 1760 | Words_JoinFree(Words words) | |
1758 | { | 1761 | { | |
1759 | Buffer buf; | 1762 | Buffer buf; | |
1760 | size_t i; | 1763 | size_t i; | |
1761 | 1764 | |||
1762 | Buf_Init(&buf); | 1765 | Buf_Init(&buf); | |
1763 | 1766 | |||
1764 | for (i = 0; i < words.len; i++) { | 1767 | for (i = 0; i < words.len; i++) { | |
1765 | if (i != 0) { | 1768 | if (i != 0) { | |
1766 | /* XXX: Use st->sep instead of ' ', for consistency. */ | 1769 | /* XXX: Use st->sep instead of ' ', for consistency. */ | |
1767 | Buf_AddByte(&buf, ' '); | 1770 | Buf_AddByte(&buf, ' '); | |
1768 | } | 1771 | } | |
1769 | Buf_AddStr(&buf, words.words[i]); | 1772 | Buf_AddStr(&buf, words.words[i]); | |
1770 | } | 1773 | } | |
1771 | 1774 | |||
1772 | Words_Free(words); | 1775 | Words_Free(words); | |
1773 | 1776 | |||
1774 | return Buf_Destroy(&buf, FALSE); | 1777 | return Buf_DoneData(&buf); | |
1775 | } | 1778 | } | |
1776 | 1779 | |||
1777 | /* Remove adjacent duplicate words. */ | 1780 | /* Remove adjacent duplicate words. */ | |
1778 | static char * | 1781 | static char * | |
1779 | VarUniq(const char *str) | 1782 | VarUniq(const char *str) | |
1780 | { | 1783 | { | |
1781 | Words words = Str_Words(str, FALSE); | 1784 | Words words = Str_Words(str, FALSE); | |
1782 | 1785 | |||
1783 | if (words.len > 1) { | 1786 | if (words.len > 1) { | |
1784 | size_t i, j; | 1787 | size_t i, j; | |
1785 | for (j = 0, i = 1; i < words.len; i++) | 1788 | for (j = 0, i = 1; i < words.len; i++) | |
1786 | if (strcmp(words.words[i], words.words[j]) != 0 && | 1789 | if (strcmp(words.words[i], words.words[j]) != 0 && | |
1787 | (++j != i)) | 1790 | (++j != i)) | |
@@ -1808,27 +1811,27 @@ VarQuote(const char *str, Boolean quoteD | @@ -1808,27 +1811,27 @@ VarQuote(const char *str, Boolean quoteD | |||
1808 | const char *newline = Shell_GetNewline(); | 1811 | const char *newline = Shell_GetNewline(); | |
1809 | if (newline == NULL) | 1812 | if (newline == NULL) | |
1810 | newline = "\\\n"; | 1813 | newline = "\\\n"; | |
1811 | Buf_AddStr(&buf, newline); | 1814 | Buf_AddStr(&buf, newline); | |
1812 | continue; | 1815 | continue; | |
1813 | } | 1816 | } | |
1814 | if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str)) | 1817 | if (ch_isspace(*str) || is_shell_metachar((unsigned char)*str)) | |
1815 | Buf_AddByte(&buf, '\\'); | 1818 | Buf_AddByte(&buf, '\\'); | |
1816 | Buf_AddByte(&buf, *str); | 1819 | Buf_AddByte(&buf, *str); | |
1817 | if (quoteDollar && *str == '$') | 1820 | if (quoteDollar && *str == '$') | |
1818 | Buf_AddStr(&buf, "\\$"); | 1821 | Buf_AddStr(&buf, "\\$"); | |
1819 | } | 1822 | } | |
1820 | 1823 | |||
1821 | return Buf_Destroy(&buf, FALSE); | 1824 | return Buf_DoneData(&buf); | |
1822 | } | 1825 | } | |
1823 | 1826 | |||
1824 | /* | 1827 | /* | |
1825 | * Compute the 32-bit hash of the given string, using the MurmurHash3 | 1828 | * Compute the 32-bit hash of the given string, using the MurmurHash3 | |
1826 | * algorithm. Output is encoded as 8 hex digits, in Little Endian order. | 1829 | * algorithm. Output is encoded as 8 hex digits, in Little Endian order. | |
1827 | */ | 1830 | */ | |
1828 | static char * | 1831 | static char * | |
1829 | VarHash(const char *str) | 1832 | VarHash(const char *str) | |
1830 | { | 1833 | { | |
1831 | static const char hexdigits[16] = "0123456789abcdef"; | 1834 | static const char hexdigits[16] = "0123456789abcdef"; | |
1832 | const unsigned char *ustr = (const unsigned char *)str; | 1835 | const unsigned char *ustr = (const unsigned char *)str; | |
1833 | 1836 | |||
1834 | uint32_t h = 0x971e137bU; | 1837 | uint32_t h = 0x971e137bU; | |
@@ -2154,27 +2157,27 @@ ParseModifierPartSubst( | @@ -2154,27 +2157,27 @@ ParseModifierPartSubst( | |||
2154 | 2157 | |||
2155 | if (*p != delim) { | 2158 | if (*p != delim) { | |
2156 | *pp = p; | 2159 | *pp = p; | |
2157 | Error("Unfinished modifier for %s ('%c' missing)", | 2160 | Error("Unfinished modifier for %s ('%c' missing)", | |
2158 | st->var->name.str, delim); | 2161 | st->var->name.str, delim); | |
2159 | *out_part = NULL; | 2162 | *out_part = NULL; | |
2160 | return VPR_ERR; | 2163 | return VPR_ERR; | |
2161 | } | 2164 | } | |
2162 | 2165 | |||
2163 | *pp = ++p; | 2166 | *pp = ++p; | |
2164 | if (out_length != NULL) | 2167 | if (out_length != NULL) | |
2165 | *out_length = Buf_Len(&buf); | 2168 | *out_length = Buf_Len(&buf); | |
2166 | 2169 | |||
2167 | *out_part = Buf_Destroy(&buf, FALSE); | 2170 | *out_part = Buf_DoneData(&buf); | |
2168 | DEBUG1(VAR, "Modifier part: \"%s\"\n", *out_part); | 2171 | DEBUG1(VAR, "Modifier part: \"%s\"\n", *out_part); | |
2169 | return VPR_OK; | 2172 | return VPR_OK; | |
2170 | } | 2173 | } | |
2171 | 2174 | |||
2172 | /* | 2175 | /* | |
2173 | * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or | 2176 | * Parse a part of a modifier such as the "from" and "to" in :S/from/to/ or | |
2174 | * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and | 2177 | * the "var" or "replacement ${var}" in :@var@replacement ${var}@, up to and | |
2175 | * including the next unescaped delimiter. The delimiter, as well as the | 2178 | * including the next unescaped delimiter. The delimiter, as well as the | |
2176 | * backslash or the dollar, can be escaped with a backslash. | 2179 | * backslash or the dollar, can be escaped with a backslash. | |
2177 | * | 2180 | * | |
2178 | * Return the parsed (and possibly expanded) string, or NULL if no delimiter | 2181 | * Return the parsed (and possibly expanded) string, or NULL if no delimiter | |
2179 | * was found. On successful return, the parsing position pp points right | 2182 | * was found. On successful return, the parsing position pp points right | |
2180 | * after the delimiter. The delimiter is not included in the returned | 2183 | * after the delimiter. The delimiter is not included in the returned | |
@@ -2355,30 +2358,30 @@ ApplyModifier_Defined(const char **pp, c | @@ -2355,30 +2358,30 @@ ApplyModifier_Defined(const char **pp, c | |||
2355 | FStr_Done(&nested_val); | 2358 | FStr_Done(&nested_val); | |
2356 | continue; | 2359 | continue; | |
2357 | } | 2360 | } | |
2358 | 2361 | |||
2359 | /* Ordinary text */ | 2362 | /* Ordinary text */ | |
2360 | Buf_AddByte(&buf, *p); | 2363 | Buf_AddByte(&buf, *p); | |
2361 | p++; | 2364 | p++; | |
2362 | } | 2365 | } | |
2363 | *pp = p; | 2366 | *pp = p; | |
2364 | 2367 | |||
2365 | ApplyModifiersState_Define(st); | 2368 | ApplyModifiersState_Define(st); | |
2366 | 2369 | |||
2367 | if (eflags & VARE_WANTRES) { | 2370 | if (eflags & VARE_WANTRES) { | |
2368 | st->newVal = FStr_InitOwn(Buf_Destroy(&buf, FALSE)); | 2371 | st->newVal = FStr_InitOwn(Buf_DoneData(&buf)); | |
2369 | } else { | 2372 | } else { | |
2370 | st->newVal = FStr_InitRefer(val); | 2373 | st->newVal = FStr_InitRefer(val); | |
2371 | Buf_Destroy(&buf, TRUE); | 2374 | Buf_Done(&buf); | |
2372 | } | 2375 | } | |
2373 | return AMR_OK; | 2376 | return AMR_OK; | |
2374 | } | 2377 | } | |
2375 | 2378 | |||
2376 | /* :L */ | 2379 | /* :L */ | |
2377 | static ApplyModifierResult | 2380 | static ApplyModifierResult | |
2378 | ApplyModifier_Literal(const char **pp, ApplyModifiersState *st) | 2381 | ApplyModifier_Literal(const char **pp, ApplyModifiersState *st) | |
2379 | { | 2382 | { | |
2380 | ApplyModifiersState_Define(st); | 2383 | ApplyModifiersState_Define(st); | |
2381 | st->newVal = FStr_InitOwn(bmake_strdup(st->var->name.str)); | 2384 | st->newVal = FStr_InitOwn(bmake_strdup(st->var->name.str)); | |
2382 | (*pp)++; | 2385 | (*pp)++; | |
2383 | return AMR_OK; | 2386 | return AMR_OK; | |
2384 | } | 2387 | } | |
@@ -2553,27 +2556,27 @@ ApplyModifier_Range(const char **pp, con | @@ -2553,27 +2556,27 @@ ApplyModifier_Range(const char **pp, con | |||
2553 | Words_Free(words); | 2556 | Words_Free(words); | |
2554 | } | 2557 | } | |
2555 | 2558 | |||
2556 | Buf_Init(&buf); | 2559 | Buf_Init(&buf); | |
2557 | 2560 | |||
2558 | for (i = 0; i < n; i++) { | 2561 | for (i = 0; i < n; i++) { | |
2559 | if (i != 0) { | 2562 | if (i != 0) { | |
2560 | /* XXX: Use st->sep instead of ' ', for consistency. */ | 2563 | /* XXX: Use st->sep instead of ' ', for consistency. */ | |
2561 | Buf_AddByte(&buf, ' '); | 2564 | Buf_AddByte(&buf, ' '); | |
2562 | } | 2565 | } | |
2563 | Buf_AddInt(&buf, 1 + (int)i); | 2566 | Buf_AddInt(&buf, 1 + (int)i); | |
2564 | } | 2567 | } | |
2565 | 2568 | |||
2566 | st->newVal = FStr_InitOwn(Buf_Destroy(&buf, FALSE)); | 2569 | st->newVal = FStr_InitOwn(Buf_DoneData(&buf)); | |
2567 | return AMR_OK; | 2570 | return AMR_OK; | |
2568 | } | 2571 | } | |
2569 | 2572 | |||
2570 | /* :Mpattern or :Npattern */ | 2573 | /* :Mpattern or :Npattern */ | |
2571 | static ApplyModifierResult | 2574 | static ApplyModifierResult | |
2572 | ApplyModifier_Match(const char **pp, const char *val, ApplyModifiersState *st) | 2575 | ApplyModifier_Match(const char **pp, const char *val, ApplyModifiersState *st) | |
2573 | { | 2576 | { | |
2574 | const char *mod = *pp; | 2577 | const char *mod = *pp; | |
2575 | Boolean copy = FALSE; /* pattern should be, or has been, copied */ | 2578 | Boolean copy = FALSE; /* pattern should be, or has been, copied */ | |
2576 | Boolean needSubst = FALSE; | 2579 | Boolean needSubst = FALSE; | |
2577 | const char *endpat; | 2580 | const char *endpat; | |
2578 | char *pattern; | 2581 | char *pattern; | |
2579 | ModifyWordsCallback callback; | 2582 | ModifyWordsCallback callback; | |
@@ -2978,27 +2981,27 @@ ApplyModifier_Words(const char **pp, con | @@ -2978,27 +2981,27 @@ ApplyModifier_Words(const char **pp, con | |||
2978 | if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ | 2981 | if (estr[0] == '#' && estr[1] == '\0') { /* Found ":[#]" */ | |
2979 | if (st->oneBigWord) { | 2982 | if (st->oneBigWord) { | |
2980 | st->newVal = FStr_InitRefer("1"); | 2983 | st->newVal = FStr_InitRefer("1"); | |
2981 | } else { | 2984 | } else { | |
2982 | Buffer buf; | 2985 | Buffer buf; | |
2983 | 2986 | |||
2984 | Words words = Str_Words(val, FALSE); | 2987 | Words words = Str_Words(val, FALSE); | |
2985 | size_t ac = words.len; | 2988 | size_t ac = words.len; | |
2986 | Words_Free(words); | 2989 | Words_Free(words); | |
2987 | 2990 | |||
2988 | /* 3 digits + '\0' is usually enough */ | 2991 | /* 3 digits + '\0' is usually enough */ | |
2989 | Buf_InitSize(&buf, 4); | 2992 | Buf_InitSize(&buf, 4); | |
2990 | Buf_AddInt(&buf, (int)ac); | 2993 | Buf_AddInt(&buf, (int)ac); | |
2991 | st->newVal = FStr_InitOwn(Buf_Destroy(&buf, FALSE)); | 2994 | st->newVal = FStr_InitOwn(Buf_DoneData(&buf)); | |
2992 | } | 2995 | } | |
2993 | goto ok; | 2996 | goto ok; | |
2994 | } | 2997 | } | |
2995 | 2998 | |||
2996 | if (estr[0] == '*' && estr[1] == '\0') { | 2999 | if (estr[0] == '*' && estr[1] == '\0') { | |
2997 | /* Found ":[*]" */ | 3000 | /* Found ":[*]" */ | |
2998 | st->oneBigWord = TRUE; | 3001 | st->oneBigWord = TRUE; | |
2999 | st->newVal = FStr_InitRefer(val); | 3002 | st->newVal = FStr_InitRefer(val); | |
3000 | goto ok; | 3003 | goto ok; | |
3001 | } | 3004 | } | |
3002 | 3005 | |||
3003 | if (estr[0] == '@' && estr[1] == '\0') { | 3006 | if (estr[0] == '@' && estr[1] == '\0') { | |
3004 | /* Found ":[@]" */ | 3007 | /* Found ":[@]" */ | |
@@ -3793,27 +3796,27 @@ ParseVarname(const char **pp, char start | @@ -3793,27 +3796,27 @@ ParseVarname(const char **pp, char start | |||
3793 | if (*p == '$') { | 3796 | if (*p == '$') { | |
3794 | FStr nested_val; | 3797 | FStr nested_val; | |
3795 | (void)Var_Parse(&p, ctxt, eflags, &nested_val); | 3798 | (void)Var_Parse(&p, ctxt, eflags, &nested_val); | |
3796 | /* TODO: handle errors */ | 3799 | /* TODO: handle errors */ | |
3797 | Buf_AddStr(&buf, nested_val.str); | 3800 | Buf_AddStr(&buf, nested_val.str); | |
3798 | FStr_Done(&nested_val); | 3801 | FStr_Done(&nested_val); | |
3799 | } else { | 3802 | } else { | |
3800 | Buf_AddByte(&buf, *p); | 3803 | Buf_AddByte(&buf, *p); | |
3801 | p++; | 3804 | p++; | |
3802 | } | 3805 | } | |
3803 | } | 3806 | } | |
3804 | *pp = p; | 3807 | *pp = p; | |
3805 | *out_varname_len = Buf_Len(&buf); | 3808 | *out_varname_len = Buf_Len(&buf); | |
3806 | return Buf_Destroy(&buf, FALSE); | 3809 | return Buf_DoneData(&buf); | |
3807 | } | 3810 | } | |
3808 | 3811 | |||
3809 | static VarParseResult | 3812 | static VarParseResult | |
3810 | ValidShortVarname(char varname, const char *start) | 3813 | ValidShortVarname(char varname, const char *start) | |
3811 | { | 3814 | { | |
3812 | switch (varname) { | 3815 | switch (varname) { | |
3813 | case '\0': | 3816 | case '\0': | |
3814 | case ')': | 3817 | case ')': | |
3815 | case '}': | 3818 | case '}': | |
3816 | case ':': | 3819 | case ':': | |
3817 | case '$': | 3820 | case '$': | |
3818 | break; /* and continue below */ | 3821 | break; /* and continue below */ | |
3819 | default: | 3822 | default: | |
@@ -4060,27 +4063,27 @@ ParseVarnameLong( | @@ -4060,27 +4063,27 @@ ParseVarnameLong( | |||
4060 | 4063 | |||
4061 | *out_TRUE_endc = endc; | 4064 | *out_TRUE_endc = endc; | |
4062 | *out_TRUE_p = p; | 4065 | *out_TRUE_p = p; | |
4063 | *out_TRUE_v = v; | 4066 | *out_TRUE_v = v; | |
4064 | *out_TRUE_haveModifier = haveModifier; | 4067 | *out_TRUE_haveModifier = haveModifier; | |
4065 | *out_TRUE_dynamic = dynamic; | 4068 | *out_TRUE_dynamic = dynamic; | |
4066 | return TRUE; | 4069 | return TRUE; | |
4067 | } | 4070 | } | |
4068 | 4071 | |||
4069 | /* Free the environment variable now since we own it. */ | 4072 | /* Free the environment variable now since we own it. */ | |
4070 | static void | 4073 | static void | |
4071 | FreeEnvVar(void **out_val_freeIt, Var *v, const char *value) | 4074 | FreeEnvVar(void **out_val_freeIt, Var *v, const char *value) | |
4072 | { | 4075 | { | |
4073 | char *varValue = Buf_Destroy(&v->val, FALSE); | 4076 | char *varValue = Buf_DoneData(&v->val); | |
4074 | if (value == varValue) | 4077 | if (value == varValue) | |
4075 | *out_val_freeIt = varValue; | 4078 | *out_val_freeIt = varValue; | |
4076 | else | 4079 | else | |
4077 | free(varValue); | 4080 | free(varValue); | |
4078 | 4081 | |||
4079 | FStr_Done(&v->name); | 4082 | FStr_Done(&v->name); | |
4080 | free(v); | 4083 | free(v); | |
4081 | } | 4084 | } | |
4082 | 4085 | |||
4083 | /* | 4086 | /* | |
4084 | * Given the start of a variable expression (such as $v, $(VAR), | 4087 | * Given the start of a variable expression (such as $v, $(VAR), | |
4085 | * ${VAR:Mpattern}), extract the variable name and value, and the modifiers, | 4088 | * ${VAR:Mpattern}), extract the variable name and value, and the modifiers, | |
4086 | * if any. While doing that, apply the modifiers to the value of the | 4089 | * if any. While doing that, apply the modifiers to the value of the | |
@@ -4231,27 +4234,27 @@ Var_Parse(const char **pp, GNode *ctxt, | @@ -4231,27 +4234,27 @@ Var_Parse(const char **pp, GNode *ctxt, | |||
4231 | if (dynamic) { | 4234 | if (dynamic) { | |
4232 | value = FStr_InitOwn(bmake_strsedup(start, p)); | 4235 | value = FStr_InitOwn(bmake_strsedup(start, p)); | |
4233 | } else { | 4236 | } else { | |
4234 | /* | 4237 | /* | |
4235 | * The expression is still undefined, | 4238 | * The expression is still undefined, | |
4236 | * therefore discard the actual value and | 4239 | * therefore discard the actual value and | |
4237 | * return an error marker instead. | 4240 | * return an error marker instead. | |
4238 | */ | 4241 | */ | |
4239 | value = FStr_InitRefer(eflags & VARE_UNDEFERR | 4242 | value = FStr_InitRefer(eflags & VARE_UNDEFERR | |
4240 | ? var_Error : varUndefined); | 4243 | ? var_Error : varUndefined); | |
4241 | } | 4244 | } | |
4242 | } | 4245 | } | |
4243 | if (value.str != Buf_GetAll(&v->val, NULL)) | 4246 | if (value.str != Buf_GetAll(&v->val, NULL)) | |
4244 | Buf_Destroy(&v->val, TRUE); | 4247 | Buf_Done(&v->val); | |
4245 | FStr_Done(&v->name); | 4248 | FStr_Done(&v->name); | |
4246 | free(v); | 4249 | free(v); | |
4247 | } | 4250 | } | |
4248 | *out_val = (FStr){ value.str, value.freeIt }; | 4251 | *out_val = (FStr){ value.str, value.freeIt }; | |
4249 | return VPR_OK; /* XXX: Is not correct in all cases */ | 4252 | return VPR_OK; /* XXX: Is not correct in all cases */ | |
4250 | } | 4253 | } | |
4251 | 4254 | |||
4252 | static void | 4255 | static void | |
4253 | VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalFlags eflags) | 4256 | VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalFlags eflags) | |
4254 | { | 4257 | { | |
4255 | /* | 4258 | /* | |
4256 | * A dollar sign may be escaped with another dollar | 4259 | * A dollar sign may be escaped with another dollar | |
4257 | * sign. | 4260 | * sign. | |
@@ -4355,27 +4358,27 @@ Var_Subst(const char *str, GNode *ctxt, | @@ -4355,27 +4358,27 @@ Var_Subst(const char *str, GNode *ctxt, | |||
4355 | 4358 | |||
4356 | Buf_Init(&res); | 4359 | Buf_Init(&res); | |
4357 | errorReported = FALSE; | 4360 | errorReported = FALSE; | |
4358 | 4361 | |||
4359 | while (*p != '\0') { | 4362 | while (*p != '\0') { | |
4360 | if (p[0] == '$' && p[1] == '$') | 4363 | if (p[0] == '$' && p[1] == '$') | |
4361 | VarSubstDollarDollar(&p, &res, eflags); | 4364 | VarSubstDollarDollar(&p, &res, eflags); | |
4362 | else if (p[0] == '$') | 4365 | else if (p[0] == '$') | |
4363 | VarSubstExpr(&p, &res, ctxt, eflags, &errorReported); | 4366 | VarSubstExpr(&p, &res, ctxt, eflags, &errorReported); | |
4364 | else | 4367 | else | |
4365 | VarSubstPlain(&p, &res); | 4368 | VarSubstPlain(&p, &res); | |
4366 | } | 4369 | } | |
4367 | 4370 | |||
4368 | *out_res = Buf_DestroyCompact(&res); | 4371 | *out_res = Buf_DoneDataCompact(&res); | |
4369 | return VPR_OK; | 4372 | return VPR_OK; | |
4370 | } | 4373 | } | |
4371 | 4374 | |||
4372 | /* Initialize the variables module. */ | 4375 | /* Initialize the variables module. */ | |
4373 | void | 4376 | void | |
4374 | Var_Init(void) | 4377 | Var_Init(void) | |
4375 | { | 4378 | { | |
4376 | VAR_INTERNAL = GNode_New("Internal"); | 4379 | VAR_INTERNAL = GNode_New("Internal"); | |
4377 | VAR_GLOBAL = GNode_New("Global"); | 4380 | VAR_GLOBAL = GNode_New("Global"); | |
4378 | VAR_CMDLINE = GNode_New("Command"); | 4381 | VAR_CMDLINE = GNode_New("Command"); | |
4379 | } | 4382 | } | |
4380 | 4383 | |||
4381 | /* Clean up the variables module. */ | 4384 | /* Clean up the variables module. */ |