Sun Nov 1 17:47:26 2020 UTC ()
make(1): negate NoExecute to GNode_ShouldExecute


(rillig)
diff -r1.172 -r1.173 src/usr.bin/make/compat.c
diff -r1.299 -r1.300 src/usr.bin/make/job.c
diff -r1.185 -r1.186 src/usr.bin/make/make.c
diff -r1.178 -r1.179 src/usr.bin/make/make.h

cvs diff -r1.172 -r1.173 src/usr.bin/make/compat.c (switch to unified diff)

--- src/usr.bin/make/compat.c 2020/10/31 18:20:00 1.172
+++ src/usr.bin/make/compat.c 2020/11/01 17:47:26 1.173
@@ -1,706 +1,706 @@ @@ -1,706 +1,706 @@
1/* $NetBSD: compat.c,v 1.172 2020/10/31 18:20:00 rillig Exp $ */ 1/* $NetBSD: compat.c,v 1.173 2020/11/01 17:47:26 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1988, 1989 by Adam de Boor 36 * Copyright (c) 1988, 1989 by Adam de Boor
37 * Copyright (c) 1989 by Berkeley Softworks 37 * Copyright (c) 1989 by Berkeley Softworks
38 * All rights reserved. 38 * All rights reserved.
39 * 39 *
40 * This code is derived from software contributed to Berkeley by 40 * This code is derived from software contributed to Berkeley by
41 * Adam de Boor. 41 * Adam de Boor.
42 * 42 *
43 * Redistribution and use in source and binary forms, with or without 43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions 44 * modification, are permitted provided that the following conditions
45 * are met: 45 * are met:
46 * 1. Redistributions of source code must retain the above copyright 46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer. 47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright 48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the 49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution. 50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software 51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement: 52 * must display the following acknowledgement:
53 * This product includes software developed by the University of 53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors. 54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors 55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software 56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission. 57 * without specific prior written permission.
58 * 58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
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/*- 72/*-
73 * compat.c -- 73 * compat.c --
74 * The routines in this file implement the full-compatibility 74 * The routines in this file implement the full-compatibility
75 * mode of PMake. Most of the special functionality of PMake 75 * mode of PMake. Most of the special functionality of PMake
76 * is available in this mode. Things not supported: 76 * is available in this mode. Things not supported:
77 * - different shells. 77 * - different shells.
78 * - friendly variable substitution. 78 * - friendly variable substitution.
79 * 79 *
80 * Interface: 80 * Interface:
81 * Compat_Run Initialize things for this module and recreate 81 * Compat_Run Initialize things for this module and recreate
82 * thems as need creatin' 82 * thems as need creatin'
83 */ 83 */
84 84
85#include <sys/types.h> 85#include <sys/types.h>
86#include <sys/stat.h> 86#include <sys/stat.h>
87#include <sys/wait.h> 87#include <sys/wait.h>
88 88
89#include <errno.h> 89#include <errno.h>
90#include <signal.h> 90#include <signal.h>
91 91
92#include "make.h" 92#include "make.h"
93#include "dir.h" 93#include "dir.h"
94#include "job.h" 94#include "job.h"
95#include "metachar.h" 95#include "metachar.h"
96#include "pathnames.h" 96#include "pathnames.h"
97 97
98/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */ 98/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
99MAKE_RCSID("$NetBSD: compat.c,v 1.172 2020/10/31 18:20:00 rillig Exp $"); 99MAKE_RCSID("$NetBSD: compat.c,v 1.173 2020/11/01 17:47:26 rillig Exp $");
100 100
101static GNode *curTarg = NULL; 101static GNode *curTarg = NULL;
102static pid_t compatChild; 102static pid_t compatChild;
103static int compatSigno; 103static int compatSigno;
104 104
105/* 105/*
106 * CompatDeleteTarget -- delete a failed, interrupted, or otherwise 106 * CompatDeleteTarget -- delete a failed, interrupted, or otherwise
107 * duffed target if not inhibited by .PRECIOUS. 107 * duffed target if not inhibited by .PRECIOUS.
108 */ 108 */
109static void 109static void
110CompatDeleteTarget(GNode *gn) 110CompatDeleteTarget(GNode *gn)
111{ 111{
112 if (gn != NULL && !Targ_Precious(gn)) { 112 if (gn != NULL && !Targ_Precious(gn)) {
113 const char *file = GNode_VarTarget(gn); 113 const char *file = GNode_VarTarget(gn);
114 114
115 if (!opts.noExecute && eunlink(file) != -1) { 115 if (!opts.noExecute && eunlink(file) != -1) {
116 Error("*** %s removed", file); 116 Error("*** %s removed", file);
117 } 117 }
118 } 118 }
119} 119}
120 120
121/* Interrupt the creation of the current target and remove it if it ain't 121/* Interrupt the creation of the current target and remove it if it ain't
122 * precious. Then exit. 122 * precious. Then exit.
123 * 123 *
124 * If .INTERRUPT exists, its commands are run first WITH INTERRUPTS IGNORED. 124 * If .INTERRUPT exists, its commands are run first WITH INTERRUPTS IGNORED.
125 * 125 *
126 * XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've 126 * XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've
127 * left the logic alone for now. - dholland 20160826 127 * left the logic alone for now. - dholland 20160826
128 */ 128 */
129static void 129static void
130CompatInterrupt(int signo) 130CompatInterrupt(int signo)
131{ 131{
132 GNode *gn; 132 GNode *gn;
133 133
134 CompatDeleteTarget(curTarg); 134 CompatDeleteTarget(curTarg);
135 135
136 if (curTarg != NULL && !Targ_Precious(curTarg)) { 136 if (curTarg != NULL && !Targ_Precious(curTarg)) {
137 /* 137 /*
138 * Run .INTERRUPT only if hit with interrupt signal 138 * Run .INTERRUPT only if hit with interrupt signal
139 */ 139 */
140 if (signo == SIGINT) { 140 if (signo == SIGINT) {
141 gn = Targ_FindNode(".INTERRUPT"); 141 gn = Targ_FindNode(".INTERRUPT");
142 if (gn != NULL) { 142 if (gn != NULL) {
143 Compat_Make(gn, gn); 143 Compat_Make(gn, gn);
144 } 144 }
145 } 145 }
146 } 146 }
147 147
148 if (signo == SIGQUIT) 148 if (signo == SIGQUIT)
149 _exit(signo); 149 _exit(signo);
150 150
151 /* 151 /*
152 * If there is a child running, pass the signal on. 152 * If there is a child running, pass the signal on.
153 * We will exist after it has exited. 153 * We will exist after it has exited.
154 */ 154 */
155 compatSigno = signo; 155 compatSigno = signo;
156 if (compatChild > 0) { 156 if (compatChild > 0) {
157 KILLPG(compatChild, signo); 157 KILLPG(compatChild, signo);
158 } else { 158 } else {
159 bmake_signal(signo, SIG_DFL); 159 bmake_signal(signo, SIG_DFL);
160 kill(myPid, signo); 160 kill(myPid, signo);
161 } 161 }
162} 162}
163 163
164/* Execute the next command for a target. If the command returns an error, 164/* Execute the next command for a target. If the command returns an error,
165 * the node's made field is set to ERROR and creation stops. 165 * the node's made field is set to ERROR and creation stops.
166 * 166 *
167 * Input: 167 * Input:
168 * cmdp Command to execute 168 * cmdp Command to execute
169 * gnp Node from which the command came 169 * gnp Node from which the command came
170 * 170 *
171 * Results: 171 * Results:
172 * 0 if the command succeeded, 1 if an error occurred. 172 * 0 if the command succeeded, 1 if an error occurred.
173 */ 173 */
174int 174int
175Compat_RunCommand(const char *cmdp, GNode *gn) 175Compat_RunCommand(const char *cmdp, GNode *gn)
176{ 176{
177 char *cmdStart; /* Start of expanded command */ 177 char *cmdStart; /* Start of expanded command */
178 char *bp; 178 char *bp;
179 Boolean silent; /* Don't print command */ 179 Boolean silent; /* Don't print command */
180 Boolean doIt; /* Execute even if -n */ 180 Boolean doIt; /* Execute even if -n */
181 volatile Boolean errCheck; /* Check errors */ 181 volatile Boolean errCheck; /* Check errors */
182 int reason; /* Reason for child's death */ 182 int reason; /* Reason for child's death */
183 int status; /* Description of child's death */ 183 int status; /* Description of child's death */
184 pid_t cpid; /* Child actually found */ 184 pid_t cpid; /* Child actually found */
185 pid_t retstat; /* Result of wait */ 185 pid_t retstat; /* Result of wait */
186 StringListNode *cmdNode; /* Node where current command is located */ 186 StringListNode *cmdNode; /* Node where current command is located */
187 const char **volatile av; /* Argument vector for thing to exec */ 187 const char **volatile av; /* Argument vector for thing to exec */
188 char **volatile mav; /* Copy of the argument vector for freeing */ 188 char **volatile mav; /* Copy of the argument vector for freeing */
189 Boolean useShell; /* TRUE if command should be executed 189 Boolean useShell; /* TRUE if command should be executed
190 * using a shell */ 190 * using a shell */
191 const char *volatile cmd = cmdp; 191 const char *volatile cmd = cmdp;
192 192
193 silent = (gn->type & OP_SILENT) != 0; 193 silent = (gn->type & OP_SILENT) != 0;
194 errCheck = !(gn->type & OP_IGNORE); 194 errCheck = !(gn->type & OP_IGNORE);
195 doIt = FALSE; 195 doIt = FALSE;
196 196
197 /* Luckily the commands don't end up in a string pool, otherwise 197 /* Luckily the commands don't end up in a string pool, otherwise
198 * this comparison could match too early, in a dependency using "..." 198 * this comparison could match too early, in a dependency using "..."
199 * for delayed commands, run in parallel mode, using the same shell 199 * for delayed commands, run in parallel mode, using the same shell
200 * command line more than once; see JobPrintCommand. 200 * command line more than once; see JobPrintCommand.
201 * TODO: write a unit-test to protect against this potential bug. */ 201 * TODO: write a unit-test to protect against this potential bug. */
202 cmdNode = Lst_FindDatum(gn->commands, cmd); 202 cmdNode = Lst_FindDatum(gn->commands, cmd);
203 (void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart); 203 (void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart);
204 /* TODO: handle errors */ 204 /* TODO: handle errors */
205 205
206 if (*cmdStart == '\0') { 206 if (*cmdStart == '\0') {
207 free(cmdStart); 207 free(cmdStart);
208 return 0; 208 return 0;
209 } 209 }
210 cmd = cmdStart; 210 cmd = cmdStart;
211 LstNode_Set(cmdNode, cmdStart); 211 LstNode_Set(cmdNode, cmdStart);
212 212
213 if (gn->type & OP_SAVE_CMDS) { 213 if (gn->type & OP_SAVE_CMDS) {
214 GNode *endNode = Targ_GetEndNode(); 214 GNode *endNode = Targ_GetEndNode();
215 if (gn != endNode) { 215 if (gn != endNode) {
216 Lst_Append(endNode->commands, cmdStart); 216 Lst_Append(endNode->commands, cmdStart);
217 return 0; 217 return 0;
218 } 218 }
219 } 219 }
220 if (strcmp(cmdStart, "...") == 0) { 220 if (strcmp(cmdStart, "...") == 0) {
221 gn->type |= OP_SAVE_CMDS; 221 gn->type |= OP_SAVE_CMDS;
222 return 0; 222 return 0;
223 } 223 }
224 224
225 while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 225 while (*cmd == '@' || *cmd == '-' || *cmd == '+') {
226 switch (*cmd) { 226 switch (*cmd) {
227 case '@': 227 case '@':
228 silent = !DEBUG(LOUD); 228 silent = !DEBUG(LOUD);
229 break; 229 break;
230 case '-': 230 case '-':
231 errCheck = FALSE; 231 errCheck = FALSE;
232 break; 232 break;
233 case '+': 233 case '+':
234 doIt = TRUE; 234 doIt = TRUE;
235 if (!shellName) /* we came here from jobs */ 235 if (!shellName) /* we came here from jobs */
236 Shell_Init(); 236 Shell_Init();
237 break; 237 break;
238 } 238 }
239 cmd++; 239 cmd++;
240 } 240 }
241 241
242 while (ch_isspace(*cmd)) 242 while (ch_isspace(*cmd))
243 cmd++; 243 cmd++;
244 244
245 /* 245 /*
246 * If we did not end up with a command, just skip it. 246 * If we did not end up with a command, just skip it.
247 */ 247 */
248 if (!*cmd) 248 if (!*cmd)
249 return 0; 249 return 0;
250 250
251#if !defined(MAKE_NATIVE) 251#if !defined(MAKE_NATIVE)
252 /* 252 /*
253 * In a non-native build, the host environment might be weird enough 253 * In a non-native build, the host environment might be weird enough
254 * that it's necessary to go through a shell to get the correct 254 * that it's necessary to go through a shell to get the correct
255 * behaviour. Or perhaps the shell has been replaced with something 255 * behaviour. Or perhaps the shell has been replaced with something
256 * that does extra logging, and that should not be bypassed. 256 * that does extra logging, and that should not be bypassed.
257 */ 257 */
258 useShell = TRUE; 258 useShell = TRUE;
259#else 259#else
260 /* 260 /*
261 * Search for meta characters in the command. If there are no meta 261 * Search for meta characters in the command. If there are no meta
262 * characters, there's no need to execute a shell to execute the 262 * characters, there's no need to execute a shell to execute the
263 * command. 263 * command.
264 * 264 *
265 * Additionally variable assignments and empty commands 265 * Additionally variable assignments and empty commands
266 * go to the shell. Therefore treat '=' and ':' like shell 266 * go to the shell. Therefore treat '=' and ':' like shell
267 * meta characters as documented in make(1). 267 * meta characters as documented in make(1).
268 */ 268 */
269 269
270 useShell = needshell(cmd); 270 useShell = needshell(cmd);
271#endif 271#endif
272 272
273 /* 273 /*
274 * Print the command before echoing if we're not supposed to be quiet for 274 * Print the command before echoing if we're not supposed to be quiet for
275 * this one. We also print the command if -n given. 275 * this one. We also print the command if -n given.
276 */ 276 */
277 if (!silent || NoExecute(gn)) { 277 if (!silent || !GNode_ShouldExecute(gn)) {
278 printf("%s\n", cmd); 278 printf("%s\n", cmd);
279 fflush(stdout); 279 fflush(stdout);
280 } 280 }
281 281
282 /* 282 /*
283 * If we're not supposed to execute any commands, this is as far as 283 * If we're not supposed to execute any commands, this is as far as
284 * we go... 284 * we go...
285 */ 285 */
286 if (!doIt && NoExecute(gn)) { 286 if (!doIt && !GNode_ShouldExecute(gn)) {
287 return 0; 287 return 0;
288 } 288 }
289 DEBUG1(JOB, "Execute: '%s'\n", cmd); 289 DEBUG1(JOB, "Execute: '%s'\n", cmd);
290 290
291 if (useShell) { 291 if (useShell) {
292 /* 292 /*
293 * We need to pass the command off to the shell, typically 293 * We need to pass the command off to the shell, typically
294 * because the command contains a "meta" character. 294 * because the command contains a "meta" character.
295 */ 295 */
296 static const char *shargv[5]; 296 static const char *shargv[5];
297 int shargc; 297 int shargc;
298 298
299 shargc = 0; 299 shargc = 0;
300 shargv[shargc++] = shellPath; 300 shargv[shargc++] = shellPath;
301 /* 301 /*
302 * The following work for any of the builtin shell specs. 302 * The following work for any of the builtin shell specs.
303 */ 303 */
304 if (errCheck && shellErrFlag) { 304 if (errCheck && shellErrFlag) {
305 shargv[shargc++] = shellErrFlag; 305 shargv[shargc++] = shellErrFlag;
306 } 306 }
307 if (DEBUG(SHELL)) 307 if (DEBUG(SHELL))
308 shargv[shargc++] = "-xc"; 308 shargv[shargc++] = "-xc";
309 else 309 else
310 shargv[shargc++] = "-c"; 310 shargv[shargc++] = "-c";
311 shargv[shargc++] = cmd; 311 shargv[shargc++] = cmd;
312 shargv[shargc] = NULL; 312 shargv[shargc] = NULL;
313 av = shargv; 313 av = shargv;
314 bp = NULL; 314 bp = NULL;
315 mav = NULL; 315 mav = NULL;
316 } else { 316 } else {
317 /* 317 /*
318 * No meta-characters, so no need to exec a shell. Break the command 318 * No meta-characters, so no need to exec a shell. Break the command
319 * into words to form an argument vector we can execute. 319 * into words to form an argument vector we can execute.
320 */ 320 */
321 Words words = Str_Words(cmd, FALSE); 321 Words words = Str_Words(cmd, FALSE);
322 mav = words.words; 322 mav = words.words;
323 bp = words.freeIt; 323 bp = words.freeIt;
324 av = (void *)mav; 324 av = (void *)mav;
325 } 325 }
326 326
327#ifdef USE_META 327#ifdef USE_META
328 if (useMeta) { 328 if (useMeta) {
329 meta_compat_start(); 329 meta_compat_start();
330 } 330 }
331#endif 331#endif
332 332
333 /* 333 /*
334 * Fork and execute the single command. If the fork fails, we abort. 334 * Fork and execute the single command. If the fork fails, we abort.
335 */ 335 */
336 compatChild = cpid = vFork(); 336 compatChild = cpid = vFork();
337 if (cpid < 0) { 337 if (cpid < 0) {
338 Fatal("Could not fork"); 338 Fatal("Could not fork");
339 } 339 }
340 if (cpid == 0) { 340 if (cpid == 0) {
341 Var_ExportVars(); 341 Var_ExportVars();
342#ifdef USE_META 342#ifdef USE_META
343 if (useMeta) { 343 if (useMeta) {
344 meta_compat_child(); 344 meta_compat_child();
345 } 345 }
346#endif 346#endif
347 (void)execvp(av[0], (char *const *)UNCONST(av)); 347 (void)execvp(av[0], (char *const *)UNCONST(av));
348 execDie("exec", av[0]); 348 execDie("exec", av[0]);
349 } 349 }
350 350
351 free(mav); 351 free(mav);
352 free(bp); 352 free(bp);
353 353
354 /* XXX: Memory management looks suspicious here. */ 354 /* XXX: Memory management looks suspicious here. */
355 /* XXX: Setting a list item to NULL is unexpected. */ 355 /* XXX: Setting a list item to NULL is unexpected. */
356 LstNode_SetNull(cmdNode); 356 LstNode_SetNull(cmdNode);
357 357
358#ifdef USE_META 358#ifdef USE_META
359 if (useMeta) { 359 if (useMeta) {
360 meta_compat_parent(cpid); 360 meta_compat_parent(cpid);
361 } 361 }
362#endif 362#endif
363 363
364 /* 364 /*
365 * The child is off and running. Now all we can do is wait... 365 * The child is off and running. Now all we can do is wait...
366 */ 366 */
367 while ((retstat = wait(&reason)) != cpid) { 367 while ((retstat = wait(&reason)) != cpid) {
368 if (retstat > 0) 368 if (retstat > 0)
369 JobReapChild(retstat, reason, FALSE); /* not ours? */ 369 JobReapChild(retstat, reason, FALSE); /* not ours? */
370 if (retstat == -1 && errno != EINTR) { 370 if (retstat == -1 && errno != EINTR) {
371 break; 371 break;
372 } 372 }
373 } 373 }
374 374
375 if (retstat < 0) 375 if (retstat < 0)
376 Fatal("error in wait: %d: %s", retstat, strerror(errno)); 376 Fatal("error in wait: %d: %s", retstat, strerror(errno));
377 377
378 if (WIFSTOPPED(reason)) { 378 if (WIFSTOPPED(reason)) {
379 status = WSTOPSIG(reason); /* stopped */ 379 status = WSTOPSIG(reason); /* stopped */
380 } else if (WIFEXITED(reason)) { 380 } else if (WIFEXITED(reason)) {
381 status = WEXITSTATUS(reason); /* exited */ 381 status = WEXITSTATUS(reason); /* exited */
382#if defined(USE_META) && defined(USE_FILEMON_ONCE) 382#if defined(USE_META) && defined(USE_FILEMON_ONCE)
383 if (useMeta) { 383 if (useMeta) {
384 meta_cmd_finish(NULL); 384 meta_cmd_finish(NULL);
385 } 385 }
386#endif 386#endif
387 if (status != 0) { 387 if (status != 0) {
388 if (DEBUG(ERROR)) { 388 if (DEBUG(ERROR)) {
389 const char *cp; 389 const char *cp;
390 debug_printf("\n*** Failed target: %s\n*** Failed command: ", 390 debug_printf("\n*** Failed target: %s\n*** Failed command: ",
391 gn->name); 391 gn->name);
392 for (cp = cmd; *cp; ) { 392 for (cp = cmd; *cp; ) {
393 if (ch_isspace(*cp)) { 393 if (ch_isspace(*cp)) {
394 debug_printf(" "); 394 debug_printf(" ");
395 while (ch_isspace(*cp)) 395 while (ch_isspace(*cp))
396 cp++; 396 cp++;
397 } else { 397 } else {
398 debug_printf("%c", *cp); 398 debug_printf("%c", *cp);
399 cp++; 399 cp++;
400 } 400 }
401 } 401 }
402 debug_printf("\n"); 402 debug_printf("\n");
403 } 403 }
404 printf("*** Error code %d", status); 404 printf("*** Error code %d", status);
405 } 405 }
406 } else { 406 } else {
407 status = WTERMSIG(reason); /* signaled */ 407 status = WTERMSIG(reason); /* signaled */
408 printf("*** Signal %d", status); 408 printf("*** Signal %d", status);
409 } 409 }
410 410
411 411
412 if (!WIFEXITED(reason) || status != 0) { 412 if (!WIFEXITED(reason) || status != 0) {
413 if (errCheck) { 413 if (errCheck) {
414#ifdef USE_META 414#ifdef USE_META
415 if (useMeta) { 415 if (useMeta) {
416 meta_job_error(NULL, gn, 0, status); 416 meta_job_error(NULL, gn, 0, status);
417 } 417 }
418#endif 418#endif
419 gn->made = ERROR; 419 gn->made = ERROR;
420 if (opts.keepgoing) { 420 if (opts.keepgoing) {
421 /* Abort the current target, but let others continue. */ 421 /* Abort the current target, but let others continue. */
422 printf(" (continuing)\n"); 422 printf(" (continuing)\n");
423 } else { 423 } else {
424 printf("\n"); 424 printf("\n");
425 } 425 }
426 if (deleteOnError) 426 if (deleteOnError)
427 CompatDeleteTarget(gn); 427 CompatDeleteTarget(gn);
428 } else { 428 } else {
429 /* 429 /*
430 * Continue executing commands for this target. 430 * Continue executing commands for this target.
431 * If we return 0, this will happen... 431 * If we return 0, this will happen...
432 */ 432 */
433 printf(" (ignored)\n"); 433 printf(" (ignored)\n");
434 status = 0; 434 status = 0;
435 } 435 }
436 } 436 }
437 437
438 free(cmdStart); 438 free(cmdStart);
439 compatChild = 0; 439 compatChild = 0;
440 if (compatSigno) { 440 if (compatSigno) {
441 bmake_signal(compatSigno, SIG_DFL); 441 bmake_signal(compatSigno, SIG_DFL);
442 kill(myPid, compatSigno); 442 kill(myPid, compatSigno);
443 } 443 }
444 444
445 return status; 445 return status;
446} 446}
447 447
448static void 448static void
449RunCommands(GNode *gn) 449RunCommands(GNode *gn)
450{ 450{
451 StringListNode *ln; 451 StringListNode *ln;
452 for (ln = gn->commands->first; ln != NULL; ln = ln->next) { 452 for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
453 const char *cmd = ln->datum; 453 const char *cmd = ln->datum;
454 if (Compat_RunCommand(cmd, gn) != 0) 454 if (Compat_RunCommand(cmd, gn) != 0)
455 break; 455 break;
456 } 456 }
457} 457}
458 458
459static void 459static void
460MakeNodes(GNodeList *gnodes, GNode *pgn) 460MakeNodes(GNodeList *gnodes, GNode *pgn)
461{ 461{
462 GNodeListNode *ln; 462 GNodeListNode *ln;
463 for (ln = gnodes->first; ln != NULL; ln = ln->next) { 463 for (ln = gnodes->first; ln != NULL; ln = ln->next) {
464 GNode *cohort = ln->datum; 464 GNode *cohort = ln->datum;
465 Compat_Make(cohort, pgn); 465 Compat_Make(cohort, pgn);
466 } 466 }
467} 467}
468 468
469/* Make a target. 469/* Make a target.
470 * 470 *
471 * If an error is detected and not being ignored, the process exits. 471 * If an error is detected and not being ignored, the process exits.
472 * 472 *
473 * Input: 473 * Input:
474 * gn The node to make 474 * gn The node to make
475 * pgn Parent to abort if necessary 475 * pgn Parent to abort if necessary
476 */ 476 */
477void 477void
478Compat_Make(GNode *gn, GNode *pgn) 478Compat_Make(GNode *gn, GNode *pgn)
479{ 479{
480 if (!shellName) /* we came here from jobs */ 480 if (!shellName) /* we came here from jobs */
481 Shell_Init(); 481 Shell_Init();
482 if (gn->made == UNMADE && (gn == pgn || !(pgn->type & OP_MADE))) { 482 if (gn->made == UNMADE && (gn == pgn || !(pgn->type & OP_MADE))) {
483 /* 483 /*
484 * First mark ourselves to be made, then apply whatever transformations 484 * First mark ourselves to be made, then apply whatever transformations
485 * the suffix module thinks are necessary. Once that's done, we can 485 * the suffix module thinks are necessary. Once that's done, we can
486 * descend and make all our children. If any of them has an error 486 * descend and make all our children. If any of them has an error
487 * but the -k flag was given, our 'make' field will be set FALSE again. 487 * but the -k flag was given, our 'make' field will be set FALSE again.
488 * This is our signal to not attempt to do anything but abort our 488 * This is our signal to not attempt to do anything but abort our
489 * parent as well. 489 * parent as well.
490 */ 490 */
491 gn->flags |= REMAKE; 491 gn->flags |= REMAKE;
492 gn->made = BEINGMADE; 492 gn->made = BEINGMADE;
493 if (!(gn->type & OP_MADE)) 493 if (!(gn->type & OP_MADE))
494 Suff_FindDeps(gn); 494 Suff_FindDeps(gn);
495 MakeNodes(gn->children, gn); 495 MakeNodes(gn->children, gn);
496 if (!(gn->flags & REMAKE)) { 496 if (!(gn->flags & REMAKE)) {
497 gn->made = ABORTED; 497 gn->made = ABORTED;
498 pgn->flags &= ~(unsigned)REMAKE; 498 pgn->flags &= ~(unsigned)REMAKE;
499 goto cohorts; 499 goto cohorts;
500 } 500 }
501 501
502 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) 502 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL)
503 Var_Set(IMPSRC, GNode_VarTarget(gn), pgn); 503 Var_Set(IMPSRC, GNode_VarTarget(gn), pgn);
504 504
505 /* 505 /*
506 * All the children were made ok. Now youngestChild->mtime contains the 506 * All the children were made ok. Now youngestChild->mtime contains the
507 * modification time of the newest child, we need to find out if we 507 * modification time of the newest child, we need to find out if we
508 * exist and when we were modified last. The criteria for datedness 508 * exist and when we were modified last. The criteria for datedness
509 * are defined by the Make_OODate function. 509 * are defined by the Make_OODate function.
510 */ 510 */
511 DEBUG1(MAKE, "Examining %s...", gn->name); 511 DEBUG1(MAKE, "Examining %s...", gn->name);
512 if (!Make_OODate(gn)) { 512 if (!Make_OODate(gn)) {
513 gn->made = UPTODATE; 513 gn->made = UPTODATE;
514 DEBUG0(MAKE, "up-to-date.\n"); 514 DEBUG0(MAKE, "up-to-date.\n");
515 goto cohorts; 515 goto cohorts;
516 } else 516 } else
517 DEBUG0(MAKE, "out-of-date.\n"); 517 DEBUG0(MAKE, "out-of-date.\n");
518 518
519 /* 519 /*
520 * If the user is just seeing if something is out-of-date, exit now 520 * If the user is just seeing if something is out-of-date, exit now
521 * to tell him/her "yes". 521 * to tell him/her "yes".
522 */ 522 */
523 if (opts.queryFlag) { 523 if (opts.queryFlag) {
524 exit(1); 524 exit(1);
525 } 525 }
526 526
527 /* 527 /*
528 * We need to be re-made. We also have to make sure we've got a $? 528 * We need to be re-made. We also have to make sure we've got a $?
529 * variable. To be nice, we also define the $> variable using 529 * variable. To be nice, we also define the $> variable using
530 * Make_DoAllVar(). 530 * Make_DoAllVar().
531 */ 531 */
532 Make_DoAllVar(gn); 532 Make_DoAllVar(gn);
533 533
534 /* 534 /*
535 * Alter our type to tell if errors should be ignored or things 535 * Alter our type to tell if errors should be ignored or things
536 * should not be printed so CompatRunCommand knows what to do. 536 * should not be printed so CompatRunCommand knows what to do.
537 */ 537 */
538 if (Targ_Ignore(gn)) 538 if (Targ_Ignore(gn))
539 gn->type |= OP_IGNORE; 539 gn->type |= OP_IGNORE;
540 if (Targ_Silent(gn)) 540 if (Targ_Silent(gn))
541 gn->type |= OP_SILENT; 541 gn->type |= OP_SILENT;
542 542
543 if (Job_CheckCommands(gn, Fatal)) { 543 if (Job_CheckCommands(gn, Fatal)) {
544 /* 544 /*
545 * Our commands are ok, but we still have to worry about the -t 545 * Our commands are ok, but we still have to worry about the -t
546 * flag... 546 * flag...
547 */ 547 */
548 if (!opts.touchFlag || (gn->type & OP_MAKE)) { 548 if (!opts.touchFlag || (gn->type & OP_MAKE)) {
549 curTarg = gn; 549 curTarg = gn;
550#ifdef USE_META 550#ifdef USE_META
551 if (useMeta && !NoExecute(gn)) { 551 if (useMeta && GNode_ShouldExecute(gn)) {
552 meta_job_start(NULL, gn); 552 meta_job_start(NULL, gn);
553 } 553 }
554#endif 554#endif
555 RunCommands(gn); 555 RunCommands(gn);
556 curTarg = NULL; 556 curTarg = NULL;
557 } else { 557 } else {
558 Job_Touch(gn, (gn->type & OP_SILENT) != 0); 558 Job_Touch(gn, (gn->type & OP_SILENT) != 0);
559 } 559 }
560 } else { 560 } else {
561 gn->made = ERROR; 561 gn->made = ERROR;
562 } 562 }
563#ifdef USE_META 563#ifdef USE_META
564 if (useMeta && !NoExecute(gn)) { 564 if (useMeta && GNode_ShouldExecute(gn)) {
565 if (meta_job_finish(NULL) != 0) 565 if (meta_job_finish(NULL) != 0)
566 gn->made = ERROR; 566 gn->made = ERROR;
567 } 567 }
568#endif 568#endif
569 569
570 if (gn->made != ERROR) { 570 if (gn->made != ERROR) {
571 /* 571 /*
572 * If the node was made successfully, mark it so, update 572 * If the node was made successfully, mark it so, update
573 * its modification time and timestamp all its parents. Note 573 * its modification time and timestamp all its parents. Note
574 * that for .ZEROTIME targets, the timestamping isn't done. 574 * that for .ZEROTIME targets, the timestamping isn't done.
575 * This is to keep its state from affecting that of its parent. 575 * This is to keep its state from affecting that of its parent.
576 */ 576 */
577 gn->made = MADE; 577 gn->made = MADE;
578 pgn->flags |= Make_Recheck(gn) == 0 ? FORCE : 0; 578 pgn->flags |= Make_Recheck(gn) == 0 ? FORCE : 0;
579 if (!(gn->type & OP_EXEC)) { 579 if (!(gn->type & OP_EXEC)) {
580 pgn->flags |= CHILDMADE; 580 pgn->flags |= CHILDMADE;
581 Make_TimeStamp(pgn, gn); 581 Make_TimeStamp(pgn, gn);
582 } 582 }
583 } else if (opts.keepgoing) { 583 } else if (opts.keepgoing) {
584 pgn->flags &= ~(unsigned)REMAKE; 584 pgn->flags &= ~(unsigned)REMAKE;
585 } else { 585 } else {
586 PrintOnError(gn, "\nStop."); 586 PrintOnError(gn, "\nStop.");
587 exit(1); 587 exit(1);
588 } 588 }
589 } else if (gn->made == ERROR) { 589 } else if (gn->made == ERROR) {
590 /* Already had an error when making this. Tell the parent to abort. */ 590 /* Already had an error when making this. Tell the parent to abort. */
591 pgn->flags &= ~(unsigned)REMAKE; 591 pgn->flags &= ~(unsigned)REMAKE;
592 } else { 592 } else {
593 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) { 593 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) {
594 const char *target = GNode_VarTarget(gn); 594 const char *target = GNode_VarTarget(gn);
595 Var_Set(IMPSRC, target != NULL ? target : "", pgn); 595 Var_Set(IMPSRC, target != NULL ? target : "", pgn);
596 } 596 }
597 switch(gn->made) { 597 switch(gn->made) {
598 case BEINGMADE: 598 case BEINGMADE:
599 Error("Graph cycles through %s", gn->name); 599 Error("Graph cycles through %s", gn->name);
600 gn->made = ERROR; 600 gn->made = ERROR;
601 pgn->flags &= ~(unsigned)REMAKE; 601 pgn->flags &= ~(unsigned)REMAKE;
602 break; 602 break;
603 case MADE: 603 case MADE:
604 if ((gn->type & OP_EXEC) == 0) { 604 if ((gn->type & OP_EXEC) == 0) {
605 pgn->flags |= CHILDMADE; 605 pgn->flags |= CHILDMADE;
606 Make_TimeStamp(pgn, gn); 606 Make_TimeStamp(pgn, gn);
607 } 607 }
608 break; 608 break;
609 case UPTODATE: 609 case UPTODATE:
610 if ((gn->type & OP_EXEC) == 0) { 610 if ((gn->type & OP_EXEC) == 0) {
611 Make_TimeStamp(pgn, gn); 611 Make_TimeStamp(pgn, gn);
612 } 612 }
613 break; 613 break;
614 default: 614 default:
615 break; 615 break;
616 } 616 }
617 } 617 }
618 618
619cohorts: 619cohorts:
620 MakeNodes(gn->cohorts, pgn); 620 MakeNodes(gn->cohorts, pgn);
621} 621}
622 622
623/* Initialize this module and start making. 623/* Initialize this module and start making.
624 * 624 *
625 * Input: 625 * Input:
626 * targs The target nodes to re-create 626 * targs The target nodes to re-create
627 */ 627 */
628void 628void
629Compat_Run(GNodeList *targs) 629Compat_Run(GNodeList *targs)
630{ 630{
631 GNode *gn = NULL; /* Current root target */ 631 GNode *gn = NULL; /* Current root target */
632 int errors; /* Number of targets not remade due to errors */ 632 int errors; /* Number of targets not remade due to errors */
633 633
634 if (!shellName) 634 if (!shellName)
635 Shell_Init(); 635 Shell_Init();
636 636
637 if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) 637 if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN)
638 bmake_signal(SIGINT, CompatInterrupt); 638 bmake_signal(SIGINT, CompatInterrupt);
639 if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN) 639 if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN)
640 bmake_signal(SIGTERM, CompatInterrupt); 640 bmake_signal(SIGTERM, CompatInterrupt);
641 if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN) 641 if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN)
642 bmake_signal(SIGHUP, CompatInterrupt); 642 bmake_signal(SIGHUP, CompatInterrupt);
643 if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN) 643 if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN)
644 bmake_signal(SIGQUIT, CompatInterrupt); 644 bmake_signal(SIGQUIT, CompatInterrupt);
645 645
646 /* Create the .END node now, to keep the (debug) output of the 646 /* Create the .END node now, to keep the (debug) output of the
647 * counter.mk test the same as before 2020-09-23. This implementation 647 * counter.mk test the same as before 2020-09-23. This implementation
648 * detail probably doesn't matter though. */ 648 * detail probably doesn't matter though. */
649 (void)Targ_GetEndNode(); 649 (void)Targ_GetEndNode();
650 /* 650 /*
651 * If the user has defined a .BEGIN target, execute the commands attached 651 * If the user has defined a .BEGIN target, execute the commands attached
652 * to it. 652 * to it.
653 */ 653 */
654 if (!opts.queryFlag) { 654 if (!opts.queryFlag) {
655 gn = Targ_FindNode(".BEGIN"); 655 gn = Targ_FindNode(".BEGIN");
656 if (gn != NULL) { 656 if (gn != NULL) {
657 Compat_Make(gn, gn); 657 Compat_Make(gn, gn);
658 if (gn->made == ERROR) { 658 if (gn->made == ERROR) {
659 PrintOnError(gn, "\nStop."); 659 PrintOnError(gn, "\nStop.");
660 exit(1); 660 exit(1);
661 } 661 }
662 } 662 }
663 } 663 }
664 664
665 /* 665 /*
666 * Expand .USE nodes right now, because they can modify the structure 666 * Expand .USE nodes right now, because they can modify the structure
667 * of the tree. 667 * of the tree.
668 */ 668 */
669 Make_ExpandUse(targs); 669 Make_ExpandUse(targs);
670 670
671 /* 671 /*
672 * For each entry in the list of targets to create, call Compat_Make on 672 * For each entry in the list of targets to create, call Compat_Make on
673 * it to create the thing. Compat_Make will leave the 'made' field of gn 673 * it to create the thing. Compat_Make will leave the 'made' field of gn
674 * in one of several states: 674 * in one of several states:
675 * UPTODATE gn was already up-to-date 675 * UPTODATE gn was already up-to-date
676 * MADE gn was recreated successfully 676 * MADE gn was recreated successfully
677 * ERROR An error occurred while gn was being created 677 * ERROR An error occurred while gn was being created
678 * ABORTED gn was not remade because one of its inferiors 678 * ABORTED gn was not remade because one of its inferiors
679 * could not be made due to errors. 679 * could not be made due to errors.
680 */ 680 */
681 errors = 0; 681 errors = 0;
682 while (!Lst_IsEmpty(targs)) { 682 while (!Lst_IsEmpty(targs)) {
683 gn = Lst_Dequeue(targs); 683 gn = Lst_Dequeue(targs);
684 Compat_Make(gn, gn); 684 Compat_Make(gn, gn);
685 685
686 if (gn->made == UPTODATE) { 686 if (gn->made == UPTODATE) {
687 printf("`%s' is up to date.\n", gn->name); 687 printf("`%s' is up to date.\n", gn->name);
688 } else if (gn->made == ABORTED) { 688 } else if (gn->made == ABORTED) {
689 printf("`%s' not remade because of errors.\n", gn->name); 689 printf("`%s' not remade because of errors.\n", gn->name);
690 errors++; 690 errors++;
691 } 691 }
692 } 692 }
693 693
694 /* 694 /*
695 * If the user has defined a .END target, run its commands. 695 * If the user has defined a .END target, run its commands.
696 */ 696 */
697 if (errors == 0) { 697 if (errors == 0) {
698 GNode *endNode = Targ_GetEndNode(); 698 GNode *endNode = Targ_GetEndNode();
699 Compat_Make(endNode, endNode); 699 Compat_Make(endNode, endNode);
700 /* XXX: Did you mean endNode->made instead of gn->made? */ 700 /* XXX: Did you mean endNode->made instead of gn->made? */
701 if (gn->made == ERROR) { 701 if (gn->made == ERROR) {
702 PrintOnError(gn, "\nStop."); 702 PrintOnError(gn, "\nStop.");
703 exit(1); 703 exit(1);
704 } 704 }
705 } 705 }
706} 706}

cvs diff -r1.299 -r1.300 src/usr.bin/make/job.c (switch to unified diff)

--- src/usr.bin/make/job.c 2020/11/01 17:07:03 1.299
+++ src/usr.bin/make/job.c 2020/11/01 17:47:26 1.300
@@ -1,2602 +1,2602 @@ @@ -1,2602 +1,2602 @@
1/* $NetBSD: job.c,v 1.299 2020/11/01 17:07:03 rillig Exp $ */ 1/* $NetBSD: job.c,v 1.300 2020/11/01 17:47:26 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1988, 1989 by Adam de Boor 36 * Copyright (c) 1988, 1989 by Adam de Boor
37 * Copyright (c) 1989 by Berkeley Softworks 37 * Copyright (c) 1989 by Berkeley Softworks
38 * All rights reserved. 38 * All rights reserved.
39 * 39 *
40 * This code is derived from software contributed to Berkeley by 40 * This code is derived from software contributed to Berkeley by
41 * Adam de Boor. 41 * Adam de Boor.
42 * 42 *
43 * Redistribution and use in source and binary forms, with or without 43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions 44 * modification, are permitted provided that the following conditions
45 * are met: 45 * are met:
46 * 1. Redistributions of source code must retain the above copyright 46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer. 47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright 48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the 49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution. 50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software 51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement: 52 * must display the following acknowledgement:
53 * This product includes software developed by the University of 53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors. 54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors 55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software 56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission. 57 * without specific prior written permission.
58 * 58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
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/*- 72/*-
73 * job.c -- 73 * job.c --
74 * handle the creation etc. of our child processes. 74 * handle the creation etc. of our child processes.
75 * 75 *
76 * Interface: 76 * Interface:
77 * Job_Init Called to initialize this module. In addition, 77 * Job_Init Called to initialize this module. In addition,
78 * any commands attached to the .BEGIN target 78 * any commands attached to the .BEGIN target
79 * are executed before this function returns. 79 * are executed before this function returns.
80 * Hence, the makefiles must have been parsed 80 * Hence, the makefiles must have been parsed
81 * before this function is called. 81 * before this function is called.
82 * 82 *
83 * Job_End Clean up any memory used. 83 * Job_End Clean up any memory used.
84 * 84 *
85 * Job_Make Start the creation of the given target. 85 * Job_Make Start the creation of the given target.
86 * 86 *
87 * Job_CatchChildren 87 * Job_CatchChildren
88 * Check for and handle the termination of any 88 * Check for and handle the termination of any
89 * children. This must be called reasonably 89 * children. This must be called reasonably
90 * frequently to keep the whole make going at 90 * frequently to keep the whole make going at
91 * a decent clip, since job table entries aren't 91 * a decent clip, since job table entries aren't
92 * removed until their process is caught this way. 92 * removed until their process is caught this way.
93 * 93 *
94 * Job_CatchOutput 94 * Job_CatchOutput
95 * Print any output our children have produced. 95 * Print any output our children have produced.
96 * Should also be called fairly frequently to 96 * Should also be called fairly frequently to
97 * keep the user informed of what's going on. 97 * keep the user informed of what's going on.
98 * If no output is waiting, it will block for 98 * If no output is waiting, it will block for
99 * a time given by the SEL_* constants, below, 99 * a time given by the SEL_* constants, below,
100 * or until output is ready. 100 * or until output is ready.
101 * 101 *
102 * Job_ParseShell Given the line following a .SHELL target, parse 102 * Job_ParseShell Given the line following a .SHELL target, parse
103 * the line as a shell specification. Returns 103 * the line as a shell specification. Returns
104 * FALSE if the spec was incorrect. 104 * FALSE if the spec was incorrect.
105 * 105 *
106 * Job_Finish Perform any final processing which needs doing. 106 * Job_Finish Perform any final processing which needs doing.
107 * This includes the execution of any commands 107 * This includes the execution of any commands
108 * which have been/were attached to the .END 108 * which have been/were attached to the .END
109 * target. It should only be called when the 109 * target. It should only be called when the
110 * job table is empty. 110 * job table is empty.
111 * 111 *
112 * Job_AbortAll Abort all currently running jobs. It doesn't 112 * Job_AbortAll Abort all currently running jobs. It doesn't
113 * handle output or do anything for the jobs, 113 * handle output or do anything for the jobs,
114 * just kills them. It should only be called in 114 * just kills them. It should only be called in
115 * an emergency. 115 * an emergency.
116 * 116 *
117 * Job_CheckCommands 117 * Job_CheckCommands
118 * Verify that the commands for a target are 118 * Verify that the commands for a target are
119 * ok. Provide them if necessary and possible. 119 * ok. Provide them if necessary and possible.
120 * 120 *
121 * Job_Touch Update a target without really updating it. 121 * Job_Touch Update a target without really updating it.
122 * 122 *
123 * Job_Wait Wait for all currently-running jobs to finish. 123 * Job_Wait Wait for all currently-running jobs to finish.
124 */ 124 */
125 125
126#include <sys/types.h> 126#include <sys/types.h>
127#include <sys/stat.h> 127#include <sys/stat.h>
128#include <sys/file.h> 128#include <sys/file.h>
129#include <sys/time.h> 129#include <sys/time.h>
130#include <sys/wait.h> 130#include <sys/wait.h>
131 131
132#include <errno.h> 132#include <errno.h>
133#ifndef USE_SELECT 133#ifndef USE_SELECT
134#include <poll.h> 134#include <poll.h>
135#endif 135#endif
136#include <signal.h> 136#include <signal.h>
137#include <utime.h> 137#include <utime.h>
138 138
139#include "make.h" 139#include "make.h"
140#include "dir.h" 140#include "dir.h"
141#include "job.h" 141#include "job.h"
142#include "pathnames.h" 142#include "pathnames.h"
143#include "trace.h" 143#include "trace.h"
144 144
145/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ 145/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
146MAKE_RCSID("$NetBSD: job.c,v 1.299 2020/11/01 17:07:03 rillig Exp $"); 146MAKE_RCSID("$NetBSD: job.c,v 1.300 2020/11/01 17:47:26 rillig Exp $");
147 147
148/* A shell defines how the commands are run. All commands for a target are 148/* A shell defines how the commands are run. All commands for a target are
149 * written into a single file, which is then given to the shell to execute 149 * written into a single file, which is then given to the shell to execute
150 * the commands from it. The commands are written to the file using a few 150 * the commands from it. The commands are written to the file using a few
151 * templates for echo control and error control. 151 * templates for echo control and error control.
152 * 152 *
153 * The name of the shell is the basename for the predefined shells, such as 153 * The name of the shell is the basename for the predefined shells, such as
154 * "sh", "csh", "bash". For custom shells, it is the full pathname, and its 154 * "sh", "csh", "bash". For custom shells, it is the full pathname, and its
155 * basename is used to select the type of shell; the longest match wins. 155 * basename is used to select the type of shell; the longest match wins.
156 * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh. 156 * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh.
157 * 157 *
158 * The echoing of command lines is controlled using hasEchoCtl, echoOff, 158 * The echoing of command lines is controlled using hasEchoCtl, echoOff,
159 * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it 159 * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it
160 * still outputs something, but this something is not interesting, therefore 160 * still outputs something, but this something is not interesting, therefore
161 * it is filtered out using noPrint and noPrintLen. 161 * it is filtered out using noPrint and noPrintLen.
162 * 162 *
163 * The error checking for individual commands is controlled using hasErrCtl, 163 * The error checking for individual commands is controlled using hasErrCtl,
164 * errOnOrEcho, errOffOrExecIgnore and errExit. 164 * errOnOrEcho, errOffOrExecIgnore and errExit.
165 * 165 *
166 * If a shell doesn't have error control, errOnOrEcho becomes a printf template 166 * If a shell doesn't have error control, errOnOrEcho becomes a printf template
167 * for echoing the command, should echoing be on; errOffOrExecIgnore becomes 167 * for echoing the command, should echoing be on; errOffOrExecIgnore becomes
168 * another printf template for executing the command while ignoring the return 168 * another printf template for executing the command while ignoring the return
169 * status. Finally errExit is a printf template for running the command and 169 * status. Finally errExit is a printf template for running the command and
170 * causing the shell to exit on error. If any of these strings are empty when 170 * causing the shell to exit on error. If any of these strings are empty when
171 * hasErrCtl is FALSE, the command will be executed anyway as is, and if it 171 * hasErrCtl is FALSE, the command will be executed anyway as is, and if it
172 * causes an error, so be it. Any templates setup to echo the command will 172 * causes an error, so be it. Any templates setup to echo the command will
173 * escape any '$ ` \ "' characters in the command string to avoid common 173 * escape any '$ ` \ "' characters in the command string to avoid common
174 * problems with echo "%s\n" as a template. 174 * problems with echo "%s\n" as a template.
175 * 175 *
176 * The command-line flags "echo" and "exit" also control the behavior. The 176 * The command-line flags "echo" and "exit" also control the behavior. The
177 * "echo" flag causes the shell to start echoing commands right away. The 177 * "echo" flag causes the shell to start echoing commands right away. The
178 * "exit" flag causes the shell to exit when an error is detected in one of 178 * "exit" flag causes the shell to exit when an error is detected in one of
179 * the commands. 179 * the commands.
180 */ 180 */
181typedef struct Shell { 181typedef struct Shell {
182 182
183 /* The name of the shell. For Bourne and C shells, this is used only to 183 /* The name of the shell. For Bourne and C shells, this is used only to
184 * find the shell description when used as the single source of a .SHELL 184 * find the shell description when used as the single source of a .SHELL
185 * target. For user-defined shells, this is the full path of the shell. */ 185 * target. For user-defined shells, this is the full path of the shell. */
186 const char *name; 186 const char *name;
187 187
188 Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */ 188 Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */
189 const char *echoOff; /* command to turn off echo */ 189 const char *echoOff; /* command to turn off echo */
190 const char *echoOn; /* command to turn it back on again */ 190 const char *echoOn; /* command to turn it back on again */
191 const char *noPrint; /* text to skip when printing output from 191 const char *noPrint; /* text to skip when printing output from
192 * shell. This is usually the same as echoOff */ 192 * shell. This is usually the same as echoOff */
193 size_t noPrintLen; /* length of noPrint command */ 193 size_t noPrintLen; /* length of noPrint command */
194 194
195 Boolean hasErrCtl; /* set if can control error checking for 195 Boolean hasErrCtl; /* set if can control error checking for
196 * individual commands */ 196 * individual commands */
197 /* XXX: split into errOn and echoCmd */ 197 /* XXX: split into errOn and echoCmd */
198 const char *errOnOrEcho; /* template to turn on error checking */ 198 const char *errOnOrEcho; /* template to turn on error checking */
199 /* XXX: split into errOff and execIgnore */ 199 /* XXX: split into errOff and execIgnore */
200 const char *errOffOrExecIgnore; /* template to turn off error checking */ 200 const char *errOffOrExecIgnore; /* template to turn off error checking */
201 const char *errExit; /* template to use for testing exit code */ 201 const char *errExit; /* template to use for testing exit code */
202 202
203 /* string literal that results in a newline character when it appears 203 /* string literal that results in a newline character when it appears
204 * outside of any 'quote' or "quote" characters */ 204 * outside of any 'quote' or "quote" characters */
205 const char *newline; 205 const char *newline;
206 char commentChar; /* character used by shell for comment lines */ 206 char commentChar; /* character used by shell for comment lines */
207 207
208 /* 208 /*
209 * command-line flags 209 * command-line flags
210 */ 210 */
211 const char *echo; /* echo commands */ 211 const char *echo; /* echo commands */
212 const char *exit; /* exit on error */ 212 const char *exit; /* exit on error */
213} Shell; 213} Shell;
214 214
215/* 215/*
216 * error handling variables 216 * error handling variables
217 */ 217 */
218static int errors = 0; /* number of errors reported */ 218static int errors = 0; /* number of errors reported */
219typedef enum AbortReason { /* why is the make aborting? */ 219typedef enum AbortReason { /* why is the make aborting? */
220 ABORT_NONE, 220 ABORT_NONE,
221 ABORT_ERROR, /* Because of an error */ 221 ABORT_ERROR, /* Because of an error */
222 ABORT_INTERRUPT, /* Because it was interrupted */ 222 ABORT_INTERRUPT, /* Because it was interrupted */
223 ABORT_WAIT /* Waiting for jobs to finish */ 223 ABORT_WAIT /* Waiting for jobs to finish */
224} AbortReason; 224} AbortReason;
225static AbortReason aborting = ABORT_NONE; 225static AbortReason aborting = ABORT_NONE;
226#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */ 226#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
227 227
228/* 228/*
229 * this tracks the number of tokens currently "out" to build jobs. 229 * this tracks the number of tokens currently "out" to build jobs.
230 */ 230 */
231int jobTokensRunning = 0; 231int jobTokensRunning = 0;
232 232
233/* The number of commands actually printed to the shell commands file for 233/* The number of commands actually printed to the shell commands file for
234 * the current job. Should this number be 0, no shell will be executed. */ 234 * the current job. Should this number be 0, no shell will be executed. */
235static int numCommands; 235static int numCommands;
236 236
237typedef enum JobStartResult { 237typedef enum JobStartResult {
238 JOB_RUNNING, /* Job is running */ 238 JOB_RUNNING, /* Job is running */
239 JOB_ERROR, /* Error in starting the job */ 239 JOB_ERROR, /* Error in starting the job */
240 JOB_FINISHED /* The job is already finished */ 240 JOB_FINISHED /* The job is already finished */
241} JobStartResult; 241} JobStartResult;
242 242
243/* 243/*
244 * Descriptions for various shells. 244 * Descriptions for various shells.
245 * 245 *
246 * The build environment may set DEFSHELL_INDEX to one of 246 * The build environment may set DEFSHELL_INDEX to one of
247 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to 247 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to
248 * select one of the predefined shells as the default shell. 248 * select one of the predefined shells as the default shell.
249 * 249 *
250 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the 250 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the
251 * name or the full path of a sh-compatible shell, which will be used as 251 * name or the full path of a sh-compatible shell, which will be used as
252 * the default shell. 252 * the default shell.
253 * 253 *
254 * ".SHELL" lines in Makefiles can choose the default shell from the 254 * ".SHELL" lines in Makefiles can choose the default shell from the
255 * set defined here, or add additional shells. 255 * set defined here, or add additional shells.
256 */ 256 */
257 257
258#ifdef DEFSHELL_CUSTOM 258#ifdef DEFSHELL_CUSTOM
259#define DEFSHELL_INDEX_CUSTOM 0 259#define DEFSHELL_INDEX_CUSTOM 0
260#define DEFSHELL_INDEX_SH 1 260#define DEFSHELL_INDEX_SH 1
261#define DEFSHELL_INDEX_KSH 2 261#define DEFSHELL_INDEX_KSH 2
262#define DEFSHELL_INDEX_CSH 3 262#define DEFSHELL_INDEX_CSH 3
263#else /* !DEFSHELL_CUSTOM */ 263#else /* !DEFSHELL_CUSTOM */
264#define DEFSHELL_INDEX_SH 0 264#define DEFSHELL_INDEX_SH 0
265#define DEFSHELL_INDEX_KSH 1 265#define DEFSHELL_INDEX_KSH 1
266#define DEFSHELL_INDEX_CSH 2 266#define DEFSHELL_INDEX_CSH 2
267#endif /* !DEFSHELL_CUSTOM */ 267#endif /* !DEFSHELL_CUSTOM */
268 268
269#ifndef DEFSHELL_INDEX 269#ifndef DEFSHELL_INDEX
270#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */ 270#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
271#endif /* !DEFSHELL_INDEX */ 271#endif /* !DEFSHELL_INDEX */
272 272
273static Shell shells[] = { 273static Shell shells[] = {
274#ifdef DEFSHELL_CUSTOM 274#ifdef DEFSHELL_CUSTOM
275 /* 275 /*
276 * An sh-compatible shell with a non-standard name. 276 * An sh-compatible shell with a non-standard name.
277 * 277 *
278 * Keep this in sync with the "sh" description below, but avoid 278 * Keep this in sync with the "sh" description below, but avoid
279 * non-portable features that might not be supplied by all 279 * non-portable features that might not be supplied by all
280 * sh-compatible shells. 280 * sh-compatible shells.
281 */ 281 */
282{ 282{
283 DEFSHELL_CUSTOM, /* .name */ 283 DEFSHELL_CUSTOM, /* .name */
284 FALSE, /* .hasEchoCtl */ 284 FALSE, /* .hasEchoCtl */
285 "", /* .echoOff */ 285 "", /* .echoOff */
286 "", /* .echoOn */ 286 "", /* .echoOn */
287 "", /* .noPrint */ 287 "", /* .noPrint */
288 0, /* .noPrintLen */ 288 0, /* .noPrintLen */
289 FALSE, /* .hasErrCtl */ 289 FALSE, /* .hasErrCtl */
290 "echo \"%s\"\n", /* .errOnOrEcho */ 290 "echo \"%s\"\n", /* .errOnOrEcho */
291 "%s\n", /* .errOffOrExecIgnore */ 291 "%s\n", /* .errOffOrExecIgnore */
292 "{ %s \n} || exit $?\n", /* .errExit */ 292 "{ %s \n} || exit $?\n", /* .errExit */
293 "'\n'", /* .newline */ 293 "'\n'", /* .newline */
294 '#', /* .commentChar */ 294 '#', /* .commentChar */
295 "", /* .echo */ 295 "", /* .echo */
296 "", /* .exit */ 296 "", /* .exit */
297}, 297},
298#endif /* DEFSHELL_CUSTOM */ 298#endif /* DEFSHELL_CUSTOM */
299 /* 299 /*
300 * SH description. Echo control is also possible and, under 300 * SH description. Echo control is also possible and, under
301 * sun UNIX anyway, one can even control error checking. 301 * sun UNIX anyway, one can even control error checking.
302 */ 302 */
303{ 303{
304 "sh", /* .name */ 304 "sh", /* .name */
305 FALSE, /* .hasEchoCtl */ 305 FALSE, /* .hasEchoCtl */
306 "", /* .echoOff */ 306 "", /* .echoOff */
307 "", /* .echoOn */ 307 "", /* .echoOn */
308 "", /* .noPrint */ 308 "", /* .noPrint */
309 0, /* .noPrintLen */ 309 0, /* .noPrintLen */
310 FALSE, /* .hasErrCtl */ 310 FALSE, /* .hasErrCtl */
311 "echo \"%s\"\n", /* .errOnOrEcho */ 311 "echo \"%s\"\n", /* .errOnOrEcho */
312 "%s\n", /* .errOffOrExecIgnore */ 312 "%s\n", /* .errOffOrExecIgnore */
313 "{ %s \n} || exit $?\n", /* .errExit */ 313 "{ %s \n} || exit $?\n", /* .errExit */
314 "'\n'", /* .newline */ 314 "'\n'", /* .newline */
315 '#', /* .commentChar*/ 315 '#', /* .commentChar*/
316#if defined(MAKE_NATIVE) && defined(__NetBSD__) 316#if defined(MAKE_NATIVE) && defined(__NetBSD__)
317 "q", /* .echo */ 317 "q", /* .echo */
318#else 318#else
319 "", /* .echo */ 319 "", /* .echo */
320#endif 320#endif
321 "", /* .exit */ 321 "", /* .exit */
322}, 322},
323 /* 323 /*
324 * KSH description. 324 * KSH description.
325 */ 325 */
326{ 326{
327 "ksh", /* .name */ 327 "ksh", /* .name */
328 TRUE, /* .hasEchoCtl */ 328 TRUE, /* .hasEchoCtl */
329 "set +v", /* .echoOff */ 329 "set +v", /* .echoOff */
330 "set -v", /* .echoOn */ 330 "set -v", /* .echoOn */
331 "set +v", /* .noPrint */ 331 "set +v", /* .noPrint */
332 6, /* .noPrintLen */ 332 6, /* .noPrintLen */
333 FALSE, /* .hasErrCtl */ 333 FALSE, /* .hasErrCtl */
334 "echo \"%s\"\n", /* .errOnOrEcho */ 334 "echo \"%s\"\n", /* .errOnOrEcho */
335 "%s\n", /* .errOffOrExecIgnore */ 335 "%s\n", /* .errOffOrExecIgnore */
336 "{ %s \n} || exit $?\n", /* .errExit */ 336 "{ %s \n} || exit $?\n", /* .errExit */
337 "'\n'", /* .newline */ 337 "'\n'", /* .newline */
338 '#', /* .commentChar */ 338 '#', /* .commentChar */
339 "v", /* .echo */ 339 "v", /* .echo */
340 "", /* .exit */ 340 "", /* .exit */
341}, 341},
342 /* 342 /*
343 * CSH description. The csh can do echo control by playing 343 * CSH description. The csh can do echo control by playing
344 * with the setting of the 'echo' shell variable. Sadly, 344 * with the setting of the 'echo' shell variable. Sadly,
345 * however, it is unable to do error control nicely. 345 * however, it is unable to do error control nicely.
346 */ 346 */
347{ 347{
348 "csh", /* .name */ 348 "csh", /* .name */
349 TRUE, /* .hasEchoCtl */ 349 TRUE, /* .hasEchoCtl */
350 "unset verbose", /* .echoOff */ 350 "unset verbose", /* .echoOff */
351 "set verbose", /* .echoOn */ 351 "set verbose", /* .echoOn */
352 "unset verbose", /* .noPrint */ 352 "unset verbose", /* .noPrint */
353 13, /* .noPrintLen */ 353 13, /* .noPrintLen */
354 FALSE, /* .hasErrCtl */ 354 FALSE, /* .hasErrCtl */
355 "echo \"%s\"\n", /* .errOnOrEcho */ 355 "echo \"%s\"\n", /* .errOnOrEcho */
356 /* XXX: Mismatch between errOn and execIgnore */ 356 /* XXX: Mismatch between errOn and execIgnore */
357 "csh -c \"%s || exit 0\"\n", /* .errOffOrExecIgnore */ 357 "csh -c \"%s || exit 0\"\n", /* .errOffOrExecIgnore */
358 "", /* .errExit */ 358 "", /* .errExit */
359 "'\\\n'", /* .newline */ 359 "'\\\n'", /* .newline */
360 '#', /* .commentChar */ 360 '#', /* .commentChar */
361 "v", /* .echo */ 361 "v", /* .echo */
362 "e", /* .exit */ 362 "e", /* .exit */
363} 363}
364}; 364};
365 365
366/* This is the shell to which we pass all commands in the Makefile. 366/* This is the shell to which we pass all commands in the Makefile.
367 * It is set by the Job_ParseShell function. */ 367 * It is set by the Job_ParseShell function. */
368static Shell *commandShell = &shells[DEFSHELL_INDEX]; 368static Shell *commandShell = &shells[DEFSHELL_INDEX];
369const char *shellPath = NULL; /* full pathname of executable image */ 369const char *shellPath = NULL; /* full pathname of executable image */
370const char *shellName = NULL; /* last component of shellPath */ 370const char *shellName = NULL; /* last component of shellPath */
371char *shellErrFlag = NULL; 371char *shellErrFlag = NULL;
372static char *shellArgv = NULL; /* Custom shell args */ 372static char *shellArgv = NULL; /* Custom shell args */
373 373
374 374
375static Job *job_table; /* The structures that describe them */ 375static Job *job_table; /* The structures that describe them */
376static Job *job_table_end; /* job_table + maxJobs */ 376static Job *job_table_end; /* job_table + maxJobs */
377static unsigned int wantToken; /* we want a token */ 377static unsigned int wantToken; /* we want a token */
378static int lurking_children = 0; 378static int lurking_children = 0;
379static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */ 379static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */
380 380
381/* 381/*
382 * Set of descriptors of pipes connected to 382 * Set of descriptors of pipes connected to
383 * the output channels of children 383 * the output channels of children
384 */ 384 */
385static struct pollfd *fds = NULL; 385static struct pollfd *fds = NULL;
386static Job **jobfds = NULL; 386static Job **jobfds = NULL;
387static nfds_t nfds = 0; 387static nfds_t nfds = 0;
388static void watchfd(Job *); 388static void watchfd(Job *);
389static void clearfd(Job *); 389static void clearfd(Job *);
390static int readyfd(Job *); 390static int readyfd(Job *);
391 391
392static GNode *lastNode; /* The node for which output was most recently 392static GNode *lastNode; /* The node for which output was most recently
393 * produced. */ 393 * produced. */
394static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */ 394static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */
395static Job tokenWaitJob; /* token wait pseudo-job */ 395static Job tokenWaitJob; /* token wait pseudo-job */
396 396
397static Job childExitJob; /* child exit pseudo-job */ 397static Job childExitJob; /* child exit pseudo-job */
398#define CHILD_EXIT "." 398#define CHILD_EXIT "."
399#define DO_JOB_RESUME "R" 399#define DO_JOB_RESUME "R"
400 400
401enum { npseudojobs = 2 }; /* number of pseudo-jobs */ 401enum { npseudojobs = 2 }; /* number of pseudo-jobs */
402 402
403#define TARG_FMT "%s %s ---\n" /* Default format */ 403#define TARG_FMT "%s %s ---\n" /* Default format */
404#define MESSAGE(fp, gn) \ 404#define MESSAGE(fp, gn) \
405 if (opts.maxJobs != 1 && targPrefix && *targPrefix) \ 405 if (opts.maxJobs != 1 && targPrefix && *targPrefix) \
406 (void)fprintf(fp, TARG_FMT, targPrefix, gn->name) 406 (void)fprintf(fp, TARG_FMT, targPrefix, gn->name)
407 407
408static sigset_t caught_signals; /* Set of signals we handle */ 408static sigset_t caught_signals; /* Set of signals we handle */
409 409
410static void JobDoOutput(Job *, Boolean); 410static void JobDoOutput(Job *, Boolean);
411static void JobInterrupt(int, int) MAKE_ATTR_DEAD; 411static void JobInterrupt(int, int) MAKE_ATTR_DEAD;
412static void JobRestartJobs(void); 412static void JobRestartJobs(void);
413static void JobSigReset(void); 413static void JobSigReset(void);
414 414
415static unsigned 415static unsigned
416nfds_per_job(void) 416nfds_per_job(void)
417{ 417{
418#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 418#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
419 if (useMeta) 419 if (useMeta)
420 return 2; 420 return 2;
421#endif 421#endif
422 return 1; 422 return 1;
423} 423}
424 424
425static void 425static void
426job_table_dump(const char *where) 426job_table_dump(const char *where)
427{ 427{
428 Job *job; 428 Job *job;
429 429
430 debug_printf("job table @ %s\n", where); 430 debug_printf("job table @ %s\n", where);
431 for (job = job_table; job < job_table_end; job++) { 431 for (job = job_table; job < job_table_end; job++) {
432 debug_printf("job %d, status %d, flags %d, pid %d\n", 432 debug_printf("job %d, status %d, flags %d, pid %d\n",
433 (int)(job - job_table), job->job_state, job->flags, job->pid); 433 (int)(job - job_table), job->job_state, job->flags, job->pid);
434 } 434 }
435} 435}
436 436
437/* 437/*
438 * Delete the target of a failed, interrupted, or otherwise 438 * Delete the target of a failed, interrupted, or otherwise
439 * unsuccessful job unless inhibited by .PRECIOUS. 439 * unsuccessful job unless inhibited by .PRECIOUS.
440 */ 440 */
441static void 441static void
442JobDeleteTarget(GNode *gn) 442JobDeleteTarget(GNode *gn)
443{ 443{
444 const char *file; 444 const char *file;
445 445
446 if (gn->type & OP_JOIN) 446 if (gn->type & OP_JOIN)
447 return; 447 return;
448 if (gn->type & OP_PHONY) 448 if (gn->type & OP_PHONY)
449 return; 449 return;
450 if (Targ_Precious(gn)) 450 if (Targ_Precious(gn))
451 return; 451 return;
452 if (opts.noExecute) 452 if (opts.noExecute)
453 return; 453 return;
454 454
455 file = GNode_Path(gn); 455 file = GNode_Path(gn);
456 if (eunlink(file) != -1) 456 if (eunlink(file) != -1)
457 Error("*** %s removed", file); 457 Error("*** %s removed", file);
458} 458}
459 459
460/* 460/*
461 * JobSigLock/JobSigUnlock 461 * JobSigLock/JobSigUnlock
462 * 462 *
463 * Signal lock routines to get exclusive access. Currently used to 463 * Signal lock routines to get exclusive access. Currently used to
464 * protect `jobs' and `stoppedJobs' list manipulations. 464 * protect `jobs' and `stoppedJobs' list manipulations.
465 */ 465 */
466static void JobSigLock(sigset_t *omaskp) 466static void JobSigLock(sigset_t *omaskp)
467{ 467{
468 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) { 468 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) {
469 Punt("JobSigLock: sigprocmask: %s", strerror(errno)); 469 Punt("JobSigLock: sigprocmask: %s", strerror(errno));
470 sigemptyset(omaskp); 470 sigemptyset(omaskp);
471 } 471 }
472} 472}
473 473
474static void JobSigUnlock(sigset_t *omaskp) 474static void JobSigUnlock(sigset_t *omaskp)
475{ 475{
476 (void)sigprocmask(SIG_SETMASK, omaskp, NULL); 476 (void)sigprocmask(SIG_SETMASK, omaskp, NULL);
477} 477}
478 478
479static void 479static void
480JobCreatePipe(Job *job, int minfd) 480JobCreatePipe(Job *job, int minfd)
481{ 481{
482 int i, fd, flags; 482 int i, fd, flags;
483 int pipe_fds[2]; 483 int pipe_fds[2];
484 484
485 if (pipe(pipe_fds) == -1) 485 if (pipe(pipe_fds) == -1)
486 Punt("Cannot create pipe: %s", strerror(errno)); 486 Punt("Cannot create pipe: %s", strerror(errno));
487 487
488 for (i = 0; i < 2; i++) { 488 for (i = 0; i < 2; i++) {
489 /* Avoid using low numbered fds */ 489 /* Avoid using low numbered fds */
490 fd = fcntl(pipe_fds[i], F_DUPFD, minfd); 490 fd = fcntl(pipe_fds[i], F_DUPFD, minfd);
491 if (fd != -1) { 491 if (fd != -1) {
492 close(pipe_fds[i]); 492 close(pipe_fds[i]);
493 pipe_fds[i] = fd; 493 pipe_fds[i] = fd;
494 } 494 }
495 } 495 }
496 496
497 job->inPipe = pipe_fds[0]; 497 job->inPipe = pipe_fds[0];
498 job->outPipe = pipe_fds[1]; 498 job->outPipe = pipe_fds[1];
499 499
500 /* Set close-on-exec flag for both */ 500 /* Set close-on-exec flag for both */
501 if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1) 501 if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1)
502 Punt("Cannot set close-on-exec: %s", strerror(errno)); 502 Punt("Cannot set close-on-exec: %s", strerror(errno));
503 if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1) 503 if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1)
504 Punt("Cannot set close-on-exec: %s", strerror(errno)); 504 Punt("Cannot set close-on-exec: %s", strerror(errno));
505 505
506 /* 506 /*
507 * We mark the input side of the pipe non-blocking; we poll(2) the 507 * We mark the input side of the pipe non-blocking; we poll(2) the
508 * pipe when we're waiting for a job token, but we might lose the 508 * pipe when we're waiting for a job token, but we might lose the
509 * race for the token when a new one becomes available, so the read 509 * race for the token when a new one becomes available, so the read
510 * from the pipe should not block. 510 * from the pipe should not block.
511 */ 511 */
512 flags = fcntl(job->inPipe, F_GETFL, 0); 512 flags = fcntl(job->inPipe, F_GETFL, 0);
513 if (flags == -1) 513 if (flags == -1)
514 Punt("Cannot get flags: %s", strerror(errno)); 514 Punt("Cannot get flags: %s", strerror(errno));
515 flags |= O_NONBLOCK; 515 flags |= O_NONBLOCK;
516 if (fcntl(job->inPipe, F_SETFL, flags) == -1) 516 if (fcntl(job->inPipe, F_SETFL, flags) == -1)
517 Punt("Cannot set flags: %s", strerror(errno)); 517 Punt("Cannot set flags: %s", strerror(errno));
518} 518}
519 519
520/* Pass the signal to each running job. */ 520/* Pass the signal to each running job. */
521static void 521static void
522JobCondPassSig(int signo) 522JobCondPassSig(int signo)
523{ 523{
524 Job *job; 524 Job *job;
525 525
526 DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo); 526 DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo);
527 527
528 for (job = job_table; job < job_table_end; job++) { 528 for (job = job_table; job < job_table_end; job++) {
529 if (job->job_state != JOB_ST_RUNNING) 529 if (job->job_state != JOB_ST_RUNNING)
530 continue; 530 continue;
531 DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n", 531 DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n",
532 signo, job->pid); 532 signo, job->pid);
533 KILLPG(job->pid, signo); 533 KILLPG(job->pid, signo);
534 } 534 }
535} 535}
536 536
537/* SIGCHLD handler. 537/* SIGCHLD handler.
538 * 538 *
539 * Sends a token on the child exit pipe to wake us up from select()/poll(). */ 539 * Sends a token on the child exit pipe to wake us up from select()/poll(). */
540static void 540static void
541JobChildSig(int signo MAKE_ATTR_UNUSED) 541JobChildSig(int signo MAKE_ATTR_UNUSED)
542{ 542{
543 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN) 543 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN)
544 continue; 544 continue;
545} 545}
546 546
547 547
548/* Resume all stopped jobs. */ 548/* Resume all stopped jobs. */
549static void 549static void
550JobContinueSig(int signo MAKE_ATTR_UNUSED) 550JobContinueSig(int signo MAKE_ATTR_UNUSED)
551{ 551{
552 /* 552 /*
553 * Defer sending SIGCONT to our stopped children until we return 553 * Defer sending SIGCONT to our stopped children until we return
554 * from the signal handler. 554 * from the signal handler.
555 */ 555 */
556 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 && 556 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
557 errno == EAGAIN) 557 errno == EAGAIN)
558 continue; 558 continue;
559} 559}
560 560
561/* Pass a signal on to all jobs, then resend to ourselves. 561/* Pass a signal on to all jobs, then resend to ourselves.
562 * We die by the same signal. */ 562 * We die by the same signal. */
563MAKE_ATTR_DEAD static void 563MAKE_ATTR_DEAD static void
564JobPassSig_int(int signo) 564JobPassSig_int(int signo)
565{ 565{
566 /* Run .INTERRUPT target then exit */ 566 /* Run .INTERRUPT target then exit */
567 JobInterrupt(TRUE, signo); 567 JobInterrupt(TRUE, signo);
568} 568}
569 569
570/* Pass a signal on to all jobs, then resend to ourselves. 570/* Pass a signal on to all jobs, then resend to ourselves.
571 * We die by the same signal. */ 571 * We die by the same signal. */
572MAKE_ATTR_DEAD static void 572MAKE_ATTR_DEAD static void
573JobPassSig_term(int signo) 573JobPassSig_term(int signo)
574{ 574{
575 /* Dont run .INTERRUPT target then exit */ 575 /* Dont run .INTERRUPT target then exit */
576 JobInterrupt(FALSE, signo); 576 JobInterrupt(FALSE, signo);
577} 577}
578 578
579static void 579static void
580JobPassSig_suspend(int signo) 580JobPassSig_suspend(int signo)
581{ 581{
582 sigset_t nmask, omask; 582 sigset_t nmask, omask;
583 struct sigaction act; 583 struct sigaction act;
584 584
585 /* Suppress job started/continued messages */ 585 /* Suppress job started/continued messages */
586 make_suspended = 1; 586 make_suspended = 1;
587 587
588 /* Pass the signal onto every job */ 588 /* Pass the signal onto every job */
589 JobCondPassSig(signo); 589 JobCondPassSig(signo);
590 590
591 /* 591 /*
592 * Send ourselves the signal now we've given the message to everyone else. 592 * Send ourselves the signal now we've given the message to everyone else.
593 * Note we block everything else possible while we're getting the signal. 593 * Note we block everything else possible while we're getting the signal.
594 * This ensures that all our jobs get continued when we wake up before 594 * This ensures that all our jobs get continued when we wake up before
595 * we take any other signal. 595 * we take any other signal.
596 */ 596 */
597 sigfillset(&nmask); 597 sigfillset(&nmask);
598 sigdelset(&nmask, signo); 598 sigdelset(&nmask, signo);
599 (void)sigprocmask(SIG_SETMASK, &nmask, &omask); 599 (void)sigprocmask(SIG_SETMASK, &nmask, &omask);
600 600
601 act.sa_handler = SIG_DFL; 601 act.sa_handler = SIG_DFL;
602 sigemptyset(&act.sa_mask); 602 sigemptyset(&act.sa_mask);
603 act.sa_flags = 0; 603 act.sa_flags = 0;
604 (void)sigaction(signo, &act, NULL); 604 (void)sigaction(signo, &act, NULL);
605 605
606 if (DEBUG(JOB)) 606 if (DEBUG(JOB))
607 debug_printf("JobPassSig passing signal %d to self.\n", signo); 607 debug_printf("JobPassSig passing signal %d to self.\n", signo);
608 608
609 (void)kill(getpid(), signo); 609 (void)kill(getpid(), signo);
610 610
611 /* 611 /*
612 * We've been continued. 612 * We've been continued.
613 * 613 *
614 * A whole host of signals continue to happen! 614 * A whole host of signals continue to happen!
615 * SIGCHLD for any processes that actually suspended themselves. 615 * SIGCHLD for any processes that actually suspended themselves.
616 * SIGCHLD for any processes that exited while we were alseep. 616 * SIGCHLD for any processes that exited while we were alseep.
617 * The SIGCONT that actually caused us to wakeup. 617 * The SIGCONT that actually caused us to wakeup.
618 * 618 *
619 * Since we defer passing the SIGCONT on to our children until 619 * Since we defer passing the SIGCONT on to our children until
620 * the main processing loop, we can be sure that all the SIGCHLD 620 * the main processing loop, we can be sure that all the SIGCHLD
621 * events will have happened by then - and that the waitpid() will 621 * events will have happened by then - and that the waitpid() will
622 * collect the child 'suspended' events. 622 * collect the child 'suspended' events.
623 * For correct sequencing we just need to ensure we process the 623 * For correct sequencing we just need to ensure we process the
624 * waitpid() before passing on the SIGCONT. 624 * waitpid() before passing on the SIGCONT.
625 * 625 *
626 * In any case nothing else is needed here. 626 * In any case nothing else is needed here.
627 */ 627 */
628 628
629 /* Restore handler and signal mask */ 629 /* Restore handler and signal mask */
630 act.sa_handler = JobPassSig_suspend; 630 act.sa_handler = JobPassSig_suspend;
631 (void)sigaction(signo, &act, NULL); 631 (void)sigaction(signo, &act, NULL);
632 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 632 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
633} 633}
634 634
635static Job * 635static Job *
636JobFindPid(int pid, JobState status, Boolean isJobs) 636JobFindPid(int pid, JobState status, Boolean isJobs)
637{ 637{
638 Job *job; 638 Job *job;
639 639
640 for (job = job_table; job < job_table_end; job++) { 640 for (job = job_table; job < job_table_end; job++) {
641 if ((job->job_state == status) && job->pid == pid) 641 if ((job->job_state == status) && job->pid == pid)
642 return job; 642 return job;
643 } 643 }
644 if (DEBUG(JOB) && isJobs) 644 if (DEBUG(JOB) && isJobs)
645 job_table_dump("no pid"); 645 job_table_dump("no pid");
646 return NULL; 646 return NULL;
647} 647}
648 648
649/* Parse leading '@', '-' and '+', which control the exact execution mode. */ 649/* Parse leading '@', '-' and '+', which control the exact execution mode. */
650static void 650static void
651ParseRunOptions( 651ParseRunOptions(
652 char **pp, 652 char **pp,
653 Boolean *out_shutUp, Boolean *out_errOff, Boolean *out_runAlways) 653 Boolean *out_shutUp, Boolean *out_errOff, Boolean *out_runAlways)
654{ 654{
655 char *p = *pp; 655 char *p = *pp;
656 *out_shutUp = FALSE; 656 *out_shutUp = FALSE;
657 *out_errOff = FALSE; 657 *out_errOff = FALSE;
658 *out_runAlways = FALSE; 658 *out_runAlways = FALSE;
659 659
660 for (;;) { 660 for (;;) {
661 if (*p == '@') 661 if (*p == '@')
662 *out_shutUp = !DEBUG(LOUD); 662 *out_shutUp = !DEBUG(LOUD);
663 else if (*p == '-') 663 else if (*p == '-')
664 *out_errOff = TRUE; 664 *out_errOff = TRUE;
665 else if (*p == '+') 665 else if (*p == '+')
666 *out_runAlways = TRUE; 666 *out_runAlways = TRUE;
667 else 667 else
668 break; 668 break;
669 p++; 669 p++;
670 } 670 }
671 671
672 pp_skip_whitespace(&p); 672 pp_skip_whitespace(&p);
673 673
674 *pp = p; 674 *pp = p;
675} 675}
676 676
677/* Escape a string for a double-quoted string literal in sh, csh and ksh. */ 677/* Escape a string for a double-quoted string literal in sh, csh and ksh. */
678static char * 678static char *
679EscapeShellDblQuot(const char *cmd) 679EscapeShellDblQuot(const char *cmd)
680{ 680{
681 size_t i, j; 681 size_t i, j;
682 682
683 /* Worst that could happen is every char needs escaping. */ 683 /* Worst that could happen is every char needs escaping. */
684 char *esc = bmake_malloc(strlen(cmd) * 2 + 1); 684 char *esc = bmake_malloc(strlen(cmd) * 2 + 1);
685 for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) { 685 for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) {
686 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' || cmd[i] == '"') 686 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' || cmd[i] == '"')
687 esc[j++] = '\\'; 687 esc[j++] = '\\';
688 esc[j] = cmd[i]; 688 esc[j] = cmd[i];
689 } 689 }
690 esc[j] = '\0'; 690 esc[j] = '\0';
691 691
692 return esc; 692 return esc;
693} 693}
694 694
695/*- 695/*-
696 *----------------------------------------------------------------------- 696 *-----------------------------------------------------------------------
697 * JobPrintCommand -- 697 * JobPrintCommand --
698 * Put out another command for the given job. If the command starts 698 * Put out another command for the given job. If the command starts
699 * with an @ or a - we process it specially. In the former case, 699 * with an @ or a - we process it specially. In the former case,
700 * so long as the -s and -n flags weren't given to make, we stick 700 * so long as the -s and -n flags weren't given to make, we stick
701 * a shell-specific echoOff command in the script. In the latter, 701 * a shell-specific echoOff command in the script. In the latter,
702 * we ignore errors for the entire job, unless the shell has error 702 * we ignore errors for the entire job, unless the shell has error
703 * control. 703 * control.
704 * If the command is just "..." we take all future commands for this 704 * If the command is just "..." we take all future commands for this
705 * job to be commands to be executed once the entire graph has been 705 * job to be commands to be executed once the entire graph has been
706 * made and return non-zero to signal that the end of the commands 706 * made and return non-zero to signal that the end of the commands
707 * was reached. These commands are later attached to the postCommands 707 * was reached. These commands are later attached to the postCommands
708 * node and executed by Job_End when all things are done. 708 * node and executed by Job_End when all things are done.
709 * 709 *
710 * Side Effects: 710 * Side Effects:
711 * If the command begins with a '-' and the shell has no error control, 711 * If the command begins with a '-' and the shell has no error control,
712 * the JOB_IGNERR flag is set in the job descriptor. 712 * the JOB_IGNERR flag is set in the job descriptor.
713 * numCommands is incremented if the command is actually printed. 713 * numCommands is incremented if the command is actually printed.
714 *----------------------------------------------------------------------- 714 *-----------------------------------------------------------------------
715 */ 715 */
716static void 716static void
717JobPrintCommand(Job *job, char *cmd) 717JobPrintCommand(Job *job, char *cmd)
718{ 718{
719 const char *const cmdp = cmd; 719 const char *const cmdp = cmd;
720 Boolean noSpecials; /* true if we shouldn't worry about 720 Boolean noSpecials; /* true if we shouldn't worry about
721 * inserting special commands into 721 * inserting special commands into
722 * the input stream. */ 722 * the input stream. */
723 Boolean shutUp; /* true if we put a no echo command 723 Boolean shutUp; /* true if we put a no echo command
724 * into the command file */ 724 * into the command file */
725 Boolean errOff; /* true if we turned error checking 725 Boolean errOff; /* true if we turned error checking
726 * off before printing the command 726 * off before printing the command
727 * and need to turn it back on */ 727 * and need to turn it back on */
728 Boolean runAlways; 728 Boolean runAlways;
729 const char *cmdTemplate; /* Template to use when printing the 729 const char *cmdTemplate; /* Template to use when printing the
730 * command */ 730 * command */
731 char *cmdStart; /* Start of expanded command */ 731 char *cmdStart; /* Start of expanded command */
732 char *escCmd = NULL; /* Command with quotes/backticks escaped */ 732 char *escCmd = NULL; /* Command with quotes/backticks escaped */
733 733
734 noSpecials = NoExecute(job->node); 734 noSpecials = !GNode_ShouldExecute(job->node);
735 735
736#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ 736#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \
737 debug_printf(fmt, arg); \ 737 debug_printf(fmt, arg); \
738 } \ 738 } \
739 (void)fprintf(job->cmdFILE, fmt, arg); \ 739 (void)fprintf(job->cmdFILE, fmt, arg); \
740 (void)fflush(job->cmdFILE); 740 (void)fflush(job->cmdFILE);
741 741
742 numCommands++; 742 numCommands++;
743 743
744 Var_Subst(cmd, job->node, VARE_WANTRES, &cmd); 744 Var_Subst(cmd, job->node, VARE_WANTRES, &cmd);
745 /* TODO: handle errors */ 745 /* TODO: handle errors */
746 cmdStart = cmd; 746 cmdStart = cmd;
747 747
748 cmdTemplate = "%s\n"; 748 cmdTemplate = "%s\n";
749 749
750 ParseRunOptions(&cmd, &shutUp, &errOff, &runAlways); 750 ParseRunOptions(&cmd, &shutUp, &errOff, &runAlways);
751 751
752 if (runAlways && noSpecials) { 752 if (runAlways && noSpecials) {
753 /* 753 /*
754 * We're not actually executing anything... 754 * We're not actually executing anything...
755 * but this one needs to be - use compat mode just for it. 755 * but this one needs to be - use compat mode just for it.
756 */ 756 */
757 Compat_RunCommand(cmdp, job->node); 757 Compat_RunCommand(cmdp, job->node);
758 free(cmdStart); 758 free(cmdStart);
759 return; 759 return;
760 } 760 }
761 761
762 /* 762 /*
763 * If the shell doesn't have error control the alternate echo'ing will 763 * If the shell doesn't have error control the alternate echo'ing will
764 * be done (to avoid showing additional error checking code) 764 * be done (to avoid showing additional error checking code)
765 * and this will need the characters '$ ` \ "' escaped 765 * and this will need the characters '$ ` \ "' escaped
766 */ 766 */
767 767
768 if (!commandShell->hasErrCtl) 768 if (!commandShell->hasErrCtl)
769 escCmd = EscapeShellDblQuot(cmd); 769 escCmd = EscapeShellDblQuot(cmd);
770 770
771 if (shutUp) { 771 if (shutUp) {
772 if (!(job->flags & JOB_SILENT) && !noSpecials && 772 if (!(job->flags & JOB_SILENT) && !noSpecials &&
773 commandShell->hasEchoCtl) { 773 commandShell->hasEchoCtl) {
774 DBPRINTF("%s\n", commandShell->echoOff); 774 DBPRINTF("%s\n", commandShell->echoOff);
775 } else { 775 } else {
776 if (commandShell->hasErrCtl) 776 if (commandShell->hasErrCtl)
777 shutUp = FALSE; 777 shutUp = FALSE;
778 } 778 }
779 } 779 }
780 780
781 if (errOff) { 781 if (errOff) {
782 if (!noSpecials) { 782 if (!noSpecials) {
783 if (commandShell->hasErrCtl) { 783 if (commandShell->hasErrCtl) {
784 /* 784 /*
785 * we don't want the error-control commands showing 785 * we don't want the error-control commands showing
786 * up either, so we turn off echoing while executing 786 * up either, so we turn off echoing while executing
787 * them. We could put another field in the shell 787 * them. We could put another field in the shell
788 * structure to tell JobDoOutput to look for this 788 * structure to tell JobDoOutput to look for this
789 * string too, but why make it any more complex than 789 * string too, but why make it any more complex than
790 * it already is? 790 * it already is?
791 */ 791 */
792 if (!(job->flags & JOB_SILENT) && !shutUp && 792 if (!(job->flags & JOB_SILENT) && !shutUp &&
793 commandShell->hasEchoCtl) { 793 commandShell->hasEchoCtl) {
794 DBPRINTF("%s\n", commandShell->echoOff); 794 DBPRINTF("%s\n", commandShell->echoOff);
795 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore); 795 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore);
796 DBPRINTF("%s\n", commandShell->echoOn); 796 DBPRINTF("%s\n", commandShell->echoOn);
797 } else { 797 } else {
798 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore); 798 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore);
799 } 799 }
800 } else if (commandShell->errOffOrExecIgnore && 800 } else if (commandShell->errOffOrExecIgnore &&
801 commandShell->errOffOrExecIgnore[0] != '\0') 801 commandShell->errOffOrExecIgnore[0] != '\0')
802 { 802 {
803 /* 803 /*
804 * The shell has no error control, so we need to be 804 * The shell has no error control, so we need to be
805 * weird to get it to ignore any errors from the command. 805 * weird to get it to ignore any errors from the command.
806 * If echoing is turned on, we turn it off and use the 806 * If echoing is turned on, we turn it off and use the
807 * errOnOrEcho template to echo the command. Leave echoing 807 * errOnOrEcho template to echo the command. Leave echoing
808 * off so the user doesn't see the weirdness we go through 808 * off so the user doesn't see the weirdness we go through
809 * to ignore errors. Set cmdTemplate to use the weirdness 809 * to ignore errors. Set cmdTemplate to use the weirdness
810 * instead of the simple "%s\n" template. 810 * instead of the simple "%s\n" template.
811 */ 811 */
812 job->flags |= JOB_IGNERR; 812 job->flags |= JOB_IGNERR;
813 if (!(job->flags & JOB_SILENT) && !shutUp) { 813 if (!(job->flags & JOB_SILENT) && !shutUp) {
814 if (commandShell->hasEchoCtl) { 814 if (commandShell->hasEchoCtl) {
815 DBPRINTF("%s\n", commandShell->echoOff); 815 DBPRINTF("%s\n", commandShell->echoOff);
816 } 816 }
817 DBPRINTF(commandShell->errOnOrEcho, escCmd); 817 DBPRINTF(commandShell->errOnOrEcho, escCmd);
818 shutUp = TRUE; 818 shutUp = TRUE;
819 } else { 819 } else {
820 if (!shutUp) { 820 if (!shutUp) {
821 DBPRINTF(commandShell->errOnOrEcho, escCmd); 821 DBPRINTF(commandShell->errOnOrEcho, escCmd);
822 } 822 }
823 } 823 }
824 cmdTemplate = commandShell->errOffOrExecIgnore; 824 cmdTemplate = commandShell->errOffOrExecIgnore;
825 /* 825 /*
826 * The error ignoration (hee hee) is already taken care 826 * The error ignoration (hee hee) is already taken care
827 * of by the errOffOrExecIgnore template, so pretend error 827 * of by the errOffOrExecIgnore template, so pretend error
828 * checking is still on. 828 * checking is still on.
829 */ 829 */
830 errOff = FALSE; 830 errOff = FALSE;
831 } else { 831 } else {
832 errOff = FALSE; 832 errOff = FALSE;
833 } 833 }
834 } else { 834 } else {
835 errOff = FALSE; 835 errOff = FALSE;
836 } 836 }
837 } else { 837 } else {
838 838
839 /* 839 /*
840 * If errors are being checked and the shell doesn't have error control 840 * If errors are being checked and the shell doesn't have error control
841 * but does supply an errExit template, then setup commands to run 841 * but does supply an errExit template, then setup commands to run
842 * through it. 842 * through it.
843 */ 843 */
844 844
845 if (!commandShell->hasErrCtl && commandShell->errExit && 845 if (!commandShell->hasErrCtl && commandShell->errExit &&
846 commandShell->errExit[0] != '\0') { 846 commandShell->errExit[0] != '\0') {
847 if (!(job->flags & JOB_SILENT) && !shutUp) { 847 if (!(job->flags & JOB_SILENT) && !shutUp) {
848 if (commandShell->hasEchoCtl) { 848 if (commandShell->hasEchoCtl) {
849 DBPRINTF("%s\n", commandShell->echoOff); 849 DBPRINTF("%s\n", commandShell->echoOff);
850 } 850 }
851 DBPRINTF(commandShell->errOnOrEcho, escCmd); 851 DBPRINTF(commandShell->errOnOrEcho, escCmd);
852 shutUp = TRUE; 852 shutUp = TRUE;
853 } 853 }
854 /* If it's a comment line or blank, treat as an ignored error */ 854 /* If it's a comment line or blank, treat as an ignored error */
855 if ((escCmd[0] == commandShell->commentChar) || 855 if ((escCmd[0] == commandShell->commentChar) ||
856 (escCmd[0] == 0)) 856 (escCmd[0] == 0))
857 cmdTemplate = commandShell->errOffOrExecIgnore; 857 cmdTemplate = commandShell->errOffOrExecIgnore;
858 else 858 else
859 cmdTemplate = commandShell->errExit; 859 cmdTemplate = commandShell->errExit;
860 errOff = FALSE; 860 errOff = FALSE;
861 } 861 }
862 } 862 }
863 863
864 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 && 864 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 &&
865 (job->flags & JOB_TRACED) == 0) { 865 (job->flags & JOB_TRACED) == 0) {
866 DBPRINTF("set -%s\n", "x"); 866 DBPRINTF("set -%s\n", "x");
867 job->flags |= JOB_TRACED; 867 job->flags |= JOB_TRACED;
868 } 868 }
869 869
870 DBPRINTF(cmdTemplate, cmd); 870 DBPRINTF(cmdTemplate, cmd);
871 free(cmdStart); 871 free(cmdStart);
872 free(escCmd); 872 free(escCmd);
873 if (errOff) { 873 if (errOff) {
874 /* 874 /*
875 * If echoing is already off, there's no point in issuing the 875 * If echoing is already off, there's no point in issuing the
876 * echoOff command. Otherwise we issue it and pretend it was on 876 * echoOff command. Otherwise we issue it and pretend it was on
877 * for the whole command... 877 * for the whole command...
878 */ 878 */
879 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ 879 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
880 DBPRINTF("%s\n", commandShell->echoOff); 880 DBPRINTF("%s\n", commandShell->echoOff);
881 shutUp = TRUE; 881 shutUp = TRUE;
882 } 882 }
883 DBPRINTF("%s\n", commandShell->errOnOrEcho); 883 DBPRINTF("%s\n", commandShell->errOnOrEcho);
884 } 884 }
885 if (shutUp && commandShell->hasEchoCtl) { 885 if (shutUp && commandShell->hasEchoCtl) {
886 DBPRINTF("%s\n", commandShell->echoOn); 886 DBPRINTF("%s\n", commandShell->echoOn);
887 } 887 }
888} 888}
889 889
890/* Print all commands to the shell file that is later executed. 890/* Print all commands to the shell file that is later executed.
891 * 891 *
892 * The special command "..." stops printing and saves the remaining commands 892 * The special command "..." stops printing and saves the remaining commands
893 * to be executed later. */ 893 * to be executed later. */
894static void 894static void
895JobPrintCommands(Job *job) 895JobPrintCommands(Job *job)
896{ 896{
897 StringListNode *ln; 897 StringListNode *ln;
898 898
899 for (ln = job->node->commands->first; ln != NULL; ln = ln->next) { 899 for (ln = job->node->commands->first; ln != NULL; ln = ln->next) {
900 const char *cmd = ln->datum; 900 const char *cmd = ln->datum;
901 901
902 if (strcmp(cmd, "...") == 0) { 902 if (strcmp(cmd, "...") == 0) {
903 job->node->type |= OP_SAVE_CMDS; 903 job->node->type |= OP_SAVE_CMDS;
904 if ((job->flags & JOB_IGNDOTS) == 0) { 904 if ((job->flags & JOB_IGNDOTS) == 0) {
905 job->tailCmds = ln->next; 905 job->tailCmds = ln->next;
906 break; 906 break;
907 } 907 }
908 } else 908 } else
909 JobPrintCommand(job, ln->datum); 909 JobPrintCommand(job, ln->datum);
910 } 910 }
911} 911}
912 912
913/* Save the delayed commands, to be executed when everything else is done. */ 913/* Save the delayed commands, to be executed when everything else is done. */
914static void 914static void
915JobSaveCommands(Job *job) 915JobSaveCommands(Job *job)
916{ 916{
917 StringListNode *node; 917 StringListNode *node;
918 918
919 for (node = job->tailCmds; node != NULL; node = node->next) { 919 for (node = job->tailCmds; node != NULL; node = node->next) {
920 const char *cmd = node->datum; 920 const char *cmd = node->datum;
921 char *expanded_cmd; 921 char *expanded_cmd;
922 /* XXX: This Var_Subst is only intended to expand the dynamic 922 /* XXX: This Var_Subst is only intended to expand the dynamic
923 * variables such as .TARGET, .IMPSRC. It is not intended to 923 * variables such as .TARGET, .IMPSRC. It is not intended to
924 * expand the other variables as well; see deptgt-end.mk. */ 924 * expand the other variables as well; see deptgt-end.mk. */
925 (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd); 925 (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd);
926 /* TODO: handle errors */ 926 /* TODO: handle errors */
927 Lst_Append(Targ_GetEndNode()->commands, expanded_cmd); 927 Lst_Append(Targ_GetEndNode()->commands, expanded_cmd);
928 } 928 }
929} 929}
930 930
931 931
932/* Called to close both input and output pipes when a job is finished. */ 932/* Called to close both input and output pipes when a job is finished. */
933static void 933static void
934JobClose(Job *job) 934JobClose(Job *job)
935{ 935{
936 clearfd(job); 936 clearfd(job);
937 (void)close(job->outPipe); 937 (void)close(job->outPipe);
938 job->outPipe = -1; 938 job->outPipe = -1;
939 939
940 JobDoOutput(job, TRUE); 940 JobDoOutput(job, TRUE);
941 (void)close(job->inPipe); 941 (void)close(job->inPipe);
942 job->inPipe = -1; 942 job->inPipe = -1;
943} 943}
944 944
945/*- 945/*-
946 *----------------------------------------------------------------------- 946 *-----------------------------------------------------------------------
947 * JobFinish -- 947 * JobFinish --
948 * Do final processing for the given job including updating 948 * Do final processing for the given job including updating
949 * parents and starting new jobs as available/necessary. Note 949 * parents and starting new jobs as available/necessary. Note
950 * that we pay no attention to the JOB_IGNERR flag here. 950 * that we pay no attention to the JOB_IGNERR flag here.
951 * This is because when we're called because of a noexecute flag 951 * This is because when we're called because of a noexecute flag
952 * or something, jstat.w_status is 0 and when called from 952 * or something, jstat.w_status is 0 and when called from
953 * Job_CatchChildren, the status is zeroed if it s/b ignored. 953 * Job_CatchChildren, the status is zeroed if it s/b ignored.
954 * 954 *
955 * Input: 955 * Input:
956 * job job to finish 956 * job job to finish
957 * status sub-why job went away 957 * status sub-why job went away
958 * 958 *
959 * Side Effects: 959 * Side Effects:
960 * Final commands for the job are placed on postCommands. 960 * Final commands for the job are placed on postCommands.
961 * 961 *
962 * If we got an error and are aborting (aborting == ABORT_ERROR) and 962 * If we got an error and are aborting (aborting == ABORT_ERROR) and
963 * the job list is now empty, we are done for the day. 963 * the job list is now empty, we are done for the day.
964 * If we recognized an error (errors !=0), we set the aborting flag 964 * If we recognized an error (errors !=0), we set the aborting flag
965 * to ABORT_ERROR so no more jobs will be started. 965 * to ABORT_ERROR so no more jobs will be started.
966 *----------------------------------------------------------------------- 966 *-----------------------------------------------------------------------
967 */ 967 */
968static void 968static void
969JobFinish(Job *job, int status) 969JobFinish(Job *job, int status)
970{ 970{
971 Boolean done, return_job_token; 971 Boolean done, return_job_token;
972 972
973 DEBUG3(JOB, "JobFinish: %d [%s], status %d\n", 973 DEBUG3(JOB, "JobFinish: %d [%s], status %d\n",
974 job->pid, job->node->name, status); 974 job->pid, job->node->name, status);
975 975
976 if ((WIFEXITED(status) && 976 if ((WIFEXITED(status) &&
977 (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) || 977 (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) ||
978 WIFSIGNALED(status)) 978 WIFSIGNALED(status))
979 { 979 {
980 /* 980 /*
981 * If it exited non-zero and either we're doing things our 981 * If it exited non-zero and either we're doing things our
982 * way or we're not ignoring errors, the job is finished. 982 * way or we're not ignoring errors, the job is finished.
983 * Similarly, if the shell died because of a signal 983 * Similarly, if the shell died because of a signal
984 * the job is also finished. In these 984 * the job is also finished. In these
985 * cases, finish out the job's output before printing the exit 985 * cases, finish out the job's output before printing the exit
986 * status... 986 * status...
987 */ 987 */
988 JobClose(job); 988 JobClose(job);
989 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 989 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
990 (void)fclose(job->cmdFILE); 990 (void)fclose(job->cmdFILE);
991 job->cmdFILE = NULL; 991 job->cmdFILE = NULL;
992 } 992 }
993 done = TRUE; 993 done = TRUE;
994 } else if (WIFEXITED(status)) { 994 } else if (WIFEXITED(status)) {
995 /* 995 /*
996 * Deal with ignored errors in -B mode. We need to print a message 996 * Deal with ignored errors in -B mode. We need to print a message
997 * telling of the ignored error as well as setting status.w_status 997 * telling of the ignored error as well as setting status.w_status
998 * to 0 so the next command gets run. To do this, we set done to be 998 * to 0 so the next command gets run. To do this, we set done to be
999 * TRUE if in -B mode and the job exited non-zero. 999 * TRUE if in -B mode and the job exited non-zero.
1000 */ 1000 */
1001 done = WEXITSTATUS(status) != 0; 1001 done = WEXITSTATUS(status) != 0;
1002 /* 1002 /*
1003 * Old comment said: "Note we don't 1003 * Old comment said: "Note we don't
1004 * want to close down any of the streams until we know we're at the 1004 * want to close down any of the streams until we know we're at the
1005 * end." 1005 * end."
1006 * But we do. Otherwise when are we going to print the rest of the 1006 * But we do. Otherwise when are we going to print the rest of the
1007 * stuff? 1007 * stuff?
1008 */ 1008 */
1009 JobClose(job); 1009 JobClose(job);
1010 } else { 1010 } else {
1011 /* 1011 /*
1012 * No need to close things down or anything. 1012 * No need to close things down or anything.
1013 */ 1013 */
1014 done = FALSE; 1014 done = FALSE;
1015 } 1015 }
1016 1016
1017 if (done) { 1017 if (done) {
1018 if (WIFEXITED(status)) { 1018 if (WIFEXITED(status)) {
1019 DEBUG2(JOB, "Process %d [%s] exited.\n", 1019 DEBUG2(JOB, "Process %d [%s] exited.\n",
1020 job->pid, job->node->name); 1020 job->pid, job->node->name);
1021 if (WEXITSTATUS(status) != 0) { 1021 if (WEXITSTATUS(status) != 0) {
1022 if (job->node != lastNode) { 1022 if (job->node != lastNode) {
1023 MESSAGE(stdout, job->node); 1023 MESSAGE(stdout, job->node);
1024 lastNode = job->node; 1024 lastNode = job->node;
1025 } 1025 }
1026#ifdef USE_META 1026#ifdef USE_META
1027 if (useMeta) { 1027 if (useMeta) {
1028 meta_job_error(job, job->node, job->flags, WEXITSTATUS(status)); 1028 meta_job_error(job, job->node, job->flags, WEXITSTATUS(status));
1029 } 1029 }
1030#endif 1030#endif
1031 if (!dieQuietly(job->node, -1)) 1031 if (!dieQuietly(job->node, -1))
1032 (void)printf("*** [%s] Error code %d%s\n", 1032 (void)printf("*** [%s] Error code %d%s\n",
1033 job->node->name, 1033 job->node->name,
1034 WEXITSTATUS(status), 1034 WEXITSTATUS(status),
1035 (job->flags & JOB_IGNERR) ? " (ignored)" : ""); 1035 (job->flags & JOB_IGNERR) ? " (ignored)" : "");
1036 if (job->flags & JOB_IGNERR) { 1036 if (job->flags & JOB_IGNERR) {
1037 status = 0; 1037 status = 0;
1038 } else { 1038 } else {
1039 if (deleteOnError) { 1039 if (deleteOnError) {
1040 JobDeleteTarget(job->node); 1040 JobDeleteTarget(job->node);
1041 } 1041 }
1042 PrintOnError(job->node, NULL); 1042 PrintOnError(job->node, NULL);
1043 } 1043 }
1044 } else if (DEBUG(JOB)) { 1044 } else if (DEBUG(JOB)) {
1045 if (job->node != lastNode) { 1045 if (job->node != lastNode) {
1046 MESSAGE(stdout, job->node); 1046 MESSAGE(stdout, job->node);
1047 lastNode = job->node; 1047 lastNode = job->node;
1048 } 1048 }
1049 (void)printf("*** [%s] Completed successfully\n", 1049 (void)printf("*** [%s] Completed successfully\n",
1050 job->node->name); 1050 job->node->name);
1051 } 1051 }
1052 } else { 1052 } else {
1053 if (job->node != lastNode) { 1053 if (job->node != lastNode) {
1054 MESSAGE(stdout, job->node); 1054 MESSAGE(stdout, job->node);
1055 lastNode = job->node; 1055 lastNode = job->node;
1056 } 1056 }
1057 (void)printf("*** [%s] Signal %d\n", 1057 (void)printf("*** [%s] Signal %d\n",
1058 job->node->name, WTERMSIG(status)); 1058 job->node->name, WTERMSIG(status));
1059 if (deleteOnError) { 1059 if (deleteOnError) {
1060 JobDeleteTarget(job->node); 1060 JobDeleteTarget(job->node);
1061 } 1061 }
1062 } 1062 }
1063 (void)fflush(stdout); 1063 (void)fflush(stdout);
1064 } 1064 }
1065 1065
1066#ifdef USE_META 1066#ifdef USE_META
1067 if (useMeta) { 1067 if (useMeta) {
1068 int x; 1068 int x;
1069 1069
1070 if ((x = meta_job_finish(job)) != 0 && status == 0) { 1070 if ((x = meta_job_finish(job)) != 0 && status == 0) {
1071 status = x; 1071 status = x;
1072 } 1072 }
1073 } 1073 }
1074#endif 1074#endif
1075 1075
1076 return_job_token = FALSE; 1076 return_job_token = FALSE;
1077 1077
1078 Trace_Log(JOBEND, job); 1078 Trace_Log(JOBEND, job);
1079 if (!(job->flags & JOB_SPECIAL)) { 1079 if (!(job->flags & JOB_SPECIAL)) {
1080 if ((status != 0) || 1080 if ((status != 0) ||
1081 (aborting == ABORT_ERROR) || 1081 (aborting == ABORT_ERROR) ||
1082 (aborting == ABORT_INTERRUPT)) 1082 (aborting == ABORT_INTERRUPT))
1083 return_job_token = TRUE; 1083 return_job_token = TRUE;
1084 } 1084 }
1085 1085
1086 if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && (status == 0)) { 1086 if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && (status == 0)) {
1087 /* 1087 /*
1088 * As long as we aren't aborting and the job didn't return a non-zero 1088 * As long as we aren't aborting and the job didn't return a non-zero
1089 * status that we shouldn't ignore, we call Make_Update to update 1089 * status that we shouldn't ignore, we call Make_Update to update
1090 * the parents. 1090 * the parents.
1091 */ 1091 */
1092 JobSaveCommands(job); 1092 JobSaveCommands(job);
1093 job->node->made = MADE; 1093 job->node->made = MADE;
1094 if (!(job->flags & JOB_SPECIAL)) 1094 if (!(job->flags & JOB_SPECIAL))
1095 return_job_token = TRUE; 1095 return_job_token = TRUE;
1096 Make_Update(job->node); 1096 Make_Update(job->node);
1097 job->job_state = JOB_ST_FREE; 1097 job->job_state = JOB_ST_FREE;
1098 } else if (status != 0) { 1098 } else if (status != 0) {
1099 errors++; 1099 errors++;
1100 job->job_state = JOB_ST_FREE; 1100 job->job_state = JOB_ST_FREE;
1101 } 1101 }
1102 1102
1103 /* 1103 /*
1104 * Set aborting if any error. 1104 * Set aborting if any error.
1105 */ 1105 */
1106 if (errors && !opts.keepgoing && (aborting != ABORT_INTERRUPT)) { 1106 if (errors && !opts.keepgoing && (aborting != ABORT_INTERRUPT)) {
1107 /* 1107 /*
1108 * If we found any errors in this batch of children and the -k flag 1108 * If we found any errors in this batch of children and the -k flag
1109 * wasn't given, we set the aborting flag so no more jobs get 1109 * wasn't given, we set the aborting flag so no more jobs get
1110 * started. 1110 * started.
1111 */ 1111 */
1112 aborting = ABORT_ERROR; 1112 aborting = ABORT_ERROR;
1113 } 1113 }
1114 1114
1115 if (return_job_token) 1115 if (return_job_token)
1116 Job_TokenReturn(); 1116 Job_TokenReturn();
1117 1117
1118 if (aborting == ABORT_ERROR && jobTokensRunning == 0) { 1118 if (aborting == ABORT_ERROR && jobTokensRunning == 0) {
1119 /* 1119 /*
1120 * If we are aborting and the job table is now empty, we finish. 1120 * If we are aborting and the job table is now empty, we finish.
1121 */ 1121 */
1122 Finish(errors); 1122 Finish(errors);
1123 } 1123 }
1124} 1124}
1125 1125
1126/* Touch the given target. Called by JobStart when the -t flag was given. 1126/* Touch the given target. Called by JobStart when the -t flag was given.
1127 * 1127 *
1128 * The modification date of the file is changed. 1128 * The modification date of the file is changed.
1129 * If the file did not exist, it is created. */ 1129 * If the file did not exist, it is created. */
1130void 1130void
1131Job_Touch(GNode *gn, Boolean silent) 1131Job_Touch(GNode *gn, Boolean silent)
1132{ 1132{
1133 int streamID; /* ID of stream opened to do the touch */ 1133 int streamID; /* ID of stream opened to do the touch */
1134 struct utimbuf times; /* Times for utime() call */ 1134 struct utimbuf times; /* Times for utime() call */
1135 1135
1136 if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL| 1136 if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL|
1137 OP_SPECIAL|OP_PHONY)) { 1137 OP_SPECIAL|OP_PHONY)) {
1138 /* 1138 /*
1139 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets 1139 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
1140 * and, as such, shouldn't really be created. 1140 * and, as such, shouldn't really be created.
1141 */ 1141 */
1142 return; 1142 return;
1143 } 1143 }
1144 1144
1145 if (!silent || NoExecute(gn)) { 1145 if (!silent || !GNode_ShouldExecute(gn)) {
1146 (void)fprintf(stdout, "touch %s\n", gn->name); 1146 (void)fprintf(stdout, "touch %s\n", gn->name);
1147 (void)fflush(stdout); 1147 (void)fflush(stdout);
1148 } 1148 }
1149 1149
1150 if (NoExecute(gn)) { 1150 if (!GNode_ShouldExecute(gn)) {
1151 return; 1151 return;
1152 } 1152 }
1153 1153
1154 if (gn->type & OP_ARCHV) { 1154 if (gn->type & OP_ARCHV) {
1155 Arch_Touch(gn); 1155 Arch_Touch(gn);
1156 } else if (gn->type & OP_LIB) { 1156 } else if (gn->type & OP_LIB) {
1157 Arch_TouchLib(gn); 1157 Arch_TouchLib(gn);
1158 } else { 1158 } else {
1159 const char *file = GNode_Path(gn); 1159 const char *file = GNode_Path(gn);
1160 1160
1161 times.actime = times.modtime = now; 1161 times.actime = times.modtime = now;
1162 if (utime(file, &times) < 0){ 1162 if (utime(file, &times) < 0){
1163 streamID = open(file, O_RDWR | O_CREAT, 0666); 1163 streamID = open(file, O_RDWR | O_CREAT, 0666);
1164 1164
1165 if (streamID >= 0) { 1165 if (streamID >= 0) {
1166 char c; 1166 char c;
1167 1167
1168 /* 1168 /*
1169 * Read and write a byte to the file to change the 1169 * Read and write a byte to the file to change the
1170 * modification time, then close the file. 1170 * modification time, then close the file.
1171 */ 1171 */
1172 if (read(streamID, &c, 1) == 1) { 1172 if (read(streamID, &c, 1) == 1) {
1173 (void)lseek(streamID, (off_t)0, SEEK_SET); 1173 (void)lseek(streamID, (off_t)0, SEEK_SET);
1174 while (write(streamID, &c, 1) == -1 && errno == EAGAIN) 1174 while (write(streamID, &c, 1) == -1 && errno == EAGAIN)
1175 continue; 1175 continue;
1176 } 1176 }
1177 1177
1178 (void)close(streamID); 1178 (void)close(streamID);
1179 } else { 1179 } else {
1180 (void)fprintf(stdout, "*** couldn't touch %s: %s", 1180 (void)fprintf(stdout, "*** couldn't touch %s: %s",
1181 file, strerror(errno)); 1181 file, strerror(errno));
1182 (void)fflush(stdout); 1182 (void)fflush(stdout);
1183 } 1183 }
1184 } 1184 }
1185 } 1185 }
1186} 1186}
1187 1187
1188/* Make sure the given node has all the commands it needs. 1188/* Make sure the given node has all the commands it needs.
1189 * 1189 *
1190 * The node will have commands from the .DEFAULT rule added to it if it 1190 * The node will have commands from the .DEFAULT rule added to it if it
1191 * needs them. 1191 * needs them.
1192 * 1192 *
1193 * Input: 1193 * Input:
1194 * gn The target whose commands need verifying 1194 * gn The target whose commands need verifying
1195 * abortProc Function to abort with message 1195 * abortProc Function to abort with message
1196 * 1196 *
1197 * Results: 1197 * Results:
1198 * TRUE if the commands list is/was ok. 1198 * TRUE if the commands list is/was ok.
1199 */ 1199 */
1200Boolean 1200Boolean
1201Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 1201Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
1202{ 1202{
1203 if (GNode_IsTarget(gn)) 1203 if (GNode_IsTarget(gn))
1204 return TRUE; 1204 return TRUE;
1205 if (!Lst_IsEmpty(gn->commands)) 1205 if (!Lst_IsEmpty(gn->commands))
1206 return TRUE; 1206 return TRUE;
1207 if ((gn->type & OP_LIB) && !Lst_IsEmpty(gn->children)) 1207 if ((gn->type & OP_LIB) && !Lst_IsEmpty(gn->children))
1208 return TRUE; 1208 return TRUE;
1209 1209
1210 /* 1210 /*
1211 * No commands. Look for .DEFAULT rule from which we might infer 1211 * No commands. Look for .DEFAULT rule from which we might infer
1212 * commands 1212 * commands
1213 */ 1213 */
1214 if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) && 1214 if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) &&
1215 (gn->type & OP_SPECIAL) == 0) { 1215 (gn->type & OP_SPECIAL) == 0) {
1216 /* 1216 /*
1217 * Make only looks for a .DEFAULT if the node was never the 1217 * Make only looks for a .DEFAULT if the node was never the
1218 * target of an operator, so that's what we do too. If 1218 * target of an operator, so that's what we do too. If
1219 * a .DEFAULT was given, we substitute its commands for gn's 1219 * a .DEFAULT was given, we substitute its commands for gn's
1220 * commands and set the IMPSRC variable to be the target's name 1220 * commands and set the IMPSRC variable to be the target's name
1221 * The DEFAULT node acts like a transformation rule, in that 1221 * The DEFAULT node acts like a transformation rule, in that
1222 * gn also inherits any attributes or sources attached to 1222 * gn also inherits any attributes or sources attached to
1223 * .DEFAULT itself. 1223 * .DEFAULT itself.
1224 */ 1224 */
1225 Make_HandleUse(DEFAULT, gn); 1225 Make_HandleUse(DEFAULT, gn);
1226 Var_Set(IMPSRC, GNode_VarTarget(gn), gn); 1226 Var_Set(IMPSRC, GNode_VarTarget(gn), gn);
1227 return TRUE; 1227 return TRUE;
1228 } 1228 }
1229 1229
1230 if (Dir_MTime(gn, 0) != 0 || (gn->type & OP_SPECIAL)) 1230 if (Dir_MTime(gn, 0) != 0 || (gn->type & OP_SPECIAL))
1231 return TRUE; 1231 return TRUE;
1232 1232
1233 /* 1233 /*
1234 * The node wasn't the target of an operator. We have no .DEFAULT 1234 * The node wasn't the target of an operator. We have no .DEFAULT
1235 * rule to go on and the target doesn't already exist. There's 1235 * rule to go on and the target doesn't already exist. There's
1236 * nothing more we can do for this branch. If the -k flag wasn't 1236 * nothing more we can do for this branch. If the -k flag wasn't
1237 * given, we stop in our tracks, otherwise we just don't update 1237 * given, we stop in our tracks, otherwise we just don't update
1238 * this node's parents so they never get examined. 1238 * this node's parents so they never get examined.
1239 */ 1239 */
1240 1240
1241 if (gn->flags & FROM_DEPEND) { 1241 if (gn->flags & FROM_DEPEND) {
1242 if (!Job_RunTarget(".STALE", gn->fname)) 1242 if (!Job_RunTarget(".STALE", gn->fname))
1243 fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n", 1243 fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n",
1244 progname, gn->fname, gn->lineno, makeDependfile, 1244 progname, gn->fname, gn->lineno, makeDependfile,
1245 gn->name); 1245 gn->name);
1246 return TRUE; 1246 return TRUE;
1247 } 1247 }
1248 1248
1249 if (gn->type & OP_OPTIONAL) { 1249 if (gn->type & OP_OPTIONAL) {
1250 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", 1250 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n",
1251 progname, gn->name, "ignored"); 1251 progname, gn->name, "ignored");
1252 (void)fflush(stdout); 1252 (void)fflush(stdout);
1253 return TRUE; 1253 return TRUE;
1254 } 1254 }
1255 1255
1256 if (opts.keepgoing) { 1256 if (opts.keepgoing) {
1257 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n", 1257 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n",
1258 progname, gn->name, "continuing"); 1258 progname, gn->name, "continuing");
1259 (void)fflush(stdout); 1259 (void)fflush(stdout);
1260 return FALSE; 1260 return FALSE;
1261 } 1261 }
1262 1262
1263 abortProc("%s: don't know how to make %s. Stop", progname, gn->name); 1263 abortProc("%s: don't know how to make %s. Stop", progname, gn->name);
1264 return FALSE; 1264 return FALSE;
1265} 1265}
1266 1266
1267/* Execute the shell for the given job. 1267/* Execute the shell for the given job.
1268 * 1268 *
1269 * A shell is executed, its output is altered and the Job structure added 1269 * A shell is executed, its output is altered and the Job structure added
1270 * to the job table. 1270 * to the job table.
1271 */ 1271 */
1272static void 1272static void
1273JobExec(Job *job, char **argv) 1273JobExec(Job *job, char **argv)
1274{ 1274{
1275 int cpid; /* ID of new child */ 1275 int cpid; /* ID of new child */
1276 sigset_t mask; 1276 sigset_t mask;
1277 1277
1278 job->flags &= ~JOB_TRACED; 1278 job->flags &= ~JOB_TRACED;
1279 1279
1280 if (DEBUG(JOB)) { 1280 if (DEBUG(JOB)) {
1281 int i; 1281 int i;
1282 1282
1283 debug_printf("Running %s %sly\n", job->node->name, "local"); 1283 debug_printf("Running %s %sly\n", job->node->name, "local");
1284 debug_printf("\tCommand: "); 1284 debug_printf("\tCommand: ");
1285 for (i = 0; argv[i] != NULL; i++) { 1285 for (i = 0; argv[i] != NULL; i++) {
1286 debug_printf("%s ", argv[i]); 1286 debug_printf("%s ", argv[i]);
1287 } 1287 }
1288 debug_printf("\n"); 1288 debug_printf("\n");
1289 } 1289 }
1290 1290
1291 /* 1291 /*
1292 * Some jobs produce no output and it's disconcerting to have 1292 * Some jobs produce no output and it's disconcerting to have
1293 * no feedback of their running (since they produce no output, the 1293 * no feedback of their running (since they produce no output, the
1294 * banner with their name in it never appears). This is an attempt to 1294 * banner with their name in it never appears). This is an attempt to
1295 * provide that feedback, even if nothing follows it. 1295 * provide that feedback, even if nothing follows it.
1296 */ 1296 */
1297 if ((lastNode != job->node) && !(job->flags & JOB_SILENT)) { 1297 if ((lastNode != job->node) && !(job->flags & JOB_SILENT)) {
1298 MESSAGE(stdout, job->node); 1298 MESSAGE(stdout, job->node);
1299 lastNode = job->node; 1299 lastNode = job->node;
1300 } 1300 }
1301 1301
1302 /* No interruptions until this job is on the `jobs' list */ 1302 /* No interruptions until this job is on the `jobs' list */
1303 JobSigLock(&mask); 1303 JobSigLock(&mask);
1304 1304
1305 /* Pre-emptively mark job running, pid still zero though */ 1305 /* Pre-emptively mark job running, pid still zero though */
1306 job->job_state = JOB_ST_RUNNING; 1306 job->job_state = JOB_ST_RUNNING;
1307 1307
1308 cpid = vFork(); 1308 cpid = vFork();
1309 if (cpid == -1) 1309 if (cpid == -1)
1310 Punt("Cannot vfork: %s", strerror(errno)); 1310 Punt("Cannot vfork: %s", strerror(errno));
1311 1311
1312 if (cpid == 0) { 1312 if (cpid == 0) {
1313 /* Child */ 1313 /* Child */
1314 sigset_t tmask; 1314 sigset_t tmask;
1315 1315
1316#ifdef USE_META 1316#ifdef USE_META
1317 if (useMeta) { 1317 if (useMeta) {
1318 meta_job_child(job); 1318 meta_job_child(job);
1319 } 1319 }
1320#endif 1320#endif
1321 /* 1321 /*
1322 * Reset all signal handlers; this is necessary because we also 1322 * Reset all signal handlers; this is necessary because we also
1323 * need to unblock signals before we exec(2). 1323 * need to unblock signals before we exec(2).
1324 */ 1324 */
1325 JobSigReset(); 1325 JobSigReset();
1326 1326
1327 /* Now unblock signals */ 1327 /* Now unblock signals */
1328 sigemptyset(&tmask); 1328 sigemptyset(&tmask);
1329 JobSigUnlock(&tmask); 1329 JobSigUnlock(&tmask);
1330 1330
1331 /* 1331 /*
1332 * Must duplicate the input stream down to the child's input and 1332 * Must duplicate the input stream down to the child's input and
1333 * reset it to the beginning (again). Since the stream was marked 1333 * reset it to the beginning (again). Since the stream was marked
1334 * close-on-exec, we must clear that bit in the new input. 1334 * close-on-exec, we must clear that bit in the new input.
1335 */ 1335 */
1336 if (dup2(fileno(job->cmdFILE), 0) == -1) 1336 if (dup2(fileno(job->cmdFILE), 0) == -1)
1337 execDie("dup2", "job->cmdFILE"); 1337 execDie("dup2", "job->cmdFILE");
1338 if (fcntl(0, F_SETFD, 0) == -1) 1338 if (fcntl(0, F_SETFD, 0) == -1)
1339 execDie("fcntl clear close-on-exec", "stdin"); 1339 execDie("fcntl clear close-on-exec", "stdin");
1340 if (lseek(0, (off_t)0, SEEK_SET) == -1) 1340 if (lseek(0, (off_t)0, SEEK_SET) == -1)
1341 execDie("lseek to 0", "stdin"); 1341 execDie("lseek to 0", "stdin");
1342 1342
1343 if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { 1343 if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
1344 /* 1344 /*
1345 * Pass job token pipe to submakes. 1345 * Pass job token pipe to submakes.
1346 */ 1346 */
1347 if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) 1347 if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1)
1348 execDie("clear close-on-exec", "tokenWaitJob.inPipe"); 1348 execDie("clear close-on-exec", "tokenWaitJob.inPipe");
1349 if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) 1349 if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1)
1350 execDie("clear close-on-exec", "tokenWaitJob.outPipe"); 1350 execDie("clear close-on-exec", "tokenWaitJob.outPipe");
1351 } 1351 }
1352 1352
1353 /* 1353 /*
1354 * Set up the child's output to be routed through the pipe 1354 * Set up the child's output to be routed through the pipe
1355 * we've created for it. 1355 * we've created for it.
1356 */ 1356 */
1357 if (dup2(job->outPipe, 1) == -1) 1357 if (dup2(job->outPipe, 1) == -1)
1358 execDie("dup2", "job->outPipe"); 1358 execDie("dup2", "job->outPipe");
1359 1359
1360 /* 1360 /*
1361 * The output channels are marked close on exec. This bit was 1361 * The output channels are marked close on exec. This bit was
1362 * duplicated by the dup2(on some systems), so we have to clear 1362 * duplicated by the dup2(on some systems), so we have to clear
1363 * it before routing the shell's error output to the same place as 1363 * it before routing the shell's error output to the same place as
1364 * its standard output. 1364 * its standard output.
1365 */ 1365 */
1366 if (fcntl(1, F_SETFD, 0) == -1) 1366 if (fcntl(1, F_SETFD, 0) == -1)
1367 execDie("clear close-on-exec", "stdout"); 1367 execDie("clear close-on-exec", "stdout");
1368 if (dup2(1, 2) == -1) 1368 if (dup2(1, 2) == -1)
1369 execDie("dup2", "1, 2"); 1369 execDie("dup2", "1, 2");
1370 1370
1371 /* 1371 /*
1372 * We want to switch the child into a different process family so 1372 * We want to switch the child into a different process family so
1373 * we can kill it and all its descendants in one fell swoop, 1373 * we can kill it and all its descendants in one fell swoop,
1374 * by killing its process family, but not commit suicide. 1374 * by killing its process family, but not commit suicide.
1375 */ 1375 */
1376#if defined(MAKE_NATIVE) || defined(HAVE_SETPGID) 1376#if defined(MAKE_NATIVE) || defined(HAVE_SETPGID)
1377#if defined(SYSV) 1377#if defined(SYSV)
1378 /* XXX: dsl - I'm sure this should be setpgrp()... */ 1378 /* XXX: dsl - I'm sure this should be setpgrp()... */
1379 (void)setsid(); 1379 (void)setsid();
1380#else 1380#else
1381 (void)setpgid(0, getpid()); 1381 (void)setpgid(0, getpid());
1382#endif 1382#endif
1383#endif 1383#endif
1384 1384
1385 Var_ExportVars(); 1385 Var_ExportVars();
1386 1386
1387 (void)execv(shellPath, argv); 1387 (void)execv(shellPath, argv);
1388 execDie("exec", shellPath); 1388 execDie("exec", shellPath);
1389 } 1389 }
1390 1390
1391 /* Parent, continuing after the child exec */ 1391 /* Parent, continuing after the child exec */
1392 job->pid = cpid; 1392 job->pid = cpid;
1393 1393
1394 Trace_Log(JOBSTART, job); 1394 Trace_Log(JOBSTART, job);
1395 1395
1396#ifdef USE_META 1396#ifdef USE_META
1397 if (useMeta) { 1397 if (useMeta) {
1398 meta_job_parent(job, cpid); 1398 meta_job_parent(job, cpid);
1399 } 1399 }
1400#endif 1400#endif
1401 1401
1402 /* 1402 /*
1403 * Set the current position in the buffer to the beginning 1403 * Set the current position in the buffer to the beginning
1404 * and mark another stream to watch in the outputs mask 1404 * and mark another stream to watch in the outputs mask
1405 */ 1405 */
1406 job->curPos = 0; 1406 job->curPos = 0;
1407 1407
1408 watchfd(job); 1408 watchfd(job);
1409 1409
1410 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1410 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1411 (void)fclose(job->cmdFILE); 1411 (void)fclose(job->cmdFILE);
1412 job->cmdFILE = NULL; 1412 job->cmdFILE = NULL;
1413 } 1413 }
1414 1414
1415 /* 1415 /*
1416 * Now the job is actually running, add it to the table. 1416 * Now the job is actually running, add it to the table.
1417 */ 1417 */
1418 if (DEBUG(JOB)) { 1418 if (DEBUG(JOB)) {
1419 debug_printf("JobExec(%s): pid %d added to jobs table\n", 1419 debug_printf("JobExec(%s): pid %d added to jobs table\n",
1420 job->node->name, job->pid); 1420 job->node->name, job->pid);
1421 job_table_dump("job started"); 1421 job_table_dump("job started");
1422 } 1422 }
1423 JobSigUnlock(&mask); 1423 JobSigUnlock(&mask);
1424} 1424}
1425 1425
1426/* Create the argv needed to execute the shell for a given job. */ 1426/* Create the argv needed to execute the shell for a given job. */
1427static void 1427static void
1428JobMakeArgv(Job *job, char **argv) 1428JobMakeArgv(Job *job, char **argv)
1429{ 1429{
1430 int argc; 1430 int argc;
1431 static char args[10]; /* For merged arguments */ 1431 static char args[10]; /* For merged arguments */
1432 1432
1433 argv[0] = UNCONST(shellName); 1433 argv[0] = UNCONST(shellName);
1434 argc = 1; 1434 argc = 1;
1435 1435
1436 if ((commandShell->exit && commandShell->exit[0] != '-') || 1436 if ((commandShell->exit && commandShell->exit[0] != '-') ||
1437 (commandShell->echo && commandShell->echo[0] != '-')) 1437 (commandShell->echo && commandShell->echo[0] != '-'))
1438 { 1438 {
1439 /* 1439 /*
1440 * At least one of the flags doesn't have a minus before it, so 1440 * At least one of the flags doesn't have a minus before it, so
1441 * merge them together. Have to do this because the *(&(@*#*&#$# 1441 * merge them together. Have to do this because the *(&(@*#*&#$#
1442 * Bourne shell thinks its second argument is a file to source. 1442 * Bourne shell thinks its second argument is a file to source.
1443 * Grrrr. Note the ten-character limitation on the combined arguments. 1443 * Grrrr. Note the ten-character limitation on the combined arguments.
1444 */ 1444 */
1445 (void)snprintf(args, sizeof(args), "-%s%s", 1445 (void)snprintf(args, sizeof(args), "-%s%s",
1446 ((job->flags & JOB_IGNERR) ? "" : 1446 ((job->flags & JOB_IGNERR) ? "" :
1447 (commandShell->exit ? commandShell->exit : "")), 1447 (commandShell->exit ? commandShell->exit : "")),
1448 ((job->flags & JOB_SILENT) ? "" : 1448 ((job->flags & JOB_SILENT) ? "" :
1449 (commandShell->echo ? commandShell->echo : ""))); 1449 (commandShell->echo ? commandShell->echo : "")));
1450 1450
1451 if (args[1]) { 1451 if (args[1]) {
1452 argv[argc] = args; 1452 argv[argc] = args;
1453 argc++; 1453 argc++;
1454 } 1454 }
1455 } else { 1455 } else {
1456 if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1456 if (!(job->flags & JOB_IGNERR) && commandShell->exit) {
1457 argv[argc] = UNCONST(commandShell->exit); 1457 argv[argc] = UNCONST(commandShell->exit);
1458 argc++; 1458 argc++;
1459 } 1459 }
1460 if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1460 if (!(job->flags & JOB_SILENT) && commandShell->echo) {
1461 argv[argc] = UNCONST(commandShell->echo); 1461 argv[argc] = UNCONST(commandShell->echo);
1462 argc++; 1462 argc++;
1463 } 1463 }
1464 } 1464 }
1465 argv[argc] = NULL; 1465 argv[argc] = NULL;
1466} 1466}
1467 1467
1468/*- 1468/*-
1469 *----------------------------------------------------------------------- 1469 *-----------------------------------------------------------------------
1470 * JobStart -- 1470 * JobStart --
1471 * Start a target-creation process going for the target described 1471 * Start a target-creation process going for the target described
1472 * by the graph node gn. 1472 * by the graph node gn.
1473 * 1473 *
1474 * Input: 1474 * Input:
1475 * gn target to create 1475 * gn target to create
1476 * flags flags for the job to override normal ones. 1476 * flags flags for the job to override normal ones.
1477 * e.g. JOB_SPECIAL or JOB_IGNDOTS 1477 * e.g. JOB_SPECIAL or JOB_IGNDOTS
1478 * previous The previous Job structure for this node, if any. 1478 * previous The previous Job structure for this node, if any.
1479 * 1479 *
1480 * Results: 1480 * Results:
1481 * JOB_ERROR if there was an error in the commands, JOB_FINISHED 1481 * JOB_ERROR if there was an error in the commands, JOB_FINISHED
1482 * if there isn't actually anything left to do for the job and 1482 * if there isn't actually anything left to do for the job and
1483 * JOB_RUNNING if the job has been started. 1483 * JOB_RUNNING if the job has been started.
1484 * 1484 *
1485 * Side Effects: 1485 * Side Effects:
1486 * A new Job node is created and added to the list of running 1486 * A new Job node is created and added to the list of running
1487 * jobs. PMake is forked and a child shell created. 1487 * jobs. PMake is forked and a child shell created.
1488 * 1488 *
1489 * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set 1489 * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set
1490 * JOB_IGNDOTS is never set (dsl) 1490 * JOB_IGNDOTS is never set (dsl)
1491 * Also the return value is ignored by everyone. 1491 * Also the return value is ignored by everyone.
1492 *----------------------------------------------------------------------- 1492 *-----------------------------------------------------------------------
1493 */ 1493 */
1494static JobStartResult 1494static JobStartResult
1495JobStart(GNode *gn, int flags) 1495JobStart(GNode *gn, int flags)
1496{ 1496{
1497 Job *job; /* new job descriptor */ 1497 Job *job; /* new job descriptor */
1498 char *argv[10]; /* Argument vector to shell */ 1498 char *argv[10]; /* Argument vector to shell */
1499 Boolean cmdsOK; /* true if the nodes commands were all right */ 1499 Boolean cmdsOK; /* true if the nodes commands were all right */
1500 Boolean noExec; /* Set true if we decide not to run the job */ 1500 Boolean noExec; /* Set true if we decide not to run the job */
1501 int tfd; /* File descriptor to the temp file */ 1501 int tfd; /* File descriptor to the temp file */
1502 1502
1503 for (job = job_table; job < job_table_end; job++) { 1503 for (job = job_table; job < job_table_end; job++) {
1504 if (job->job_state == JOB_ST_FREE) 1504 if (job->job_state == JOB_ST_FREE)
1505 break; 1505 break;
1506 } 1506 }
1507 if (job >= job_table_end) 1507 if (job >= job_table_end)
1508 Punt("JobStart no job slots vacant"); 1508 Punt("JobStart no job slots vacant");
1509 1509
1510 memset(job, 0, sizeof *job); 1510 memset(job, 0, sizeof *job);
1511 job->job_state = JOB_ST_SETUP; 1511 job->job_state = JOB_ST_SETUP;
1512 if (gn->type & OP_SPECIAL) 1512 if (gn->type & OP_SPECIAL)
1513 flags |= JOB_SPECIAL; 1513 flags |= JOB_SPECIAL;
1514 1514
1515 job->node = gn; 1515 job->node = gn;
1516 job->tailCmds = NULL; 1516 job->tailCmds = NULL;
1517 1517
1518 /* 1518 /*
1519 * Set the initial value of the flags for this job based on the global 1519 * Set the initial value of the flags for this job based on the global
1520 * ones and the node's attributes... Any flags supplied by the caller 1520 * ones and the node's attributes... Any flags supplied by the caller
1521 * are also added to the field. 1521 * are also added to the field.
1522 */ 1522 */
1523 job->flags = 0; 1523 job->flags = 0;
1524 if (Targ_Ignore(gn)) { 1524 if (Targ_Ignore(gn)) {
1525 job->flags |= JOB_IGNERR; 1525 job->flags |= JOB_IGNERR;
1526 } 1526 }
1527 if (Targ_Silent(gn)) { 1527 if (Targ_Silent(gn)) {
1528 job->flags |= JOB_SILENT; 1528 job->flags |= JOB_SILENT;
1529 } 1529 }
1530 job->flags |= flags; 1530 job->flags |= flags;
1531 1531
1532 /* 1532 /*
1533 * Check the commands now so any attributes from .DEFAULT have a chance 1533 * Check the commands now so any attributes from .DEFAULT have a chance
1534 * to migrate to the node 1534 * to migrate to the node
1535 */ 1535 */
1536 cmdsOK = Job_CheckCommands(gn, Error); 1536 cmdsOK = Job_CheckCommands(gn, Error);
1537 1537
1538 job->inPollfd = NULL; 1538 job->inPollfd = NULL;
1539 /* 1539 /*
1540 * If the -n flag wasn't given, we open up OUR (not the child's) 1540 * If the -n flag wasn't given, we open up OUR (not the child's)
1541 * temporary file to stuff commands in it. The thing is rd/wr so we don't 1541 * temporary file to stuff commands in it. The thing is rd/wr so we don't
1542 * need to reopen it to feed it to the shell. If the -n flag *was* given, 1542 * need to reopen it to feed it to the shell. If the -n flag *was* given,
1543 * we just set the file to be stdout. Cute, huh? 1543 * we just set the file to be stdout. Cute, huh?
1544 */ 1544 */
1545 if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) || 1545 if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) ||
1546 (!opts.noExecute && !opts.touchFlag)) { 1546 (!opts.noExecute && !opts.touchFlag)) {
1547 /* 1547 /*
1548 * tfile is the name of a file into which all shell commands are 1548 * tfile is the name of a file into which all shell commands are
1549 * put. It is removed before the child shell is executed, unless 1549 * put. It is removed before the child shell is executed, unless
1550 * DEBUG(SCRIPT) is set. 1550 * DEBUG(SCRIPT) is set.
1551 */ 1551 */
1552 char *tfile; 1552 char *tfile;
1553 sigset_t mask; 1553 sigset_t mask;
1554 /* 1554 /*
1555 * We're serious here, but if the commands were bogus, we're 1555 * We're serious here, but if the commands were bogus, we're
1556 * also dead... 1556 * also dead...
1557 */ 1557 */
1558 if (!cmdsOK) { 1558 if (!cmdsOK) {
1559 PrintOnError(gn, NULL); /* provide some clue */ 1559 PrintOnError(gn, NULL); /* provide some clue */
1560 DieHorribly(); 1560 DieHorribly();
1561 } 1561 }
1562 1562
1563 JobSigLock(&mask); 1563 JobSigLock(&mask);
1564 tfd = mkTempFile(TMPPAT, &tfile); 1564 tfd = mkTempFile(TMPPAT, &tfile);
1565 if (!DEBUG(SCRIPT)) 1565 if (!DEBUG(SCRIPT))
1566 (void)eunlink(tfile); 1566 (void)eunlink(tfile);
1567 JobSigUnlock(&mask); 1567 JobSigUnlock(&mask);
1568 1568
1569 job->cmdFILE = fdopen(tfd, "w+"); 1569 job->cmdFILE = fdopen(tfd, "w+");
1570 if (job->cmdFILE == NULL) { 1570 if (job->cmdFILE == NULL) {
1571 Punt("Could not fdopen %s", tfile); 1571 Punt("Could not fdopen %s", tfile);
1572 } 1572 }
1573 (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC); 1573 (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC);
1574 /* 1574 /*
1575 * Send the commands to the command file, flush all its buffers then 1575 * Send the commands to the command file, flush all its buffers then
1576 * rewind and remove the thing. 1576 * rewind and remove the thing.
1577 */ 1577 */
1578 noExec = FALSE; 1578 noExec = FALSE;
1579 1579
1580#ifdef USE_META 1580#ifdef USE_META
1581 if (useMeta) { 1581 if (useMeta) {
1582 meta_job_start(job, gn); 1582 meta_job_start(job, gn);
1583 if (Targ_Silent(gn)) { /* might have changed */ 1583 if (Targ_Silent(gn)) { /* might have changed */
1584 job->flags |= JOB_SILENT; 1584 job->flags |= JOB_SILENT;
1585 } 1585 }
1586 } 1586 }
1587#endif 1587#endif
1588 /* 1588 /*
1589 * We can do all the commands at once. hooray for sanity 1589 * We can do all the commands at once. hooray for sanity
1590 */ 1590 */
1591 numCommands = 0; 1591 numCommands = 0;
1592 JobPrintCommands(job); 1592 JobPrintCommands(job);
1593 1593
1594 /* 1594 /*
1595 * If we didn't print out any commands to the shell script, 1595 * If we didn't print out any commands to the shell script,
1596 * there's not much point in executing the shell, is there? 1596 * there's not much point in executing the shell, is there?
1597 */ 1597 */
1598 if (numCommands == 0) { 1598 if (numCommands == 0) {
1599 noExec = TRUE; 1599 noExec = TRUE;
1600 } 1600 }
1601 1601
1602 free(tfile); 1602 free(tfile);
1603 } else if (NoExecute(gn)) { 1603 } else if (!GNode_ShouldExecute(gn)) {
1604 /* 1604 /*
1605 * Not executing anything -- just print all the commands to stdout 1605 * Not executing anything -- just print all the commands to stdout
1606 * in one fell swoop. This will still set up job->tailCmds correctly. 1606 * in one fell swoop. This will still set up job->tailCmds correctly.
1607 */ 1607 */
1608 if (lastNode != gn) { 1608 if (lastNode != gn) {
1609 MESSAGE(stdout, gn); 1609 MESSAGE(stdout, gn);
1610 lastNode = gn; 1610 lastNode = gn;
1611 } 1611 }
1612 job->cmdFILE = stdout; 1612 job->cmdFILE = stdout;
1613 /* 1613 /*
1614 * Only print the commands if they're ok, but don't die if they're 1614 * Only print the commands if they're ok, but don't die if they're
1615 * not -- just let the user know they're bad and keep going. It 1615 * not -- just let the user know they're bad and keep going. It
1616 * doesn't do any harm in this case and may do some good. 1616 * doesn't do any harm in this case and may do some good.
1617 */ 1617 */
1618 if (cmdsOK) 1618 if (cmdsOK)
1619 JobPrintCommands(job); 1619 JobPrintCommands(job);
1620 /* 1620 /*
1621 * Don't execute the shell, thank you. 1621 * Don't execute the shell, thank you.
1622 */ 1622 */
1623 noExec = TRUE; 1623 noExec = TRUE;
1624 } else { 1624 } else {
1625 /* 1625 /*
1626 * Just touch the target and note that no shell should be executed. 1626 * Just touch the target and note that no shell should be executed.
1627 * Set cmdFILE to stdout to make life easier. Check the commands, too, 1627 * Set cmdFILE to stdout to make life easier. Check the commands, too,
1628 * but don't die if they're no good -- it does no harm to keep working 1628 * but don't die if they're no good -- it does no harm to keep working
1629 * up the graph. 1629 * up the graph.
1630 */ 1630 */
1631 job->cmdFILE = stdout; 1631 job->cmdFILE = stdout;
1632 Job_Touch(gn, job->flags&JOB_SILENT); 1632 Job_Touch(gn, job->flags&JOB_SILENT);
1633 noExec = TRUE; 1633 noExec = TRUE;
1634 } 1634 }
1635 /* Just in case it isn't already... */ 1635 /* Just in case it isn't already... */
1636 (void)fflush(job->cmdFILE); 1636 (void)fflush(job->cmdFILE);
1637 1637
1638 /* 1638 /*
1639 * If we're not supposed to execute a shell, don't. 1639 * If we're not supposed to execute a shell, don't.
1640 */ 1640 */
1641 if (noExec) { 1641 if (noExec) {
1642 if (!(job->flags & JOB_SPECIAL)) 1642 if (!(job->flags & JOB_SPECIAL))
1643 Job_TokenReturn(); 1643 Job_TokenReturn();
1644 /* 1644 /*
1645 * Unlink and close the command file if we opened one 1645 * Unlink and close the command file if we opened one
1646 */ 1646 */
1647 if (job->cmdFILE != stdout) { 1647 if (job->cmdFILE != stdout) {
1648 if (job->cmdFILE != NULL) { 1648 if (job->cmdFILE != NULL) {
1649 (void)fclose(job->cmdFILE); 1649 (void)fclose(job->cmdFILE);
1650 job->cmdFILE = NULL; 1650 job->cmdFILE = NULL;
1651 } 1651 }
1652 } 1652 }
1653 1653
1654 /* 1654 /*
1655 * We only want to work our way up the graph if we aren't here because 1655 * We only want to work our way up the graph if we aren't here because
1656 * the commands for the job were no good. 1656 * the commands for the job were no good.
1657 */ 1657 */
1658 if (cmdsOK && aborting == ABORT_NONE) { 1658 if (cmdsOK && aborting == ABORT_NONE) {
1659 JobSaveCommands(job); 1659 JobSaveCommands(job);
1660 job->node->made = MADE; 1660 job->node->made = MADE;
1661 Make_Update(job->node); 1661 Make_Update(job->node);
1662 } 1662 }
1663 job->job_state = JOB_ST_FREE; 1663 job->job_state = JOB_ST_FREE;
1664 return cmdsOK ? JOB_FINISHED : JOB_ERROR; 1664 return cmdsOK ? JOB_FINISHED : JOB_ERROR;
1665 } 1665 }
1666 1666
1667 /* 1667 /*
1668 * Set up the control arguments to the shell. This is based on the flags 1668 * Set up the control arguments to the shell. This is based on the flags
1669 * set earlier for this job. 1669 * set earlier for this job.
1670 */ 1670 */
1671 JobMakeArgv(job, argv); 1671 JobMakeArgv(job, argv);
1672 1672
1673 /* Create the pipe by which we'll get the shell's output. */ 1673 /* Create the pipe by which we'll get the shell's output. */
1674 JobCreatePipe(job, 3); 1674 JobCreatePipe(job, 3);
1675 1675
1676 JobExec(job, argv); 1676 JobExec(job, argv);
1677 return JOB_RUNNING; 1677 return JOB_RUNNING;
1678} 1678}
1679 1679
1680static char * 1680static char *
1681JobOutput(Job *job, char *cp, char *endp) 1681JobOutput(Job *job, char *cp, char *endp)
1682{ 1682{
1683 char *ecp; 1683 char *ecp;
1684 1684
1685 if (commandShell->noPrint && commandShell->noPrint[0] != '\0') { 1685 if (commandShell->noPrint && commandShell->noPrint[0] != '\0') {
1686 while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) { 1686 while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) {
1687 if (cp != ecp) { 1687 if (cp != ecp) {
1688 *ecp = '\0'; 1688 *ecp = '\0';
1689 /* 1689 /*
1690 * The only way there wouldn't be a newline after 1690 * The only way there wouldn't be a newline after
1691 * this line is if it were the last in the buffer. 1691 * this line is if it were the last in the buffer.
1692 * however, since the non-printable comes after it, 1692 * however, since the non-printable comes after it,
1693 * there must be a newline, so we don't print one. 1693 * there must be a newline, so we don't print one.
1694 */ 1694 */
1695 (void)fprintf(stdout, "%s", cp); 1695 (void)fprintf(stdout, "%s", cp);
1696 (void)fflush(stdout); 1696 (void)fflush(stdout);
1697 } 1697 }
1698 cp = ecp + commandShell->noPrintLen; 1698 cp = ecp + commandShell->noPrintLen;
1699 if (cp != endp) { 1699 if (cp != endp) {
1700 /* 1700 /*
1701 * Still more to print, look again after skipping 1701 * Still more to print, look again after skipping
1702 * the whitespace following the non-printable 1702 * the whitespace following the non-printable
1703 * command.... 1703 * command....
1704 */ 1704 */
1705 cp++; 1705 cp++;
1706 while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 1706 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
1707 cp++; 1707 cp++;
1708 } 1708 }
1709 } else { 1709 } else {
1710 return cp; 1710 return cp;
1711 } 1711 }
1712 } 1712 }
1713 } 1713 }
1714 return cp; 1714 return cp;
1715} 1715}
1716 1716
1717/*- 1717/*-
1718 *----------------------------------------------------------------------- 1718 *-----------------------------------------------------------------------
1719 * JobDoOutput -- 1719 * JobDoOutput --
1720 * This function is called at different times depending on 1720 * This function is called at different times depending on
1721 * whether the user has specified that output is to be collected 1721 * whether the user has specified that output is to be collected
1722 * via pipes or temporary files. In the former case, we are called 1722 * via pipes or temporary files. In the former case, we are called
1723 * whenever there is something to read on the pipe. We collect more 1723 * whenever there is something to read on the pipe. We collect more
1724 * output from the given job and store it in the job's outBuf. If 1724 * output from the given job and store it in the job's outBuf. If
1725 * this makes up a line, we print it tagged by the job's identifier, 1725 * this makes up a line, we print it tagged by the job's identifier,
1726 * as necessary. 1726 * as necessary.
1727 * If output has been collected in a temporary file, we open the 1727 * If output has been collected in a temporary file, we open the
1728 * file and read it line by line, transferring it to our own 1728 * file and read it line by line, transferring it to our own
1729 * output channel until the file is empty. At which point we 1729 * output channel until the file is empty. At which point we
1730 * remove the temporary file. 1730 * remove the temporary file.
1731 * In both cases, however, we keep our figurative eye out for the 1731 * In both cases, however, we keep our figurative eye out for the
1732 * 'noPrint' line for the shell from which the output came. If 1732 * 'noPrint' line for the shell from which the output came. If
1733 * we recognize a line, we don't print it. If the command is not 1733 * we recognize a line, we don't print it. If the command is not
1734 * alone on the line (the character after it is not \0 or \n), we 1734 * alone on the line (the character after it is not \0 or \n), we
1735 * do print whatever follows it. 1735 * do print whatever follows it.
1736 * 1736 *
1737 * Input: 1737 * Input:
1738 * job the job whose output needs printing 1738 * job the job whose output needs printing
1739 * finish TRUE if this is the last time we'll be called 1739 * finish TRUE if this is the last time we'll be called
1740 * for this job 1740 * for this job
1741 * 1741 *
1742 * Side Effects: 1742 * Side Effects:
1743 * curPos may be shifted as may the contents of outBuf. 1743 * curPos may be shifted as may the contents of outBuf.
1744 *----------------------------------------------------------------------- 1744 *-----------------------------------------------------------------------
1745 */ 1745 */
1746static void 1746static void
1747JobDoOutput(Job *job, Boolean finish) 1747JobDoOutput(Job *job, Boolean finish)
1748{ 1748{
1749 Boolean gotNL = FALSE; /* true if got a newline */ 1749 Boolean gotNL = FALSE; /* true if got a newline */
1750 Boolean fbuf; /* true if our buffer filled up */ 1750 Boolean fbuf; /* true if our buffer filled up */
1751 size_t nr; /* number of bytes read */ 1751 size_t nr; /* number of bytes read */
1752 size_t i; /* auxiliary index into outBuf */ 1752 size_t i; /* auxiliary index into outBuf */
1753 size_t max; /* limit for i (end of current data) */ 1753 size_t max; /* limit for i (end of current data) */
1754 ssize_t nRead; /* (Temporary) number of bytes read */ 1754 ssize_t nRead; /* (Temporary) number of bytes read */
1755 1755
1756 /* 1756 /*
1757 * Read as many bytes as will fit in the buffer. 1757 * Read as many bytes as will fit in the buffer.
1758 */ 1758 */
1759end_loop: 1759end_loop:
1760 gotNL = FALSE; 1760 gotNL = FALSE;
1761 fbuf = FALSE; 1761 fbuf = FALSE;
1762 1762
1763 nRead = read(job->inPipe, &job->outBuf[job->curPos], 1763 nRead = read(job->inPipe, &job->outBuf[job->curPos],
1764 JOB_BUFSIZE - job->curPos); 1764 JOB_BUFSIZE - job->curPos);
1765 if (nRead < 0) { 1765 if (nRead < 0) {
1766 if (errno == EAGAIN) 1766 if (errno == EAGAIN)
1767 return; 1767 return;
1768 if (DEBUG(JOB)) { 1768 if (DEBUG(JOB)) {
1769 perror("JobDoOutput(piperead)"); 1769 perror("JobDoOutput(piperead)");
1770 } 1770 }
1771 nr = 0; 1771 nr = 0;
1772 } else { 1772 } else {
1773 nr = (size_t)nRead; 1773 nr = (size_t)nRead;
1774 } 1774 }
1775 1775
1776 /* 1776 /*
1777 * If we hit the end-of-file (the job is dead), we must flush its 1777 * If we hit the end-of-file (the job is dead), we must flush its
1778 * remaining output, so pretend we read a newline if there's any 1778 * remaining output, so pretend we read a newline if there's any
1779 * output remaining in the buffer. 1779 * output remaining in the buffer.
1780 * Also clear the 'finish' flag so we stop looping. 1780 * Also clear the 'finish' flag so we stop looping.
1781 */ 1781 */
1782 if ((nr == 0) && (job->curPos != 0)) { 1782 if ((nr == 0) && (job->curPos != 0)) {
1783 job->outBuf[job->curPos] = '\n'; 1783 job->outBuf[job->curPos] = '\n';
1784 nr = 1; 1784 nr = 1;
1785 finish = FALSE; 1785 finish = FALSE;
1786 } else if (nr == 0) { 1786 } else if (nr == 0) {
1787 finish = FALSE; 1787 finish = FALSE;
1788 } 1788 }
1789 1789
1790 /* 1790 /*
1791 * Look for the last newline in the bytes we just got. If there is 1791 * Look for the last newline in the bytes we just got. If there is
1792 * one, break out of the loop with 'i' as its index and gotNL set 1792 * one, break out of the loop with 'i' as its index and gotNL set
1793 * TRUE. 1793 * TRUE.
1794 */ 1794 */
1795 max = job->curPos + nr; 1795 max = job->curPos + nr;
1796 for (i = job->curPos + nr - 1; i >= job->curPos && i != (size_t)-1; i--) { 1796 for (i = job->curPos + nr - 1; i >= job->curPos && i != (size_t)-1; i--) {
1797 if (job->outBuf[i] == '\n') { 1797 if (job->outBuf[i] == '\n') {
1798 gotNL = TRUE; 1798 gotNL = TRUE;
1799 break; 1799 break;
1800 } else if (job->outBuf[i] == '\0') { 1800 } else if (job->outBuf[i] == '\0') {
1801 /* 1801 /*
1802 * Why? 1802 * Why?
1803 */ 1803 */
1804 job->outBuf[i] = ' '; 1804 job->outBuf[i] = ' ';
1805 } 1805 }
1806 } 1806 }
1807 1807
1808 if (!gotNL) { 1808 if (!gotNL) {
1809 job->curPos += nr; 1809 job->curPos += nr;
1810 if (job->curPos == JOB_BUFSIZE) { 1810 if (job->curPos == JOB_BUFSIZE) {
1811 /* 1811 /*
1812 * If we've run out of buffer space, we have no choice 1812 * If we've run out of buffer space, we have no choice
1813 * but to print the stuff. sigh. 1813 * but to print the stuff. sigh.
1814 */ 1814 */
1815 fbuf = TRUE; 1815 fbuf = TRUE;
1816 i = job->curPos; 1816 i = job->curPos;
1817 } 1817 }
1818 } 1818 }
1819 if (gotNL || fbuf) { 1819 if (gotNL || fbuf) {
1820 /* 1820 /*
1821 * Need to send the output to the screen. Null terminate it 1821 * Need to send the output to the screen. Null terminate it
1822 * first, overwriting the newline character if there was one. 1822 * first, overwriting the newline character if there was one.
1823 * So long as the line isn't one we should filter (according 1823 * So long as the line isn't one we should filter (according
1824 * to the shell description), we print the line, preceded 1824 * to the shell description), we print the line, preceded
1825 * by a target banner if this target isn't the same as the 1825 * by a target banner if this target isn't the same as the
1826 * one for which we last printed something. 1826 * one for which we last printed something.
1827 * The rest of the data in the buffer are then shifted down 1827 * The rest of the data in the buffer are then shifted down
1828 * to the start of the buffer and curPos is set accordingly. 1828 * to the start of the buffer and curPos is set accordingly.
1829 */ 1829 */
1830 job->outBuf[i] = '\0'; 1830 job->outBuf[i] = '\0';
1831 if (i >= job->curPos) { 1831 if (i >= job->curPos) {
1832 char *cp; 1832 char *cp;
1833 1833
1834 cp = JobOutput(job, job->outBuf, &job->outBuf[i]); 1834 cp = JobOutput(job, job->outBuf, &job->outBuf[i]);
1835 1835
1836 /* 1836 /*
1837 * There's still more in that thar buffer. This time, though, 1837 * There's still more in that thar buffer. This time, though,
1838 * we know there's no newline at the end, so we add one of 1838 * we know there's no newline at the end, so we add one of
1839 * our own free will. 1839 * our own free will.
1840 */ 1840 */
1841 if (*cp != '\0') { 1841 if (*cp != '\0') {
1842 if (!opts.beSilent && job->node != lastNode) { 1842 if (!opts.beSilent && job->node != lastNode) {
1843 MESSAGE(stdout, job->node); 1843 MESSAGE(stdout, job->node);
1844 lastNode = job->node; 1844 lastNode = job->node;
1845 } 1845 }
1846#ifdef USE_META 1846#ifdef USE_META
1847 if (useMeta) { 1847 if (useMeta) {
1848 meta_job_output(job, cp, gotNL ? "\n" : ""); 1848 meta_job_output(job, cp, gotNL ? "\n" : "");
1849 } 1849 }
1850#endif 1850#endif
1851 (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); 1851 (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");
1852 (void)fflush(stdout); 1852 (void)fflush(stdout);
1853 } 1853 }
1854 } 1854 }
1855 /* 1855 /*
1856 * max is the last offset still in the buffer. Move any remaining 1856 * max is the last offset still in the buffer. Move any remaining
1857 * characters to the start of the buffer and update the end marker 1857 * characters to the start of the buffer and update the end marker
1858 * curPos. 1858 * curPos.
1859 */ 1859 */
1860 if (i < max) { 1860 if (i < max) {
1861 (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); 1861 (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
1862 job->curPos = max - (i + 1); 1862 job->curPos = max - (i + 1);
1863 } else { 1863 } else {
1864 assert(i == max); 1864 assert(i == max);
1865 job->curPos = 0; 1865 job->curPos = 0;
1866 } 1866 }
1867 } 1867 }
1868 if (finish) { 1868 if (finish) {
1869 /* 1869 /*
1870 * If the finish flag is true, we must loop until we hit 1870 * If the finish flag is true, we must loop until we hit
1871 * end-of-file on the pipe. This is guaranteed to happen 1871 * end-of-file on the pipe. This is guaranteed to happen
1872 * eventually since the other end of the pipe is now closed 1872 * eventually since the other end of the pipe is now closed
1873 * (we closed it explicitly and the child has exited). When 1873 * (we closed it explicitly and the child has exited). When
1874 * we do get an EOF, finish will be set FALSE and we'll fall 1874 * we do get an EOF, finish will be set FALSE and we'll fall
1875 * through and out. 1875 * through and out.
1876 */ 1876 */
1877 goto end_loop; 1877 goto end_loop;
1878 } 1878 }
1879} 1879}
1880 1880
1881static void 1881static void
1882JobRun(GNode *targ) 1882JobRun(GNode *targ)
1883{ 1883{
1884#if 0 1884#if 0
1885 /* 1885 /*
1886 * Unfortunately it is too complicated to run .BEGIN, .END, and 1886 * Unfortunately it is too complicated to run .BEGIN, .END, and
1887 * .INTERRUPT job in the parallel job module. As of 2020-09-25, 1887 * .INTERRUPT job in the parallel job module. As of 2020-09-25,
1888 * unit-tests/deptgt-end-jobs.mk hangs in an endless loop. 1888 * unit-tests/deptgt-end-jobs.mk hangs in an endless loop.
1889 * 1889 *
1890 * Running these jobs in compat mode also guarantees that these 1890 * Running these jobs in compat mode also guarantees that these
1891 * jobs do not overlap with other unrelated jobs. 1891 * jobs do not overlap with other unrelated jobs.
1892 */ 1892 */
1893 List *lst = Lst_New(); 1893 List *lst = Lst_New();
1894 Lst_Append(lst, targ); 1894 Lst_Append(lst, targ);
1895 (void)Make_Run(lst); 1895 (void)Make_Run(lst);
1896 Lst_Destroy(lst, NULL); 1896 Lst_Destroy(lst, NULL);
1897 JobStart(targ, JOB_SPECIAL); 1897 JobStart(targ, JOB_SPECIAL);
1898 while (jobTokensRunning) { 1898 while (jobTokensRunning) {
1899 Job_CatchOutput(); 1899 Job_CatchOutput();
1900 } 1900 }
1901#else 1901#else
1902 Compat_Make(targ, targ); 1902 Compat_Make(targ, targ);
1903 if (targ->made == ERROR) { 1903 if (targ->made == ERROR) {
1904 PrintOnError(targ, "\n\nStop."); 1904 PrintOnError(targ, "\n\nStop.");
1905 exit(1); 1905 exit(1);
1906 } 1906 }
1907#endif 1907#endif
1908} 1908}
1909 1909
1910/* Handle the exit of a child. Called from Make_Make. 1910/* Handle the exit of a child. Called from Make_Make.
1911 * 1911 *
1912 * The job descriptor is removed from the list of children. 1912 * The job descriptor is removed from the list of children.
1913 * 1913 *
1914 * Notes: 1914 * Notes:
1915 * We do waits, blocking or not, according to the wisdom of our 1915 * We do waits, blocking or not, according to the wisdom of our
1916 * caller, until there are no more children to report. For each 1916 * caller, until there are no more children to report. For each
1917 * job, call JobFinish to finish things off. 1917 * job, call JobFinish to finish things off.
1918 */ 1918 */
1919void 1919void
1920Job_CatchChildren(void) 1920Job_CatchChildren(void)
1921{ 1921{
1922 int pid; /* pid of dead child */ 1922 int pid; /* pid of dead child */
1923 int status; /* Exit/termination status */ 1923 int status; /* Exit/termination status */
1924 1924
1925 /* 1925 /*
1926 * Don't even bother if we know there's no one around. 1926 * Don't even bother if we know there's no one around.
1927 */ 1927 */
1928 if (jobTokensRunning == 0) 1928 if (jobTokensRunning == 0)
1929 return; 1929 return;
1930 1930
1931 while ((pid = waitpid((pid_t) -1, &status, WNOHANG | WUNTRACED)) > 0) { 1931 while ((pid = waitpid((pid_t) -1, &status, WNOHANG | WUNTRACED)) > 0) {
1932 DEBUG2(JOB, "Process %d exited/stopped status %x.\n", pid, status); 1932 DEBUG2(JOB, "Process %d exited/stopped status %x.\n", pid, status);
1933 JobReapChild(pid, status, TRUE); 1933 JobReapChild(pid, status, TRUE);
1934 } 1934 }
1935} 1935}
1936 1936
1937/* 1937/*
1938 * It is possible that wait[pid]() was called from elsewhere, 1938 * It is possible that wait[pid]() was called from elsewhere,
1939 * this lets us reap jobs regardless. 1939 * this lets us reap jobs regardless.
1940 */ 1940 */
1941void 1941void
1942JobReapChild(pid_t pid, int status, Boolean isJobs) 1942JobReapChild(pid_t pid, int status, Boolean isJobs)
1943{ 1943{
1944 Job *job; /* job descriptor for dead child */ 1944 Job *job; /* job descriptor for dead child */
1945 1945
1946 /* 1946 /*
1947 * Don't even bother if we know there's no one around. 1947 * Don't even bother if we know there's no one around.
1948 */ 1948 */
1949 if (jobTokensRunning == 0) 1949 if (jobTokensRunning == 0)
1950 return; 1950 return;
1951 1951
1952 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs); 1952 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs);
1953 if (job == NULL) { 1953 if (job == NULL) {
1954 if (isJobs) { 1954 if (isJobs) {
1955 if (!lurking_children) 1955 if (!lurking_children)
1956 Error("Child (%d) status %x not in table?", pid, status); 1956 Error("Child (%d) status %x not in table?", pid, status);
1957 } 1957 }
1958 return; /* not ours */ 1958 return; /* not ours */
1959 } 1959 }
1960 if (WIFSTOPPED(status)) { 1960 if (WIFSTOPPED(status)) {
1961 DEBUG2(JOB, "Process %d (%s) stopped.\n", job->pid, job->node->name); 1961 DEBUG2(JOB, "Process %d (%s) stopped.\n", job->pid, job->node->name);
1962 if (!make_suspended) { 1962 if (!make_suspended) {
1963 switch (WSTOPSIG(status)) { 1963 switch (WSTOPSIG(status)) {
1964 case SIGTSTP: 1964 case SIGTSTP:
1965 (void)printf("*** [%s] Suspended\n", job->node->name); 1965 (void)printf("*** [%s] Suspended\n", job->node->name);
1966 break; 1966 break;
1967 case SIGSTOP: 1967 case SIGSTOP:
1968 (void)printf("*** [%s] Stopped\n", job->node->name); 1968 (void)printf("*** [%s] Stopped\n", job->node->name);
1969 break; 1969 break;
1970 default: 1970 default:
1971 (void)printf("*** [%s] Stopped -- signal %d\n", 1971 (void)printf("*** [%s] Stopped -- signal %d\n",
1972 job->node->name, WSTOPSIG(status)); 1972 job->node->name, WSTOPSIG(status));
1973 } 1973 }
1974 job->job_suspended = 1; 1974 job->job_suspended = 1;
1975 } 1975 }
1976 (void)fflush(stdout); 1976 (void)fflush(stdout);
1977 return; 1977 return;
1978 } 1978 }
1979 1979
1980 job->job_state = JOB_ST_FINISHED; 1980 job->job_state = JOB_ST_FINISHED;
1981 job->exit_status = status; 1981 job->exit_status = status;
1982 1982
1983 JobFinish(job, status); 1983 JobFinish(job, status);
1984} 1984}
1985 1985
1986/* Catch the output from our children, if we're using pipes do so. Otherwise 1986/* Catch the output from our children, if we're using pipes do so. Otherwise
1987 * just block time until we get a signal(most likely a SIGCHLD) since there's 1987 * just block time until we get a signal(most likely a SIGCHLD) since there's
1988 * no point in just spinning when there's nothing to do and the reaping of a 1988 * no point in just spinning when there's nothing to do and the reaping of a
1989 * child can wait for a while. */ 1989 * child can wait for a while. */
1990void 1990void
1991Job_CatchOutput(void) 1991Job_CatchOutput(void)
1992{ 1992{
1993 int nready; 1993 int nready;
1994 Job *job; 1994 Job *job;
1995 unsigned int i; 1995 unsigned int i;
1996 1996
1997 (void)fflush(stdout); 1997 (void)fflush(stdout);
1998 1998
1999 /* The first fd in the list is the job token pipe */ 1999 /* The first fd in the list is the job token pipe */
2000 do { 2000 do {
2001 nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC); 2001 nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC);
2002 } while (nready < 0 && errno == EINTR); 2002 } while (nready < 0 && errno == EINTR);
2003 2003
2004 if (nready < 0) 2004 if (nready < 0)
2005 Punt("poll: %s", strerror(errno)); 2005 Punt("poll: %s", strerror(errno));
2006 2006
2007 if (nready > 0 && readyfd(&childExitJob)) { 2007 if (nready > 0 && readyfd(&childExitJob)) {
2008 char token = 0; 2008 char token = 0;
2009 ssize_t count; 2009 ssize_t count;
2010 count = read(childExitJob.inPipe, &token, 1); 2010 count = read(childExitJob.inPipe, &token, 1);
2011 switch (count) { 2011 switch (count) {
2012 case 0: 2012 case 0:
2013 Punt("unexpected eof on token pipe"); 2013 Punt("unexpected eof on token pipe");
2014 case -1: 2014 case -1:
2015 Punt("token pipe read: %s", strerror(errno)); 2015 Punt("token pipe read: %s", strerror(errno));
2016 case 1: 2016 case 1:
2017 if (token == DO_JOB_RESUME[0]) 2017 if (token == DO_JOB_RESUME[0])
2018 /* Complete relay requested from our SIGCONT handler */ 2018 /* Complete relay requested from our SIGCONT handler */
2019 JobRestartJobs(); 2019 JobRestartJobs();
2020 break; 2020 break;
2021 default: 2021 default:
2022 abort(); 2022 abort();
2023 } 2023 }
2024 --nready; 2024 --nready;
2025 } 2025 }
2026 2026
2027 Job_CatchChildren(); 2027 Job_CatchChildren();
2028 if (nready == 0) 2028 if (nready == 0)
2029 return; 2029 return;
2030 2030
2031 for (i = npseudojobs * nfds_per_job(); i < nfds; i++) { 2031 for (i = npseudojobs * nfds_per_job(); i < nfds; i++) {
2032 if (!fds[i].revents) 2032 if (!fds[i].revents)
2033 continue; 2033 continue;
2034 job = jobfds[i]; 2034 job = jobfds[i];
2035 if (job->job_state == JOB_ST_RUNNING) 2035 if (job->job_state == JOB_ST_RUNNING)
2036 JobDoOutput(job, FALSE); 2036 JobDoOutput(job, FALSE);
2037#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2037#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2038 /* 2038 /*
2039 * With meta mode, we may have activity on the job's filemon 2039 * With meta mode, we may have activity on the job's filemon
2040 * descriptor too, which at the moment is any pollfd other than 2040 * descriptor too, which at the moment is any pollfd other than
2041 * job->inPollfd. 2041 * job->inPollfd.
2042 */ 2042 */
2043 if (useMeta && job->inPollfd != &fds[i]) { 2043 if (useMeta && job->inPollfd != &fds[i]) {
2044 if (meta_job_event(job) <= 0) { 2044 if (meta_job_event(job) <= 0) {
2045 fds[i].events = 0; /* never mind */ 2045 fds[i].events = 0; /* never mind */
2046 } 2046 }
2047 } 2047 }
2048#endif 2048#endif
2049 if (--nready == 0) 2049 if (--nready == 0)
2050 return; 2050 return;
2051 } 2051 }
2052} 2052}
2053 2053
2054/* Start the creation of a target. Basically a front-end for JobStart used by 2054/* Start the creation of a target. Basically a front-end for JobStart used by
2055 * the Make module. */ 2055 * the Make module. */
2056void 2056void
2057Job_Make(GNode *gn) 2057Job_Make(GNode *gn)
2058{ 2058{
2059 (void)JobStart(gn, 0); 2059 (void)JobStart(gn, 0);
2060} 2060}
2061 2061
2062void 2062void
2063Shell_Init(void) 2063Shell_Init(void)
2064{ 2064{
2065 if (shellPath == NULL) { 2065 if (shellPath == NULL) {
2066 /* 2066 /*
2067 * We are using the default shell, which may be an absolute 2067 * We are using the default shell, which may be an absolute
2068 * path if DEFSHELL_CUSTOM is defined. 2068 * path if DEFSHELL_CUSTOM is defined.
2069 */ 2069 */
2070 shellName = commandShell->name; 2070 shellName = commandShell->name;
2071#ifdef DEFSHELL_CUSTOM 2071#ifdef DEFSHELL_CUSTOM
2072 if (*shellName == '/') { 2072 if (*shellName == '/') {
2073 shellPath = shellName; 2073 shellPath = shellName;
2074 shellName = strrchr(shellPath, '/'); 2074 shellName = strrchr(shellPath, '/');
2075 shellName++; 2075 shellName++;
2076 } else 2076 } else
2077#endif 2077#endif
2078 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName); 2078 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
2079 } 2079 }
2080 Var_Set_with_flags(".SHELL", shellPath, VAR_CMDLINE, VAR_SET_READONLY); 2080 Var_Set_with_flags(".SHELL", shellPath, VAR_CMDLINE, VAR_SET_READONLY);
2081 if (commandShell->exit == NULL) { 2081 if (commandShell->exit == NULL) {
2082 commandShell->exit = ""; 2082 commandShell->exit = "";
2083 } 2083 }
2084 if (commandShell->echo == NULL) { 2084 if (commandShell->echo == NULL) {
2085 commandShell->echo = ""; 2085 commandShell->echo = "";
2086 } 2086 }
2087 if (commandShell->hasErrCtl && commandShell->exit[0] != '\0') { 2087 if (commandShell->hasErrCtl && commandShell->exit[0] != '\0') {
2088 if (shellErrFlag && 2088 if (shellErrFlag &&
2089 strcmp(commandShell->exit, &shellErrFlag[1]) != 0) { 2089 strcmp(commandShell->exit, &shellErrFlag[1]) != 0) {
2090 free(shellErrFlag); 2090 free(shellErrFlag);
2091 shellErrFlag = NULL; 2091 shellErrFlag = NULL;
2092 } 2092 }
2093 if (!shellErrFlag) { 2093 if (!shellErrFlag) {
2094 size_t n = strlen(commandShell->exit) + 2; 2094 size_t n = strlen(commandShell->exit) + 2;
2095 2095
2096 shellErrFlag = bmake_malloc(n); 2096 shellErrFlag = bmake_malloc(n);
2097 if (shellErrFlag) { 2097 if (shellErrFlag) {
2098 snprintf(shellErrFlag, n, "-%s", commandShell->exit); 2098 snprintf(shellErrFlag, n, "-%s", commandShell->exit);
2099 } 2099 }
2100 } 2100 }
2101 } else if (shellErrFlag) { 2101 } else if (shellErrFlag) {
2102 free(shellErrFlag); 2102 free(shellErrFlag);
2103 shellErrFlag = NULL; 2103 shellErrFlag = NULL;
2104 } 2104 }
2105} 2105}
2106 2106
2107/* Return the string literal that is used in the current command shell 2107/* Return the string literal that is used in the current command shell
2108 * to produce a newline character. */ 2108 * to produce a newline character. */
2109const char * 2109const char *
2110Shell_GetNewline(void) 2110Shell_GetNewline(void)
2111{ 2111{
2112 return commandShell->newline; 2112 return commandShell->newline;
2113} 2113}
2114 2114
2115void 2115void
2116Job_SetPrefix(void) 2116Job_SetPrefix(void)
2117{ 2117{
2118 if (targPrefix) { 2118 if (targPrefix) {
2119 free(targPrefix); 2119 free(targPrefix);
2120 } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) { 2120 } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) {
2121 Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL); 2121 Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL);
2122 } 2122 }
2123 2123
2124 (void)Var_Subst("${" MAKE_JOB_PREFIX "}", 2124 (void)Var_Subst("${" MAKE_JOB_PREFIX "}",
2125 VAR_GLOBAL, VARE_WANTRES, &targPrefix); 2125 VAR_GLOBAL, VARE_WANTRES, &targPrefix);
2126 /* TODO: handle errors */ 2126 /* TODO: handle errors */
2127} 2127}
2128 2128
2129/* Initialize the process module. */ 2129/* Initialize the process module. */
2130void 2130void
2131Job_Init(void) 2131Job_Init(void)
2132{ 2132{
2133 Job_SetPrefix(); 2133 Job_SetPrefix();
2134 /* Allocate space for all the job info */ 2134 /* Allocate space for all the job info */
2135 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table); 2135 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table);
2136 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table); 2136 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table);
2137 job_table_end = job_table + opts.maxJobs; 2137 job_table_end = job_table + opts.maxJobs;
2138 wantToken = 0; 2138 wantToken = 0;
2139 2139
2140 aborting = ABORT_NONE; 2140 aborting = ABORT_NONE;
2141 errors = 0; 2141 errors = 0;
2142 2142
2143 lastNode = NULL; 2143 lastNode = NULL;
2144 2144
2145 /* 2145 /*
2146 * There is a non-zero chance that we already have children. 2146 * There is a non-zero chance that we already have children.
2147 * eg after 'make -f- <<EOF' 2147 * eg after 'make -f- <<EOF'
2148 * Since their termination causes a 'Child (pid) not in table' message, 2148 * Since their termination causes a 'Child (pid) not in table' message,
2149 * Collect the status of any that are already dead, and suppress the 2149 * Collect the status of any that are already dead, and suppress the
2150 * error message if there are any undead ones. 2150 * error message if there are any undead ones.
2151 */ 2151 */
2152 for (;;) { 2152 for (;;) {
2153 int rval, status; 2153 int rval, status;
2154 rval = waitpid((pid_t) -1, &status, WNOHANG); 2154 rval = waitpid((pid_t) -1, &status, WNOHANG);
2155 if (rval > 0) 2155 if (rval > 0)
2156 continue; 2156 continue;
2157 if (rval == 0) 2157 if (rval == 0)
2158 lurking_children = 1; 2158 lurking_children = 1;
2159 break; 2159 break;
2160 } 2160 }
2161 2161
2162 Shell_Init(); 2162 Shell_Init();
2163 2163
2164 JobCreatePipe(&childExitJob, 3); 2164 JobCreatePipe(&childExitJob, 3);
2165 2165
2166 /* Preallocate enough for the maximum number of jobs. */ 2166 /* Preallocate enough for the maximum number of jobs. */
2167 fds = bmake_malloc(sizeof(*fds) * 2167 fds = bmake_malloc(sizeof(*fds) *
2168 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job()); 2168 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job());
2169 jobfds = bmake_malloc(sizeof(*jobfds) * 2169 jobfds = bmake_malloc(sizeof(*jobfds) *
2170 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job()); 2170 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job());
2171 2171
2172 /* These are permanent entries and take slots 0 and 1 */ 2172 /* These are permanent entries and take slots 0 and 1 */
2173 watchfd(&tokenWaitJob); 2173 watchfd(&tokenWaitJob);
2174 watchfd(&childExitJob); 2174 watchfd(&childExitJob);
2175 2175
2176 sigemptyset(&caught_signals); 2176 sigemptyset(&caught_signals);
2177 /* 2177 /*
2178 * Install a SIGCHLD handler. 2178 * Install a SIGCHLD handler.
2179 */ 2179 */
2180 (void)bmake_signal(SIGCHLD, JobChildSig); 2180 (void)bmake_signal(SIGCHLD, JobChildSig);
2181 sigaddset(&caught_signals, SIGCHLD); 2181 sigaddset(&caught_signals, SIGCHLD);
2182 2182
2183#define ADDSIG(s,h) \ 2183#define ADDSIG(s,h) \
2184 if (bmake_signal(s, SIG_IGN) != SIG_IGN) { \ 2184 if (bmake_signal(s, SIG_IGN) != SIG_IGN) { \
2185 sigaddset(&caught_signals, s); \ 2185 sigaddset(&caught_signals, s); \
2186 (void)bmake_signal(s, h); \ 2186 (void)bmake_signal(s, h); \
2187 } 2187 }
2188 2188
2189 /* 2189 /*
2190 * Catch the four signals that POSIX specifies if they aren't ignored. 2190 * Catch the four signals that POSIX specifies if they aren't ignored.
2191 * JobPassSig will take care of calling JobInterrupt if appropriate. 2191 * JobPassSig will take care of calling JobInterrupt if appropriate.
2192 */ 2192 */
2193 ADDSIG(SIGINT, JobPassSig_int) 2193 ADDSIG(SIGINT, JobPassSig_int)
2194 ADDSIG(SIGHUP, JobPassSig_term) 2194 ADDSIG(SIGHUP, JobPassSig_term)
2195 ADDSIG(SIGTERM, JobPassSig_term) 2195 ADDSIG(SIGTERM, JobPassSig_term)
2196 ADDSIG(SIGQUIT, JobPassSig_term) 2196 ADDSIG(SIGQUIT, JobPassSig_term)
2197 2197
2198 /* 2198 /*
2199 * There are additional signals that need to be caught and passed if 2199 * There are additional signals that need to be caught and passed if
2200 * either the export system wants to be told directly of signals or if 2200 * either the export system wants to be told directly of signals or if
2201 * we're giving each job its own process group (since then it won't get 2201 * we're giving each job its own process group (since then it won't get
2202 * signals from the terminal driver as we own the terminal) 2202 * signals from the terminal driver as we own the terminal)
2203 */ 2203 */
2204 ADDSIG(SIGTSTP, JobPassSig_suspend) 2204 ADDSIG(SIGTSTP, JobPassSig_suspend)
2205 ADDSIG(SIGTTOU, JobPassSig_suspend) 2205 ADDSIG(SIGTTOU, JobPassSig_suspend)
2206 ADDSIG(SIGTTIN, JobPassSig_suspend) 2206 ADDSIG(SIGTTIN, JobPassSig_suspend)
2207 ADDSIG(SIGWINCH, JobCondPassSig) 2207 ADDSIG(SIGWINCH, JobCondPassSig)
2208 ADDSIG(SIGCONT, JobContinueSig) 2208 ADDSIG(SIGCONT, JobContinueSig)
2209#undef ADDSIG 2209#undef ADDSIG
2210 2210
2211 (void)Job_RunTarget(".BEGIN", NULL); 2211 (void)Job_RunTarget(".BEGIN", NULL);
2212 /* Create the .END node now, even though no code in the unit tests 2212 /* Create the .END node now, even though no code in the unit tests
2213 * depends on it. See also Targ_GetEndNode in Compat_Run. */ 2213 * depends on it. See also Targ_GetEndNode in Compat_Run. */
2214 (void)Targ_GetEndNode(); 2214 (void)Targ_GetEndNode();
2215} 2215}
2216 2216
2217static void JobSigReset(void) 2217static void JobSigReset(void)
2218{ 2218{
2219#define DELSIG(s) \ 2219#define DELSIG(s) \
2220 if (sigismember(&caught_signals, s)) { \ 2220 if (sigismember(&caught_signals, s)) { \
2221 (void)bmake_signal(s, SIG_DFL); \ 2221 (void)bmake_signal(s, SIG_DFL); \
2222 } 2222 }
2223 2223
2224 DELSIG(SIGINT) 2224 DELSIG(SIGINT)
2225 DELSIG(SIGHUP) 2225 DELSIG(SIGHUP)
2226 DELSIG(SIGQUIT) 2226 DELSIG(SIGQUIT)
2227 DELSIG(SIGTERM) 2227 DELSIG(SIGTERM)
2228 DELSIG(SIGTSTP) 2228 DELSIG(SIGTSTP)
2229 DELSIG(SIGTTOU) 2229 DELSIG(SIGTTOU)
2230 DELSIG(SIGTTIN) 2230 DELSIG(SIGTTIN)
2231 DELSIG(SIGWINCH) 2231 DELSIG(SIGWINCH)
2232 DELSIG(SIGCONT) 2232 DELSIG(SIGCONT)
2233#undef DELSIG 2233#undef DELSIG
2234 (void)bmake_signal(SIGCHLD, SIG_DFL); 2234 (void)bmake_signal(SIGCHLD, SIG_DFL);
2235} 2235}
2236 2236
2237/* Find a shell in 'shells' given its name, or return NULL. */ 2237/* Find a shell in 'shells' given its name, or return NULL. */
2238static Shell * 2238static Shell *
2239JobMatchShell(const char *name) 2239JobMatchShell(const char *name)
2240{ 2240{
2241 Shell *sh = shells; 2241 Shell *sh = shells;
2242 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0]; 2242 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0];
2243 2243
2244 for (sh = shells; sh < shellsEnd; sh++) { 2244 for (sh = shells; sh < shellsEnd; sh++) {
2245 if (strcmp(name, sh->name) == 0) 2245 if (strcmp(name, sh->name) == 0)
2246 return sh; 2246 return sh;
2247 } 2247 }
2248 return NULL; 2248 return NULL;
2249} 2249}
2250 2250
2251/*- 2251/*-
2252 *----------------------------------------------------------------------- 2252 *-----------------------------------------------------------------------
2253 * Job_ParseShell -- 2253 * Job_ParseShell --
2254 * Parse a shell specification and set up commandShell, shellPath 2254 * Parse a shell specification and set up commandShell, shellPath
2255 * and shellName appropriately. 2255 * and shellName appropriately.
2256 * 2256 *
2257 * Input: 2257 * Input:
2258 * line The shell spec 2258 * line The shell spec
2259 * 2259 *
2260 * Results: 2260 * Results:
2261 * FALSE if the specification was incorrect. 2261 * FALSE if the specification was incorrect.
2262 * 2262 *
2263 * Side Effects: 2263 * Side Effects:
2264 * commandShell points to a Shell structure (either predefined or 2264 * commandShell points to a Shell structure (either predefined or
2265 * created from the shell spec), shellPath is the full path of the 2265 * created from the shell spec), shellPath is the full path of the
2266 * shell described by commandShell, while shellName is just the 2266 * shell described by commandShell, while shellName is just the
2267 * final component of shellPath. 2267 * final component of shellPath.
2268 * 2268 *
2269 * Notes: 2269 * Notes:
2270 * A shell specification consists of a .SHELL target, with dependency 2270 * A shell specification consists of a .SHELL target, with dependency
2271 * operator, followed by a series of blank-separated words. Double 2271 * operator, followed by a series of blank-separated words. Double
2272 * quotes can be used to use blanks in words. A backslash escapes 2272 * quotes can be used to use blanks in words. A backslash escapes
2273 * anything (most notably a double-quote and a space) and 2273 * anything (most notably a double-quote and a space) and
2274 * provides the functionality it does in C. Each word consists of 2274 * provides the functionality it does in C. Each word consists of
2275 * keyword and value separated by an equal sign. There should be no 2275 * keyword and value separated by an equal sign. There should be no
2276 * unnecessary spaces in the word. The keywords are as follows: 2276 * unnecessary spaces in the word. The keywords are as follows:
2277 * name Name of shell. 2277 * name Name of shell.
2278 * path Location of shell. 2278 * path Location of shell.
2279 * quiet Command to turn off echoing. 2279 * quiet Command to turn off echoing.
2280 * echo Command to turn echoing on 2280 * echo Command to turn echoing on
2281 * filter Result of turning off echoing that shouldn't be 2281 * filter Result of turning off echoing that shouldn't be
2282 * printed. 2282 * printed.
2283 * echoFlag Flag to turn echoing on at the start 2283 * echoFlag Flag to turn echoing on at the start
2284 * errFlag Flag to turn error checking on at the start 2284 * errFlag Flag to turn error checking on at the start
2285 * hasErrCtl True if shell has error checking control 2285 * hasErrCtl True if shell has error checking control
2286 * newline String literal to represent a newline char 2286 * newline String literal to represent a newline char
2287 * check Command to turn on error checking if hasErrCtl 2287 * check Command to turn on error checking if hasErrCtl
2288 * is TRUE or template of command to echo a command 2288 * is TRUE or template of command to echo a command
2289 * for which error checking is off if hasErrCtl is 2289 * for which error checking is off if hasErrCtl is
2290 * FALSE. 2290 * FALSE.
2291 * ignore Command to turn off error checking if hasErrCtl 2291 * ignore Command to turn off error checking if hasErrCtl
2292 * is TRUE or template of command to execute a 2292 * is TRUE or template of command to execute a
2293 * command so as to ignore any errors it returns if 2293 * command so as to ignore any errors it returns if
2294 * hasErrCtl is FALSE. 2294 * hasErrCtl is FALSE.
2295 * 2295 *
2296 *----------------------------------------------------------------------- 2296 *-----------------------------------------------------------------------
2297 */ 2297 */
2298Boolean 2298Boolean
2299Job_ParseShell(char *line) 2299Job_ParseShell(char *line)
2300{ 2300{
2301 Words wordsList; 2301 Words wordsList;
2302 char **words; 2302 char **words;
2303 char **argv; 2303 char **argv;
2304 size_t argc; 2304 size_t argc;
2305 char *path; 2305 char *path;
2306 Shell newShell; 2306 Shell newShell;
2307 Boolean fullSpec = FALSE; 2307 Boolean fullSpec = FALSE;
2308 Shell *sh; 2308 Shell *sh;
2309 2309
2310 pp_skip_whitespace(&line); 2310 pp_skip_whitespace(&line);
2311 2311
2312 free(shellArgv); 2312 free(shellArgv);
2313 2313
2314 memset(&newShell, 0, sizeof(newShell)); 2314 memset(&newShell, 0, sizeof(newShell));
2315 2315
2316 /* 2316 /*
2317 * Parse the specification by keyword 2317 * Parse the specification by keyword
2318 */ 2318 */
2319 wordsList = Str_Words(line, TRUE); 2319 wordsList = Str_Words(line, TRUE);
2320 words = wordsList.words; 2320 words = wordsList.words;
2321 argc = wordsList.len; 2321 argc = wordsList.len;
2322 path = wordsList.freeIt; 2322 path = wordsList.freeIt;
2323 if (words == NULL) { 2323 if (words == NULL) {
2324 Error("Unterminated quoted string [%s]", line); 2324 Error("Unterminated quoted string [%s]", line);
2325 return FALSE; 2325 return FALSE;
2326 } 2326 }
2327 shellArgv = path; 2327 shellArgv = path;
2328 2328
2329 for (path = NULL, argv = words; argc != 0; argc--, argv++) { 2329 for (path = NULL, argv = words; argc != 0; argc--, argv++) {
2330 char *arg = *argv; 2330 char *arg = *argv;
2331 if (strncmp(arg, "path=", 5) == 0) { 2331 if (strncmp(arg, "path=", 5) == 0) {
2332 path = arg + 5; 2332 path = arg + 5;
2333 } else if (strncmp(arg, "name=", 5) == 0) { 2333 } else if (strncmp(arg, "name=", 5) == 0) {
2334 newShell.name = arg + 5; 2334 newShell.name = arg + 5;
2335 } else { 2335 } else {
2336 if (strncmp(arg, "quiet=", 6) == 0) { 2336 if (strncmp(arg, "quiet=", 6) == 0) {
2337 newShell.echoOff = arg + 6; 2337 newShell.echoOff = arg + 6;
2338 } else if (strncmp(arg, "echo=", 5) == 0) { 2338 } else if (strncmp(arg, "echo=", 5) == 0) {
2339 newShell.echoOn = arg + 5; 2339 newShell.echoOn = arg + 5;
2340 } else if (strncmp(arg, "filter=", 7) == 0) { 2340 } else if (strncmp(arg, "filter=", 7) == 0) {
2341 newShell.noPrint = arg + 7; 2341 newShell.noPrint = arg + 7;
2342 newShell.noPrintLen = strlen(newShell.noPrint); 2342 newShell.noPrintLen = strlen(newShell.noPrint);
2343 } else if (strncmp(arg, "echoFlag=", 9) == 0) { 2343 } else if (strncmp(arg, "echoFlag=", 9) == 0) {
2344 newShell.echo = arg + 9; 2344 newShell.echo = arg + 9;
2345 } else if (strncmp(arg, "errFlag=", 8) == 0) { 2345 } else if (strncmp(arg, "errFlag=", 8) == 0) {
2346 newShell.exit = arg + 8; 2346 newShell.exit = arg + 8;
2347 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) { 2347 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) {
2348 char c = arg[10]; 2348 char c = arg[10];
2349 newShell.hasErrCtl = c == 'Y' || c == 'y' || 2349 newShell.hasErrCtl = c == 'Y' || c == 'y' ||
2350 c == 'T' || c == 't'; 2350 c == 'T' || c == 't';
2351 } else if (strncmp(arg, "newline=", 8) == 0) { 2351 } else if (strncmp(arg, "newline=", 8) == 0) {
2352 newShell.newline = arg + 8; 2352 newShell.newline = arg + 8;
2353 } else if (strncmp(arg, "check=", 6) == 0) { 2353 } else if (strncmp(arg, "check=", 6) == 0) {
2354 newShell.errOnOrEcho = arg + 6; 2354 newShell.errOnOrEcho = arg + 6;
2355 } else if (strncmp(arg, "ignore=", 7) == 0) { 2355 } else if (strncmp(arg, "ignore=", 7) == 0) {
2356 newShell.errOffOrExecIgnore = arg + 7; 2356 newShell.errOffOrExecIgnore = arg + 7;
2357 } else if (strncmp(arg, "errout=", 7) == 0) { 2357 } else if (strncmp(arg, "errout=", 7) == 0) {
2358 newShell.errExit = arg + 7; 2358 newShell.errExit = arg + 7;
2359 } else if (strncmp(arg, "comment=", 8) == 0) { 2359 } else if (strncmp(arg, "comment=", 8) == 0) {
2360 newShell.commentChar = arg[8]; 2360 newShell.commentChar = arg[8];
2361 } else { 2361 } else {
2362 Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", arg); 2362 Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", arg);
2363 free(words); 2363 free(words);
2364 return FALSE; 2364 return FALSE;
2365 } 2365 }
2366 fullSpec = TRUE; 2366 fullSpec = TRUE;
2367 } 2367 }
2368 } 2368 }
2369 2369
2370 if (path == NULL) { 2370 if (path == NULL) {
2371 /* 2371 /*
2372 * If no path was given, the user wants one of the pre-defined shells, 2372 * If no path was given, the user wants one of the pre-defined shells,
2373 * yes? So we find the one s/he wants with the help of JobMatchShell 2373 * yes? So we find the one s/he wants with the help of JobMatchShell
2374 * and set things up the right way. shellPath will be set up by 2374 * and set things up the right way. shellPath will be set up by
2375 * Shell_Init. 2375 * Shell_Init.
2376 */ 2376 */
2377 if (newShell.name == NULL) { 2377 if (newShell.name == NULL) {
2378 Parse_Error(PARSE_FATAL, "Neither path nor name specified"); 2378 Parse_Error(PARSE_FATAL, "Neither path nor name specified");
2379 free(words); 2379 free(words);
2380 return FALSE; 2380 return FALSE;
2381 } else { 2381 } else {
2382 if ((sh = JobMatchShell(newShell.name)) == NULL) { 2382 if ((sh = JobMatchShell(newShell.name)) == NULL) {
2383 Parse_Error(PARSE_WARNING, "%s: No matching shell", 2383 Parse_Error(PARSE_WARNING, "%s: No matching shell",
2384 newShell.name); 2384 newShell.name);
2385 free(words); 2385 free(words);
2386 return FALSE; 2386 return FALSE;
2387 } 2387 }
2388 commandShell = sh; 2388 commandShell = sh;
2389 shellName = newShell.name; 2389 shellName = newShell.name;
2390 if (shellPath) { 2390 if (shellPath) {
2391 /* Shell_Init has already been called! Do it again. */ 2391 /* Shell_Init has already been called! Do it again. */
2392 free(UNCONST(shellPath)); 2392 free(UNCONST(shellPath));
2393 shellPath = NULL; 2393 shellPath = NULL;
2394 Shell_Init(); 2394 Shell_Init();
2395 } 2395 }
2396 } 2396 }
2397 } else { 2397 } else {
2398 /* 2398 /*
2399 * The user provided a path. If s/he gave nothing else (fullSpec is 2399 * The user provided a path. If s/he gave nothing else (fullSpec is
2400 * FALSE), try and find a matching shell in the ones we know of. 2400 * FALSE), try and find a matching shell in the ones we know of.
2401 * Else we just take the specification at its word and copy it 2401 * Else we just take the specification at its word and copy it
2402 * to a new location. In either case, we need to record the 2402 * to a new location. In either case, we need to record the
2403 * path the user gave for the shell. 2403 * path the user gave for the shell.
2404 */ 2404 */
2405 shellPath = path; 2405 shellPath = path;
2406 path = strrchr(path, '/'); 2406 path = strrchr(path, '/');
2407 if (path == NULL) { 2407 if (path == NULL) {
2408 path = UNCONST(shellPath); 2408 path = UNCONST(shellPath);
2409 } else { 2409 } else {
2410 path++; 2410 path++;
2411 } 2411 }
2412 if (newShell.name != NULL) { 2412 if (newShell.name != NULL) {
2413 shellName = newShell.name; 2413 shellName = newShell.name;
2414 } else { 2414 } else {
2415 shellName = path; 2415 shellName = path;
2416 } 2416 }
2417 if (!fullSpec) { 2417 if (!fullSpec) {
2418 if ((sh = JobMatchShell(shellName)) == NULL) { 2418 if ((sh = JobMatchShell(shellName)) == NULL) {
2419 Parse_Error(PARSE_WARNING, "%s: No matching shell", 2419 Parse_Error(PARSE_WARNING, "%s: No matching shell",
2420 shellName); 2420 shellName);
2421 free(words); 2421 free(words);
2422 return FALSE; 2422 return FALSE;
2423 } 2423 }
2424 commandShell = sh; 2424 commandShell = sh;
2425 } else { 2425 } else {
2426 commandShell = bmake_malloc(sizeof(Shell)); 2426 commandShell = bmake_malloc(sizeof(Shell));
2427 *commandShell = newShell; 2427 *commandShell = newShell;
2428 } 2428 }
2429 /* this will take care of shellErrFlag */ 2429 /* this will take care of shellErrFlag */
2430 Shell_Init(); 2430 Shell_Init();
2431 } 2431 }
2432 2432
2433 if (commandShell->echoOn && commandShell->echoOff) { 2433 if (commandShell->echoOn && commandShell->echoOff) {
2434 commandShell->hasEchoCtl = TRUE; 2434 commandShell->hasEchoCtl = TRUE;
2435 } 2435 }
2436 2436
2437 if (!commandShell->hasErrCtl) { 2437 if (!commandShell->hasErrCtl) {
2438 if (commandShell->errOnOrEcho == NULL) { 2438 if (commandShell->errOnOrEcho == NULL) {
2439 commandShell->errOnOrEcho = ""; 2439 commandShell->errOnOrEcho = "";
2440 } 2440 }
2441 if (commandShell->errOffOrExecIgnore == NULL) { 2441 if (commandShell->errOffOrExecIgnore == NULL) {
2442 commandShell->errOffOrExecIgnore = "%s\n"; 2442 commandShell->errOffOrExecIgnore = "%s\n";
2443 } 2443 }
2444 } 2444 }
2445 2445
2446 /* 2446 /*
2447 * Do not free up the words themselves, since they might be in use by the 2447 * Do not free up the words themselves, since they might be in use by the
2448 * shell specification. 2448 * shell specification.
2449 */ 2449 */
2450 free(words); 2450 free(words);
2451 return TRUE; 2451 return TRUE;
2452} 2452}
2453 2453
2454/* Handle the receipt of an interrupt. 2454/* Handle the receipt of an interrupt.
2455 * 2455 *
2456 * All children are killed. Another job will be started if the .INTERRUPT 2456 * All children are killed. Another job will be started if the .INTERRUPT
2457 * target is defined. 2457 * target is defined.
2458 * 2458 *
2459 * Input: 2459 * Input:
2460 * runINTERRUPT Non-zero if commands for the .INTERRUPT target 2460 * runINTERRUPT Non-zero if commands for the .INTERRUPT target
2461 * should be executed 2461 * should be executed
2462 * signo signal received 2462 * signo signal received
2463 */ 2463 */
2464static void 2464static void
2465JobInterrupt(int runINTERRUPT, int signo) 2465JobInterrupt(int runINTERRUPT, int signo)
2466{ 2466{
2467 Job *job; /* job descriptor in that element */ 2467 Job *job; /* job descriptor in that element */
2468 GNode *interrupt; /* the node describing the .INTERRUPT target */ 2468 GNode *interrupt; /* the node describing the .INTERRUPT target */
2469 sigset_t mask; 2469 sigset_t mask;
2470 GNode *gn; 2470 GNode *gn;
2471 2471
2472 aborting = ABORT_INTERRUPT; 2472 aborting = ABORT_INTERRUPT;
2473 2473
2474 JobSigLock(&mask); 2474 JobSigLock(&mask);
2475 2475
2476 for (job = job_table; job < job_table_end; job++) { 2476 for (job = job_table; job < job_table_end; job++) {
2477 if (job->job_state != JOB_ST_RUNNING) 2477 if (job->job_state != JOB_ST_RUNNING)
2478 continue; 2478 continue;
2479 2479
2480 gn = job->node; 2480 gn = job->node;
2481 2481
2482 JobDeleteTarget(gn); 2482 JobDeleteTarget(gn);
2483 if (job->pid) { 2483 if (job->pid) {
2484 DEBUG2(JOB, "JobInterrupt passing signal %d to child %d.\n", 2484 DEBUG2(JOB, "JobInterrupt passing signal %d to child %d.\n",
2485 signo, job->pid); 2485 signo, job->pid);
2486 KILLPG(job->pid, signo); 2486 KILLPG(job->pid, signo);
2487 } 2487 }
2488 } 2488 }
2489 2489
2490 JobSigUnlock(&mask); 2490 JobSigUnlock(&mask);
2491 2491
2492 if (runINTERRUPT && !opts.touchFlag) { 2492 if (runINTERRUPT && !opts.touchFlag) {
2493 interrupt = Targ_FindNode(".INTERRUPT"); 2493 interrupt = Targ_FindNode(".INTERRUPT");
2494 if (interrupt != NULL) { 2494 if (interrupt != NULL) {
2495 opts.ignoreErrors = FALSE; 2495 opts.ignoreErrors = FALSE;
2496 JobRun(interrupt); 2496 JobRun(interrupt);
2497 } 2497 }
2498 } 2498 }
2499 Trace_Log(MAKEINTR, 0); 2499 Trace_Log(MAKEINTR, 0);
2500 exit(signo); 2500 exit(signo);
2501} 2501}
2502 2502
2503/* Do the final processing, i.e. run the commands attached to the .END target. 2503/* Do the final processing, i.e. run the commands attached to the .END target.
2504 * 2504 *
2505 * Return the number of errors reported. */ 2505 * Return the number of errors reported. */
2506int 2506int
2507Job_Finish(void) 2507Job_Finish(void)
2508{ 2508{
2509 GNode *endNode = Targ_GetEndNode(); 2509 GNode *endNode = Targ_GetEndNode();
2510 if (!Lst_IsEmpty(endNode->commands) || !Lst_IsEmpty(endNode->children)) { 2510 if (!Lst_IsEmpty(endNode->commands) || !Lst_IsEmpty(endNode->children)) {
2511 if (errors) { 2511 if (errors) {
2512 Error("Errors reported so .END ignored"); 2512 Error("Errors reported so .END ignored");
2513 } else { 2513 } else {
2514 JobRun(endNode); 2514 JobRun(endNode);
2515 } 2515 }
2516 } 2516 }
2517 return errors; 2517 return errors;
2518} 2518}
2519 2519
2520/* Clean up any memory used by the jobs module. */ 2520/* Clean up any memory used by the jobs module. */
2521void 2521void
2522Job_End(void) 2522Job_End(void)
2523{ 2523{
2524#ifdef CLEANUP 2524#ifdef CLEANUP
2525 free(shellArgv); 2525 free(shellArgv);
2526#endif 2526#endif
2527} 2527}
2528 2528
2529/* Waits for all running jobs to finish and returns. 2529/* Waits for all running jobs to finish and returns.
2530 * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting. */ 2530 * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting. */
2531void 2531void
2532Job_Wait(void) 2532Job_Wait(void)
2533{ 2533{
2534 aborting = ABORT_WAIT; 2534 aborting = ABORT_WAIT;
2535 while (jobTokensRunning != 0) { 2535 while (jobTokensRunning != 0) {
2536 Job_CatchOutput(); 2536 Job_CatchOutput();
2537 } 2537 }
2538 aborting = ABORT_NONE; 2538 aborting = ABORT_NONE;
2539} 2539}
2540 2540
2541/* Abort all currently running jobs without handling output or anything. 2541/* Abort all currently running jobs without handling output or anything.
2542 * This function is to be called only in the event of a major error. 2542 * This function is to be called only in the event of a major error.
2543 * Most definitely NOT to be called from JobInterrupt. 2543 * Most definitely NOT to be called from JobInterrupt.
2544 * 2544 *
2545 * All children are killed, not just the firstborn. */ 2545 * All children are killed, not just the firstborn. */
2546void 2546void
2547Job_AbortAll(void) 2547Job_AbortAll(void)
2548{ 2548{
2549 Job *job; /* the job descriptor in that element */ 2549 Job *job; /* the job descriptor in that element */
2550 int foo; 2550 int foo;
2551 2551
2552 aborting = ABORT_ERROR; 2552 aborting = ABORT_ERROR;
2553 2553
2554 if (jobTokensRunning) { 2554 if (jobTokensRunning) {
2555 for (job = job_table; job < job_table_end; job++) { 2555 for (job = job_table; job < job_table_end; job++) {
2556 if (job->job_state != JOB_ST_RUNNING) 2556 if (job->job_state != JOB_ST_RUNNING)
2557 continue; 2557 continue;
2558 /* 2558 /*
2559 * kill the child process with increasingly drastic signals to make 2559 * kill the child process with increasingly drastic signals to make
2560 * darn sure it's dead. 2560 * darn sure it's dead.
2561 */ 2561 */
2562 KILLPG(job->pid, SIGINT); 2562 KILLPG(job->pid, SIGINT);
2563 KILLPG(job->pid, SIGKILL); 2563 KILLPG(job->pid, SIGKILL);
2564 } 2564 }
2565 } 2565 }
2566 2566
2567 /* 2567 /*
2568 * Catch as many children as want to report in at first, then give up 2568 * Catch as many children as want to report in at first, then give up
2569 */ 2569 */
2570 while (waitpid((pid_t) -1, &foo, WNOHANG) > 0) 2570 while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
2571 continue; 2571 continue;
2572} 2572}
2573 2573
2574/* Tries to restart stopped jobs if there are slots available. 2574/* Tries to restart stopped jobs if there are slots available.
2575 * Called in process context in response to a SIGCONT. */ 2575 * Called in process context in response to a SIGCONT. */
2576static void 2576static void
2577JobRestartJobs(void) 2577JobRestartJobs(void)
2578{ 2578{
2579 Job *job; 2579 Job *job;
2580 2580
2581 for (job = job_table; job < job_table_end; job++) { 2581 for (job = job_table; job < job_table_end; job++) {
2582 if (job->job_state == JOB_ST_RUNNING && 2582 if (job->job_state == JOB_ST_RUNNING &&
2583 (make_suspended || job->job_suspended)) { 2583 (make_suspended || job->job_suspended)) {
2584 DEBUG1(JOB, "Restarting stopped job pid %d.\n", job->pid); 2584 DEBUG1(JOB, "Restarting stopped job pid %d.\n", job->pid);
2585 if (job->job_suspended) { 2585 if (job->job_suspended) {
2586 (void)printf("*** [%s] Continued\n", job->node->name); 2586 (void)printf("*** [%s] Continued\n", job->node->name);
2587 (void)fflush(stdout); 2587 (void)fflush(stdout);
2588 } 2588 }
2589 job->job_suspended = 0; 2589 job->job_suspended = 0;
2590 if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) { 2590 if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) {
2591 debug_printf("Failed to send SIGCONT to %d\n", job->pid); 2591 debug_printf("Failed to send SIGCONT to %d\n", job->pid);
2592 } 2592 }
2593 } 2593 }
2594 if (job->job_state == JOB_ST_FINISHED) 2594 if (job->job_state == JOB_ST_FINISHED)
2595 /* Job exit deferred after calling waitpid() in a signal handler */ 2595 /* Job exit deferred after calling waitpid() in a signal handler */
2596 JobFinish(job, job->exit_status); 2596 JobFinish(job, job->exit_status);
2597 } 2597 }
2598 make_suspended = 0; 2598 make_suspended = 0;
2599} 2599}
2600 2600
2601static void 2601static void
2602watchfd(Job *job) 2602watchfd(Job *job)

cvs diff -r1.185 -r1.186 src/usr.bin/make/make.c (switch to unified diff)

--- src/usr.bin/make/make.c 2020/10/31 18:41:07 1.185
+++ src/usr.bin/make/make.c 2020/11/01 17:47:26 1.186
@@ -1,1361 +1,1361 @@ @@ -1,1361 +1,1361 @@
1/* $NetBSD: make.c,v 1.185 2020/10/31 18:41:07 rillig Exp $ */ 1/* $NetBSD: make.c,v 1.186 2020/11/01 17:47:26 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1989 by Berkeley Softworks 36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved. 37 * All rights reserved.
38 * 38 *
39 * This code is derived from software contributed to Berkeley by 39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor. 40 * Adam de Boor.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by the University of 52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors. 53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors 54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software 55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission. 56 * without specific prior written permission.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
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/*- 71/*-
72 * make.c -- 72 * make.c --
73 * The functions which perform the examination of targets and 73 * The functions which perform the examination of targets and
74 * their suitability for creation 74 * their suitability for creation
75 * 75 *
76 * Interface: 76 * Interface:
77 * Make_Run Initialize things for the module and recreate 77 * Make_Run Initialize things for the module and recreate
78 * whatever needs recreating. Returns TRUE if 78 * whatever needs recreating. Returns TRUE if
79 * work was (or would have been) done and FALSE 79 * work was (or would have been) done and FALSE
80 * otherwise. 80 * otherwise.
81 * 81 *
82 * Make_Update Update all parents of a given child. Performs 82 * Make_Update Update all parents of a given child. Performs
83 * various bookkeeping chores like the updating 83 * various bookkeeping chores like the updating
84 * of the youngestChild field of the parent, filling 84 * of the youngestChild field of the parent, filling
85 * of the IMPSRC context variable, etc. It will 85 * of the IMPSRC context variable, etc. It will
86 * place the parent on the toBeMade queue if it 86 * place the parent on the toBeMade queue if it
87 * should be. 87 * should be.
88 * 88 *
89 * Make_TimeStamp Function to set the parent's youngestChild field 89 * Make_TimeStamp Function to set the parent's youngestChild field
90 * based on a child's modification time. 90 * based on a child's modification time.
91 * 91 *
92 * Make_DoAllVar Set up the various local variables for a 92 * Make_DoAllVar Set up the various local variables for a
93 * target, including the .ALLSRC variable, making 93 * target, including the .ALLSRC variable, making
94 * sure that any variable that needs to exist 94 * sure that any variable that needs to exist
95 * at the very least has the empty value. 95 * at the very least has the empty value.
96 * 96 *
97 * Make_OODate Determine if a target is out-of-date. 97 * Make_OODate Determine if a target is out-of-date.
98 * 98 *
99 * Make_HandleUse See if a child is a .USE node for a parent 99 * Make_HandleUse See if a child is a .USE node for a parent
100 * and perform the .USE actions if so. 100 * and perform the .USE actions if so.
101 * 101 *
102 * Make_ExpandUse Expand .USE nodes 102 * Make_ExpandUse Expand .USE nodes
103 */ 103 */
104 104
105#include "make.h" 105#include "make.h"
106#include "dir.h" 106#include "dir.h"
107#include "job.h" 107#include "job.h"
108 108
109/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */ 109/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
110MAKE_RCSID("$NetBSD: make.c,v 1.185 2020/10/31 18:41:07 rillig Exp $"); 110MAKE_RCSID("$NetBSD: make.c,v 1.186 2020/11/01 17:47:26 rillig Exp $");
111 111
112/* Sequence # to detect recursion. */ 112/* Sequence # to detect recursion. */
113static unsigned int checked = 1; 113static unsigned int checked = 1;
114 114
115/* The current fringe of the graph. 115/* The current fringe of the graph.
116 * These are nodes which await examination by MakeOODate. 116 * These are nodes which await examination by MakeOODate.
117 * It is added to by Make_Update and subtracted from by MakeStartJobs */ 117 * It is added to by Make_Update and subtracted from by MakeStartJobs */
118static GNodeList *toBeMade; 118static GNodeList *toBeMade;
119 119
120static int MakeCheckOrder(void *, void *); 120static int MakeCheckOrder(void *, void *);
121static int MakeBuildParent(void *, void *); 121static int MakeBuildParent(void *, void *);
122 122
123void 123void
124debug_printf(const char *fmt, ...) 124debug_printf(const char *fmt, ...)
125{ 125{
126 va_list args; 126 va_list args;
127 127
128 va_start(args, fmt); 128 va_start(args, fmt);
129 vfprintf(opts.debug_file, fmt, args); 129 vfprintf(opts.debug_file, fmt, args);
130 va_end(args); 130 va_end(args);
131} 131}
132 132
133MAKE_ATTR_DEAD static void 133MAKE_ATTR_DEAD static void
134make_abort(GNode *gn, int line) 134make_abort(GNode *gn, int line)
135{ 135{
136 debug_printf("make_abort from line %d\n", line); 136 debug_printf("make_abort from line %d\n", line);
137 Targ_PrintNode(gn, 2); 137 Targ_PrintNode(gn, 2);
138 Targ_PrintNodes(toBeMade, 2); 138 Targ_PrintNodes(toBeMade, 2);
139 Targ_PrintGraph(3); 139 Targ_PrintGraph(3);
140 abort(); 140 abort();
141} 141}
142 142
143ENUM_VALUE_RTTI_8(GNodeMade, 143ENUM_VALUE_RTTI_8(GNodeMade,
144 UNMADE, DEFERRED, REQUESTED, BEINGMADE, 144 UNMADE, DEFERRED, REQUESTED, BEINGMADE,
145 MADE, UPTODATE, ERROR, ABORTED); 145 MADE, UPTODATE, ERROR, ABORTED);
146 146
147ENUM_FLAGS_RTTI_31(GNodeType, 147ENUM_FLAGS_RTTI_31(GNodeType,
148 OP_DEPENDS, OP_FORCE, OP_DOUBLEDEP, 148 OP_DEPENDS, OP_FORCE, OP_DOUBLEDEP,
149 /* OP_OPMASK is omitted since it combines other flags */ 149 /* OP_OPMASK is omitted since it combines other flags */
150 OP_OPTIONAL, OP_USE, OP_EXEC, OP_IGNORE, 150 OP_OPTIONAL, OP_USE, OP_EXEC, OP_IGNORE,
151 OP_PRECIOUS, OP_SILENT, OP_MAKE, OP_JOIN, 151 OP_PRECIOUS, OP_SILENT, OP_MAKE, OP_JOIN,
152 OP_MADE, OP_SPECIAL, OP_USEBEFORE, OP_INVISIBLE, 152 OP_MADE, OP_SPECIAL, OP_USEBEFORE, OP_INVISIBLE,
153 OP_NOTMAIN, OP_PHONY, OP_NOPATH, OP_WAIT, 153 OP_NOTMAIN, OP_PHONY, OP_NOPATH, OP_WAIT,
154 OP_NOMETA, OP_META, OP_NOMETA_CMP, OP_SUBMAKE, 154 OP_NOMETA, OP_META, OP_NOMETA_CMP, OP_SUBMAKE,
155 OP_TRANSFORM, OP_MEMBER, OP_LIB, OP_ARCHV, 155 OP_TRANSFORM, OP_MEMBER, OP_LIB, OP_ARCHV,
156 OP_HAS_COMMANDS, OP_SAVE_CMDS, OP_DEPS_FOUND, OP_MARK); 156 OP_HAS_COMMANDS, OP_SAVE_CMDS, OP_DEPS_FOUND, OP_MARK);
157 157
158ENUM_FLAGS_RTTI_10(GNodeFlags, 158ENUM_FLAGS_RTTI_10(GNodeFlags,
159 REMAKE, CHILDMADE, FORCE, DONE_WAIT, 159 REMAKE, CHILDMADE, FORCE, DONE_WAIT,
160 DONE_ORDER, FROM_DEPEND, DONE_ALLSRC, CYCLE, 160 DONE_ORDER, FROM_DEPEND, DONE_ALLSRC, CYCLE,
161 DONECYCLE, INTERNAL); 161 DONECYCLE, INTERNAL);
162 162
163void 163void
164GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn, 164GNode_FprintDetails(FILE *f, const char *prefix, const GNode *gn,
165 const char *suffix) 165 const char *suffix)
166{ 166{
167 char type_buf[GNodeType_ToStringSize]; 167 char type_buf[GNodeType_ToStringSize];
168 char flags_buf[GNodeFlags_ToStringSize]; 168 char flags_buf[GNodeFlags_ToStringSize];
169 169
170 fprintf(f, "%smade %s, type %s, flags %s%s", 170 fprintf(f, "%smade %s, type %s, flags %s%s",
171 prefix, 171 prefix,
172 Enum_ValueToString(gn->made, GNodeMade_ToStringSpecs), 172 Enum_ValueToString(gn->made, GNodeMade_ToStringSpecs),
173 Enum_FlagsToString(type_buf, sizeof type_buf, 173 Enum_FlagsToString(type_buf, sizeof type_buf,
174 gn->type, GNodeType_ToStringSpecs), 174 gn->type, GNodeType_ToStringSpecs),
175 Enum_FlagsToString(flags_buf, sizeof flags_buf, 175 Enum_FlagsToString(flags_buf, sizeof flags_buf,
176 gn->flags, GNodeFlags_ToStringSpecs), 176 gn->flags, GNodeFlags_ToStringSpecs),
177 suffix); 177 suffix);
178} 178}
179 179
180Boolean 180Boolean
181NoExecute(GNode *gn) 181GNode_ShouldExecute(GNode *gn)
182{ 182{
183 return (gn->type & OP_MAKE) ? opts.noRecursiveExecute : opts.noExecute; 183 return !((gn->type & OP_MAKE) ? opts.noRecursiveExecute : opts.noExecute);
184} 184}
185 185
186/* Update the youngest child of the node, according to the given child. */ 186/* Update the youngest child of the node, according to the given child. */
187void 187void
188Make_TimeStamp(GNode *pgn, GNode *cgn) 188Make_TimeStamp(GNode *pgn, GNode *cgn)
189{ 189{
190 if (pgn->youngestChild == NULL || cgn->mtime > pgn->youngestChild->mtime) { 190 if (pgn->youngestChild == NULL || cgn->mtime > pgn->youngestChild->mtime) {
191 pgn->youngestChild = cgn; 191 pgn->youngestChild = cgn;
192 } 192 }
193} 193}
194 194
195/* See if the node is out of date with respect to its sources. 195/* See if the node is out of date with respect to its sources.
196 * 196 *
197 * Used by Make_Run when deciding which nodes to place on the 197 * Used by Make_Run when deciding which nodes to place on the
198 * toBeMade queue initially and by Make_Update to screen out .USE and 198 * toBeMade queue initially and by Make_Update to screen out .USE and
199 * .EXEC nodes. In the latter case, however, any other sort of node 199 * .EXEC nodes. In the latter case, however, any other sort of node
200 * must be considered out-of-date since at least one of its children 200 * must be considered out-of-date since at least one of its children
201 * will have been recreated. 201 * will have been recreated.
202 * 202 *
203 * The mtime field of the node and the youngestChild field of its parents 203 * The mtime field of the node and the youngestChild field of its parents
204 * may be changed. 204 * may be changed.
205 */ 205 */
206Boolean 206Boolean
207Make_OODate(GNode *gn) 207Make_OODate(GNode *gn)
208{ 208{
209 Boolean oodate; 209 Boolean oodate;
210 210
211 /* 211 /*
212 * Certain types of targets needn't even be sought as their datedness 212 * Certain types of targets needn't even be sought as their datedness
213 * doesn't depend on their modification time... 213 * doesn't depend on their modification time...
214 */ 214 */
215 if ((gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC)) == 0) { 215 if ((gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC)) == 0) {
216 (void)Dir_MTime(gn, 1); 216 (void)Dir_MTime(gn, 1);
217 if (DEBUG(MAKE)) { 217 if (DEBUG(MAKE)) {
218 if (gn->mtime != 0) { 218 if (gn->mtime != 0) {
219 debug_printf("modified %s...", Targ_FmtTime(gn->mtime)); 219 debug_printf("modified %s...", Targ_FmtTime(gn->mtime));
220 } else { 220 } else {
221 debug_printf("non-existent..."); 221 debug_printf("non-existent...");
222 } 222 }
223 } 223 }
224 } 224 }
225 225
226 /* 226 /*
227 * A target is remade in one of the following circumstances: 227 * A target is remade in one of the following circumstances:
228 * its modification time is smaller than that of its youngest child and 228 * its modification time is smaller than that of its youngest child and
229 * it would actually be run (has commands or is not GNode_IsTarget) 229 * it would actually be run (has commands or is not GNode_IsTarget)
230 * it's the object of a force operator 230 * it's the object of a force operator
231 * it has no children, was on the lhs of an operator and doesn't exist 231 * it has no children, was on the lhs of an operator and doesn't exist
232 * already. 232 * already.
233 * 233 *
234 * Libraries are only considered out-of-date if the archive module says 234 * Libraries are only considered out-of-date if the archive module says
235 * they are. 235 * they are.
236 * 236 *
237 * These weird rules are brought to you by Backward-Compatibility and 237 * These weird rules are brought to you by Backward-Compatibility and
238 * the strange people who wrote 'Make'. 238 * the strange people who wrote 'Make'.
239 */ 239 */
240 if (gn->type & (OP_USE|OP_USEBEFORE)) { 240 if (gn->type & (OP_USE|OP_USEBEFORE)) {
241 /* 241 /*
242 * If the node is a USE node it is *never* out of date 242 * If the node is a USE node it is *never* out of date
243 * no matter *what*. 243 * no matter *what*.
244 */ 244 */
245 DEBUG0(MAKE, ".USE node..."); 245 DEBUG0(MAKE, ".USE node...");
246 oodate = FALSE; 246 oodate = FALSE;
247 } else if ((gn->type & OP_LIB) && 247 } else if ((gn->type & OP_LIB) &&
248 ((gn->mtime==0) || Arch_IsLib(gn))) { 248 ((gn->mtime==0) || Arch_IsLib(gn))) {
249 DEBUG0(MAKE, "library..."); 249 DEBUG0(MAKE, "library...");
250 250
251 /* 251 /*
252 * always out of date if no children and :: target 252 * always out of date if no children and :: target
253 * or non-existent. 253 * or non-existent.
254 */ 254 */
255 oodate = (gn->mtime == 0 || Arch_LibOODate(gn) || 255 oodate = (gn->mtime == 0 || Arch_LibOODate(gn) ||
256 (gn->youngestChild == NULL && (gn->type & OP_DOUBLEDEP))); 256 (gn->youngestChild == NULL && (gn->type & OP_DOUBLEDEP)));
257 } else if (gn->type & OP_JOIN) { 257 } else if (gn->type & OP_JOIN) {
258 /* 258 /*
259 * A target with the .JOIN attribute is only considered 259 * A target with the .JOIN attribute is only considered
260 * out-of-date if any of its children was out-of-date. 260 * out-of-date if any of its children was out-of-date.
261 */ 261 */
262 DEBUG0(MAKE, ".JOIN node..."); 262 DEBUG0(MAKE, ".JOIN node...");
263 DEBUG1(MAKE, "source %smade...", gn->flags & CHILDMADE ? "" : "not "); 263 DEBUG1(MAKE, "source %smade...", gn->flags & CHILDMADE ? "" : "not ");
264 oodate = (gn->flags & CHILDMADE) ? TRUE : FALSE; 264 oodate = (gn->flags & CHILDMADE) ? TRUE : FALSE;
265 } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) { 265 } else if (gn->type & (OP_FORCE|OP_EXEC|OP_PHONY)) {
266 /* 266 /*
267 * A node which is the object of the force (!) operator or which has 267 * A node which is the object of the force (!) operator or which has
268 * the .EXEC attribute is always considered out-of-date. 268 * the .EXEC attribute is always considered out-of-date.
269 */ 269 */
270 if (DEBUG(MAKE)) { 270 if (DEBUG(MAKE)) {
271 if (gn->type & OP_FORCE) { 271 if (gn->type & OP_FORCE) {
272 debug_printf("! operator..."); 272 debug_printf("! operator...");
273 } else if (gn->type & OP_PHONY) { 273 } else if (gn->type & OP_PHONY) {
274 debug_printf(".PHONY node..."); 274 debug_printf(".PHONY node...");
275 } else { 275 } else {
276 debug_printf(".EXEC node..."); 276 debug_printf(".EXEC node...");
277 } 277 }
278 } 278 }
279 oodate = TRUE; 279 oodate = TRUE;
280 } else if ((gn->youngestChild != NULL && 280 } else if ((gn->youngestChild != NULL &&
281 gn->mtime < gn->youngestChild->mtime) || 281 gn->mtime < gn->youngestChild->mtime) ||
282 (gn->youngestChild == NULL && 282 (gn->youngestChild == NULL &&
283 ((gn->mtime == 0 && !(gn->type & OP_OPTIONAL)) 283 ((gn->mtime == 0 && !(gn->type & OP_OPTIONAL))
284 || gn->type & OP_DOUBLEDEP))) 284 || gn->type & OP_DOUBLEDEP)))
285 { 285 {
286 /* 286 /*
287 * A node whose modification time is less than that of its 287 * A node whose modification time is less than that of its
288 * youngest child or that has no children (youngestChild == NULL) and 288 * youngest child or that has no children (youngestChild == NULL) and
289 * either doesn't exist (mtime == 0) and it isn't optional 289 * either doesn't exist (mtime == 0) and it isn't optional
290 * or was the object of a * :: operator is out-of-date. 290 * or was the object of a * :: operator is out-of-date.
291 * Why? Because that's the way Make does it. 291 * Why? Because that's the way Make does it.
292 */ 292 */
293 if (DEBUG(MAKE)) { 293 if (DEBUG(MAKE)) {
294 if (gn->youngestChild != NULL && 294 if (gn->youngestChild != NULL &&
295 gn->mtime < gn->youngestChild->mtime) { 295 gn->mtime < gn->youngestChild->mtime) {
296 debug_printf("modified before source %s...", 296 debug_printf("modified before source %s...",
297 GNode_Path(gn->youngestChild)); 297 GNode_Path(gn->youngestChild));
298 } else if (gn->mtime == 0) { 298 } else if (gn->mtime == 0) {
299 debug_printf("non-existent and no sources..."); 299 debug_printf("non-existent and no sources...");
300 } else { 300 } else {
301 debug_printf(":: operator and no sources..."); 301 debug_printf(":: operator and no sources...");
302 } 302 }
303 } 303 }
304 oodate = TRUE; 304 oodate = TRUE;
305 } else { 305 } else {
306 /* 306 /*
307 * When a non-existing child with no sources 307 * When a non-existing child with no sources
308 * (such as a typically used FORCE source) has been made and 308 * (such as a typically used FORCE source) has been made and
309 * the target of the child (usually a directory) has the same 309 * the target of the child (usually a directory) has the same
310 * timestamp as the timestamp just given to the non-existing child 310 * timestamp as the timestamp just given to the non-existing child
311 * after it was considered made. 311 * after it was considered made.
312 */ 312 */
313 if (DEBUG(MAKE)) { 313 if (DEBUG(MAKE)) {
314 if (gn->flags & FORCE) 314 if (gn->flags & FORCE)
315 debug_printf("non existing child..."); 315 debug_printf("non existing child...");
316 } 316 }
317 oodate = (gn->flags & FORCE) ? TRUE : FALSE; 317 oodate = (gn->flags & FORCE) ? TRUE : FALSE;
318 } 318 }
319 319
320#ifdef USE_META 320#ifdef USE_META
321 if (useMeta) { 321 if (useMeta) {
322 oodate = meta_oodate(gn, oodate); 322 oodate = meta_oodate(gn, oodate);
323 } 323 }
324#endif 324#endif
325 325
326 /* 326 /*
327 * If the target isn't out-of-date, the parents need to know its 327 * If the target isn't out-of-date, the parents need to know its
328 * modification time. Note that targets that appear to be out-of-date 328 * modification time. Note that targets that appear to be out-of-date
329 * but aren't, because they have no commands and are GNode_IsTarget, 329 * but aren't, because they have no commands and are GNode_IsTarget,
330 * have their mtime stay below their children's mtime to keep parents from 330 * have their mtime stay below their children's mtime to keep parents from
331 * thinking they're out-of-date. 331 * thinking they're out-of-date.
332 */ 332 */
333 if (!oodate) { 333 if (!oodate) {
334 GNodeListNode *ln; 334 GNodeListNode *ln;
335 for (ln = gn->parents->first; ln != NULL; ln = ln->next) 335 for (ln = gn->parents->first; ln != NULL; ln = ln->next)
336 Make_TimeStamp(ln->datum, gn); 336 Make_TimeStamp(ln->datum, gn);
337 } 337 }
338 338
339 return oodate; 339 return oodate;
340} 340}
341 341
342/* Add the node to the list if it needs to be examined. */ 342/* Add the node to the list if it needs to be examined. */
343static int 343static int
344MakeAddChild(void *gnp, void *lp) 344MakeAddChild(void *gnp, void *lp)
345{ 345{
346 GNode *gn = gnp; 346 GNode *gn = gnp;
347 GNodeList *l = lp; 347 GNodeList *l = lp;
348 348
349 if ((gn->flags & REMAKE) == 0 && !(gn->type & (OP_USE|OP_USEBEFORE))) { 349 if ((gn->flags & REMAKE) == 0 && !(gn->type & (OP_USE|OP_USEBEFORE))) {
350 DEBUG2(MAKE, "MakeAddChild: need to examine %s%s\n", 350 DEBUG2(MAKE, "MakeAddChild: need to examine %s%s\n",
351 gn->name, gn->cohort_num); 351 gn->name, gn->cohort_num);
352 Lst_Enqueue(l, gn); 352 Lst_Enqueue(l, gn);
353 } 353 }
354 return 0; 354 return 0;
355} 355}
356 356
357/* Find the pathname of a child that was already made. 357/* Find the pathname of a child that was already made.
358 * 358 *
359 * The path and mtime of the node and the youngestChild of the parent are 359 * The path and mtime of the node and the youngestChild of the parent are
360 * updated; the unmade children count of the parent is decremented. 360 * updated; the unmade children count of the parent is decremented.
361 * 361 *
362 * Input: 362 * Input:
363 * gnp the node to find 363 * gnp the node to find
364 */ 364 */
365static int 365static int
366MakeFindChild(void *gnp, void *pgnp) 366MakeFindChild(void *gnp, void *pgnp)
367{ 367{
368 GNode *gn = gnp; 368 GNode *gn = gnp;
369 GNode *pgn = pgnp; 369 GNode *pgn = pgnp;
370 370
371 (void)Dir_MTime(gn, 0); 371 (void)Dir_MTime(gn, 0);
372 Make_TimeStamp(pgn, gn); 372 Make_TimeStamp(pgn, gn);
373 pgn->unmade--; 373 pgn->unmade--;
374 374
375 return 0; 375 return 0;
376} 376}
377 377
378/* Called by Make_Run and SuffApplyTransform on the downward pass to handle 378/* Called by Make_Run and SuffApplyTransform on the downward pass to handle
379 * .USE and transformation nodes, by copying the child node's commands, type 379 * .USE and transformation nodes, by copying the child node's commands, type
380 * flags and children to the parent node. 380 * flags and children to the parent node.
381 * 381 *
382 * A .USE node is much like an explicit transformation rule, except its 382 * A .USE node is much like an explicit transformation rule, except its
383 * commands are always added to the target node, even if the target already 383 * commands are always added to the target node, even if the target already
384 * has commands. 384 * has commands.
385 * 385 *
386 * Input: 386 * Input:
387 * cgn The source node, which is either a .USE/.USEBEFORE 387 * cgn The source node, which is either a .USE/.USEBEFORE
388 * node or a transformation node (OP_TRANSFORM). 388 * node or a transformation node (OP_TRANSFORM).
389 * pgn The target node 389 * pgn The target node
390 */ 390 */
391void 391void
392Make_HandleUse(GNode *cgn, GNode *pgn) 392Make_HandleUse(GNode *cgn, GNode *pgn)
393{ 393{
394 GNodeListNode *ln; /* An element in the children list */ 394 GNodeListNode *ln; /* An element in the children list */
395 395
396#ifdef DEBUG_SRC 396#ifdef DEBUG_SRC
397 if ((cgn->type & (OP_USE|OP_USEBEFORE|OP_TRANSFORM)) == 0) { 397 if ((cgn->type & (OP_USE|OP_USEBEFORE|OP_TRANSFORM)) == 0) {
398 debug_printf("Make_HandleUse: called for plain node %s\n", cgn->name); 398 debug_printf("Make_HandleUse: called for plain node %s\n", cgn->name);
399 return; 399 return;
400 } 400 }
401#endif 401#endif
402 402
403 if ((cgn->type & (OP_USE|OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) { 403 if ((cgn->type & (OP_USE|OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) {
404 if (cgn->type & OP_USEBEFORE) { 404 if (cgn->type & OP_USEBEFORE) {
405 /* .USEBEFORE */ 405 /* .USEBEFORE */
406 Lst_PrependAll(pgn->commands, cgn->commands); 406 Lst_PrependAll(pgn->commands, cgn->commands);
407 } else { 407 } else {
408 /* .USE, or target has no commands */ 408 /* .USE, or target has no commands */
409 Lst_AppendAll(pgn->commands, cgn->commands); 409 Lst_AppendAll(pgn->commands, cgn->commands);
410 } 410 }
411 } 411 }
412 412
413 for (ln = cgn->children->first; ln != NULL; ln = ln->next) { 413 for (ln = cgn->children->first; ln != NULL; ln = ln->next) {
414 GNode *gn = ln->datum; 414 GNode *gn = ln->datum;
415 415
416 /* 416 /*
417 * Expand variables in the .USE node's name 417 * Expand variables in the .USE node's name
418 * and save the unexpanded form. 418 * and save the unexpanded form.
419 * We don't need to do this for commands. 419 * We don't need to do this for commands.
420 * They get expanded properly when we execute. 420 * They get expanded properly when we execute.
421 */ 421 */
422 if (gn->uname == NULL) { 422 if (gn->uname == NULL) {
423 gn->uname = gn->name; 423 gn->uname = gn->name;
424 } else { 424 } else {
425 free(gn->name); 425 free(gn->name);
426 } 426 }
427 (void)Var_Subst(gn->uname, pgn, VARE_WANTRES, &gn->name); 427 (void)Var_Subst(gn->uname, pgn, VARE_WANTRES, &gn->name);
428 /* TODO: handle errors */ 428 /* TODO: handle errors */
429 if (gn->uname && strcmp(gn->name, gn->uname) != 0) { 429 if (gn->uname && strcmp(gn->name, gn->uname) != 0) {
430 /* See if we have a target for this node. */ 430 /* See if we have a target for this node. */
431 GNode *tgn = Targ_FindNode(gn->name); 431 GNode *tgn = Targ_FindNode(gn->name);
432 if (tgn != NULL) 432 if (tgn != NULL)
433 gn = tgn; 433 gn = tgn;
434 } 434 }
435 435
436 Lst_Append(pgn->children, gn); 436 Lst_Append(pgn->children, gn);
437 Lst_Append(gn->parents, pgn); 437 Lst_Append(gn->parents, pgn);
438 pgn->unmade++; 438 pgn->unmade++;
439 } 439 }
440 440
441 pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_USEBEFORE|OP_TRANSFORM); 441 pgn->type |= cgn->type & ~(OP_OPMASK|OP_USE|OP_USEBEFORE|OP_TRANSFORM);
442} 442}
443 443
444/* Used by Make_Run on the downward pass to handle .USE nodes. Should be 444/* Used by Make_Run on the downward pass to handle .USE nodes. Should be
445 * called before the children are enqueued to be looked at by MakeAddChild. 445 * called before the children are enqueued to be looked at by MakeAddChild.
446 * 446 *
447 * For a .USE child, the commands, type flags and children are copied to the 447 * For a .USE child, the commands, type flags and children are copied to the
448 * parent node, and since the relation to the .USE node is then no longer 448 * parent node, and since the relation to the .USE node is then no longer
449 * needed, that relation is removed. 449 * needed, that relation is removed.
450 * 450 *
451 * Input: 451 * Input:
452 * cgn the child, which may be a .USE node 452 * cgn the child, which may be a .USE node
453 * pgn the current parent 453 * pgn the current parent
454 */ 454 */
455static void 455static void
456MakeHandleUse(GNode *cgn, GNode *pgn, GNodeListNode *ln) 456MakeHandleUse(GNode *cgn, GNode *pgn, GNodeListNode *ln)
457{ 457{
458 Boolean unmarked; 458 Boolean unmarked;
459 459
460 unmarked = ((cgn->type & OP_MARK) == 0); 460 unmarked = ((cgn->type & OP_MARK) == 0);
461 cgn->type |= OP_MARK; 461 cgn->type |= OP_MARK;
462 462
463 if ((cgn->type & (OP_USE|OP_USEBEFORE)) == 0) 463 if ((cgn->type & (OP_USE|OP_USEBEFORE)) == 0)
464 return; 464 return;
465 465
466 if (unmarked) 466 if (unmarked)
467 Make_HandleUse(cgn, pgn); 467 Make_HandleUse(cgn, pgn);
468 468
469 /* 469 /*
470 * This child node is now "made", so we decrement the count of 470 * This child node is now "made", so we decrement the count of
471 * unmade children in the parent... We also remove the child 471 * unmade children in the parent... We also remove the child
472 * from the parent's list to accurately reflect the number of decent 472 * from the parent's list to accurately reflect the number of decent
473 * children the parent has. This is used by Make_Run to decide 473 * children the parent has. This is used by Make_Run to decide
474 * whether to queue the parent or examine its children... 474 * whether to queue the parent or examine its children...
475 */ 475 */
476 Lst_Remove(pgn->children, ln); 476 Lst_Remove(pgn->children, ln);
477 pgn->unmade--; 477 pgn->unmade--;
478} 478}
479 479
480static void 480static void
481HandleUseNodes(GNode *gn) 481HandleUseNodes(GNode *gn)
482{ 482{
483 GNodeListNode *ln, *nln; 483 GNodeListNode *ln, *nln;
484 for (ln = gn->children->first; ln != NULL; ln = nln) { 484 for (ln = gn->children->first; ln != NULL; ln = nln) {
485 nln = ln->next; 485 nln = ln->next;
486 MakeHandleUse(ln->datum, gn, ln); 486 MakeHandleUse(ln->datum, gn, ln);
487 } 487 }
488} 488}
489 489
490 490
491/* Check the modification time of a gnode, and update it if necessary. 491/* Check the modification time of a gnode, and update it if necessary.
492 * Return 0 if the gnode does not exist, or its filesystem time if it does. */ 492 * Return 0 if the gnode does not exist, or its filesystem time if it does. */
493time_t 493time_t
494Make_Recheck(GNode *gn) 494Make_Recheck(GNode *gn)
495{ 495{
496 time_t mtime = Dir_MTime(gn, 1); 496 time_t mtime = Dir_MTime(gn, 1);
497 497
498#ifndef RECHECK 498#ifndef RECHECK
499 /* 499 /*
500 * We can't re-stat the thing, but we can at least take care of rules 500 * We can't re-stat the thing, but we can at least take care of rules
501 * where a target depends on a source that actually creates the 501 * where a target depends on a source that actually creates the
502 * target, but only if it has changed, e.g. 502 * target, but only if it has changed, e.g.
503 * 503 *
504 * parse.h : parse.o 504 * parse.h : parse.o
505 * 505 *
506 * parse.o : parse.y 506 * parse.o : parse.y
507 * yacc -d parse.y 507 * yacc -d parse.y
508 * cc -c y.tab.c 508 * cc -c y.tab.c
509 * mv y.tab.o parse.o 509 * mv y.tab.o parse.o
510 * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 510 * cmp -s y.tab.h parse.h || mv y.tab.h parse.h
511 * 511 *
512 * In this case, if the definitions produced by yacc haven't changed 512 * In this case, if the definitions produced by yacc haven't changed
513 * from before, parse.h won't have been updated and gn->mtime will 513 * from before, parse.h won't have been updated and gn->mtime will
514 * reflect the current modification time for parse.h. This is 514 * reflect the current modification time for parse.h. This is
515 * something of a kludge, I admit, but it's a useful one.. 515 * something of a kludge, I admit, but it's a useful one..
516 * XXX: People like to use a rule like 516 * XXX: People like to use a rule like
517 * 517 *
518 * FRC: 518 * FRC:
519 * 519 *
520 * To force things that depend on FRC to be made, so we have to 520 * To force things that depend on FRC to be made, so we have to
521 * check for gn->children being empty as well... 521 * check for gn->children being empty as well...
522 */ 522 */
523 if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) { 523 if (!Lst_IsEmpty(gn->commands) || Lst_IsEmpty(gn->children)) {
524 gn->mtime = now; 524 gn->mtime = now;
525 } 525 }
526#else 526#else
527 /* 527 /*
528 * This is what Make does and it's actually a good thing, as it 528 * This is what Make does and it's actually a good thing, as it
529 * allows rules like 529 * allows rules like
530 * 530 *
531 * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 531 * cmp -s y.tab.h parse.h || cp y.tab.h parse.h
532 * 532 *
533 * to function as intended. Unfortunately, thanks to the stateless 533 * to function as intended. Unfortunately, thanks to the stateless
534 * nature of NFS (by which I mean the loose coupling of two clients 534 * nature of NFS (by which I mean the loose coupling of two clients
535 * using the same file from a common server), there are times 535 * using the same file from a common server), there are times
536 * when the modification time of a file created on a remote 536 * when the modification time of a file created on a remote
537 * machine will not be modified before the local stat() implied by 537 * machine will not be modified before the local stat() implied by
538 * the Dir_MTime occurs, thus leading us to believe that the file 538 * the Dir_MTime occurs, thus leading us to believe that the file
539 * is unchanged, wreaking havoc with files that depend on this one. 539 * is unchanged, wreaking havoc with files that depend on this one.
540 * 540 *
541 * I have decided it is better to make too much than to make too 541 * I have decided it is better to make too much than to make too
542 * little, so this stuff is commented out unless you're sure it's ok. 542 * little, so this stuff is commented out unless you're sure it's ok.
543 * -- ardeb 1/12/88 543 * -- ardeb 1/12/88
544 */ 544 */
545 /* 545 /*
546 * Christos, 4/9/92: If we are saving commands pretend that 546 * Christos, 4/9/92: If we are saving commands pretend that
547 * the target is made now. Otherwise archives with ... rules 547 * the target is made now. Otherwise archives with ... rules
548 * don't work! 548 * don't work!
549 */ 549 */
550 if (NoExecute(gn) || (gn->type & OP_SAVE_CMDS) || 550 if (!GNode_ShouldExecute(gn) || (gn->type & OP_SAVE_CMDS) ||
551 (mtime == 0 && !(gn->type & OP_WAIT))) { 551 (mtime == 0 && !(gn->type & OP_WAIT))) {
552 DEBUG2(MAKE, " recheck(%s): update time from %s to now\n", 552 DEBUG2(MAKE, " recheck(%s): update time from %s to now\n",
553 gn->name, Targ_FmtTime(gn->mtime)); 553 gn->name, Targ_FmtTime(gn->mtime));
554 gn->mtime = now; 554 gn->mtime = now;
555 } 555 }
556 else { 556 else {
557 DEBUG2(MAKE, " recheck(%s): current update time: %s\n", 557 DEBUG2(MAKE, " recheck(%s): current update time: %s\n",
558 gn->name, Targ_FmtTime(gn->mtime)); 558 gn->name, Targ_FmtTime(gn->mtime));
559 } 559 }
560#endif 560#endif
561 return mtime; 561 return mtime;
562} 562}
563 563
564/* 564/*
565 * Set the .PREFIX and .IMPSRC variables for all the implied parents 565 * Set the .PREFIX and .IMPSRC variables for all the implied parents
566 * of this node. 566 * of this node.
567 */ 567 */
568static void 568static void
569UpdateImplicitParentsVars(GNode *cgn, const char *cname) 569UpdateImplicitParentsVars(GNode *cgn, const char *cname)
570{ 570{
571 GNodeListNode *ln; 571 GNodeListNode *ln;
572 const char *cpref = GNode_VarPrefix(cgn); 572 const char *cpref = GNode_VarPrefix(cgn);
573 573
574 for (ln = cgn->implicitParents->first; ln != NULL; ln = ln->next) { 574 for (ln = cgn->implicitParents->first; ln != NULL; ln = ln->next) {
575 GNode *pgn = ln->datum; 575 GNode *pgn = ln->datum;
576 if (pgn->flags & REMAKE) { 576 if (pgn->flags & REMAKE) {
577 Var_Set(IMPSRC, cname, pgn); 577 Var_Set(IMPSRC, cname, pgn);
578 if (cpref != NULL) 578 if (cpref != NULL)
579 Var_Set(PREFIX, cpref, pgn); 579 Var_Set(PREFIX, cpref, pgn);
580 } 580 }
581 } 581 }
582} 582}
583 583
584/* Perform update on the parents of a node. Used by JobFinish once 584/* Perform update on the parents of a node. Used by JobFinish once
585 * a node has been dealt with and by MakeStartJobs if it finds an 585 * a node has been dealt with and by MakeStartJobs if it finds an
586 * up-to-date node. 586 * up-to-date node.
587 * 587 *
588 * The unmade field of pgn is decremented and pgn may be placed on 588 * The unmade field of pgn is decremented and pgn may be placed on
589 * the toBeMade queue if this field becomes 0. 589 * the toBeMade queue if this field becomes 0.
590 * 590 *
591 * If the child was made, the parent's flag CHILDMADE field will be 591 * If the child was made, the parent's flag CHILDMADE field will be
592 * set true. 592 * set true.
593 * 593 *
594 * If the child is not up-to-date and still does not exist, 594 * If the child is not up-to-date and still does not exist,
595 * set the FORCE flag on the parents. 595 * set the FORCE flag on the parents.
596 * 596 *
597 * If the child wasn't made, the youngestChild field of the parent will be 597 * If the child wasn't made, the youngestChild field of the parent will be
598 * altered if the child's mtime is big enough. 598 * altered if the child's mtime is big enough.
599 * 599 *
600 * Finally, if the child is the implied source for the parent, the 600 * Finally, if the child is the implied source for the parent, the
601 * parent's IMPSRC variable is set appropriately. 601 * parent's IMPSRC variable is set appropriately.
602 */ 602 */
603void 603void
604Make_Update(GNode *cgn) 604Make_Update(GNode *cgn)
605{ 605{
606 const char *cname; /* the child's name */ 606 const char *cname; /* the child's name */
607 time_t mtime = -1; 607 time_t mtime = -1;
608 GNodeList *parents; 608 GNodeList *parents;
609 GNodeListNode *ln; 609 GNodeListNode *ln;
610 GNode *centurion; 610 GNode *centurion;
611 611
612 /* It is save to re-examine any nodes again */ 612 /* It is save to re-examine any nodes again */
613 checked++; 613 checked++;
614 614
615 cname = GNode_VarTarget(cgn); 615 cname = GNode_VarTarget(cgn);
616 616
617 DEBUG2(MAKE, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num); 617 DEBUG2(MAKE, "Make_Update: %s%s\n", cgn->name, cgn->cohort_num);
618 618
619 /* 619 /*
620 * If the child was actually made, see what its modification time is 620 * If the child was actually made, see what its modification time is
621 * now -- some rules won't actually update the file. If the file still 621 * now -- some rules won't actually update the file. If the file still
622 * doesn't exist, make its mtime now. 622 * doesn't exist, make its mtime now.
623 */ 623 */
624 if (cgn->made != UPTODATE) { 624 if (cgn->made != UPTODATE) {
625 mtime = Make_Recheck(cgn); 625 mtime = Make_Recheck(cgn);
626 } 626 }
627 627
628 /* 628 /*
629 * If this is a `::' node, we must consult its first instance 629 * If this is a `::' node, we must consult its first instance
630 * which is where all parents are linked. 630 * which is where all parents are linked.
631 */ 631 */
632 if ((centurion = cgn->centurion) != NULL) { 632 if ((centurion = cgn->centurion) != NULL) {
633 if (!Lst_IsEmpty(cgn->parents)) 633 if (!Lst_IsEmpty(cgn->parents))
634 Punt("%s%s: cohort has parents", cgn->name, cgn->cohort_num); 634 Punt("%s%s: cohort has parents", cgn->name, cgn->cohort_num);
635 centurion->unmade_cohorts--; 635 centurion->unmade_cohorts--;
636 if (centurion->unmade_cohorts < 0) 636 if (centurion->unmade_cohorts < 0)
637 Error("Graph cycles through centurion %s", centurion->name); 637 Error("Graph cycles through centurion %s", centurion->name);
638 } else { 638 } else {
639 centurion = cgn; 639 centurion = cgn;
640 } 640 }
641 parents = centurion->parents; 641 parents = centurion->parents;
642 642
643 /* If this was a .ORDER node, schedule the RHS */ 643 /* If this was a .ORDER node, schedule the RHS */
644 Lst_ForEachUntil(centurion->order_succ, MakeBuildParent, toBeMade->first); 644 Lst_ForEachUntil(centurion->order_succ, MakeBuildParent, toBeMade->first);
645 645
646 /* Now mark all the parents as having one less unmade child */ 646 /* Now mark all the parents as having one less unmade child */
647 for (ln = parents->first; ln != NULL; ln = ln->next) { 647 for (ln = parents->first; ln != NULL; ln = ln->next) {
648 GNode *pgn = ln->datum; 648 GNode *pgn = ln->datum;
649 649
650 if (DEBUG(MAKE)) 650 if (DEBUG(MAKE))
651 debug_printf("inspect parent %s%s: flags %x, " 651 debug_printf("inspect parent %s%s: flags %x, "
652 "type %x, made %d, unmade %d ", 652 "type %x, made %d, unmade %d ",
653 pgn->name, pgn->cohort_num, pgn->flags, 653 pgn->name, pgn->cohort_num, pgn->flags,
654 pgn->type, pgn->made, pgn->unmade - 1); 654 pgn->type, pgn->made, pgn->unmade - 1);
655 655
656 if (!(pgn->flags & REMAKE)) { 656 if (!(pgn->flags & REMAKE)) {
657 /* This parent isn't needed */ 657 /* This parent isn't needed */
658 DEBUG0(MAKE, "- not needed\n"); 658 DEBUG0(MAKE, "- not needed\n");
659 continue; 659 continue;
660 } 660 }
661 if (mtime == 0 && !(cgn->type & OP_WAIT)) 661 if (mtime == 0 && !(cgn->type & OP_WAIT))
662 pgn->flags |= FORCE; 662 pgn->flags |= FORCE;
663 663
664 /* 664 /*
665 * If the parent has the .MADE attribute, its timestamp got 665 * If the parent has the .MADE attribute, its timestamp got
666 * updated to that of its newest child, and its unmade 666 * updated to that of its newest child, and its unmade
667 * child count got set to zero in Make_ExpandUse(). 667 * child count got set to zero in Make_ExpandUse().
668 * However other things might cause us to build one of its 668 * However other things might cause us to build one of its
669 * children - and so we mustn't do any processing here when 669 * children - and so we mustn't do any processing here when
670 * the child build finishes. 670 * the child build finishes.
671 */ 671 */
672 if (pgn->type & OP_MADE) { 672 if (pgn->type & OP_MADE) {
673 DEBUG0(MAKE, "- .MADE\n"); 673 DEBUG0(MAKE, "- .MADE\n");
674 continue; 674 continue;
675 } 675 }
676 676
677 if ( ! (cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE))) { 677 if ( ! (cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE))) {
678 if (cgn->made == MADE) 678 if (cgn->made == MADE)
679 pgn->flags |= CHILDMADE; 679 pgn->flags |= CHILDMADE;
680 (void)Make_TimeStamp(pgn, cgn); 680 (void)Make_TimeStamp(pgn, cgn);
681 } 681 }
682 682
683 /* 683 /*
684 * A parent must wait for the completion of all instances 684 * A parent must wait for the completion of all instances
685 * of a `::' dependency. 685 * of a `::' dependency.
686 */ 686 */
687 if (centurion->unmade_cohorts != 0 || centurion->made < MADE) { 687 if (centurion->unmade_cohorts != 0 || centurion->made < MADE) {
688 DEBUG2(MAKE, "- centurion made %d, %d unmade cohorts\n", 688 DEBUG2(MAKE, "- centurion made %d, %d unmade cohorts\n",
689 centurion->made, centurion->unmade_cohorts); 689 centurion->made, centurion->unmade_cohorts);
690 continue; 690 continue;
691 } 691 }
692 692
693 /* One more child of this parent is now made */ 693 /* One more child of this parent is now made */
694 pgn->unmade--; 694 pgn->unmade--;
695 if (pgn->unmade < 0) { 695 if (pgn->unmade < 0) {
696 if (DEBUG(MAKE)) { 696 if (DEBUG(MAKE)) {
697 debug_printf("Graph cycles through %s%s\n", 697 debug_printf("Graph cycles through %s%s\n",
698 pgn->name, pgn->cohort_num); 698 pgn->name, pgn->cohort_num);
699 Targ_PrintGraph(2); 699 Targ_PrintGraph(2);
700 } 700 }
701 Error("Graph cycles through %s%s", pgn->name, pgn->cohort_num); 701 Error("Graph cycles through %s%s", pgn->name, pgn->cohort_num);
702 } 702 }
703 703
704 /* We must always rescan the parents of .WAIT and .ORDER nodes. */ 704 /* We must always rescan the parents of .WAIT and .ORDER nodes. */
705 if (pgn->unmade != 0 && !(centurion->type & OP_WAIT) 705 if (pgn->unmade != 0 && !(centurion->type & OP_WAIT)
706 && !(centurion->flags & DONE_ORDER)) { 706 && !(centurion->flags & DONE_ORDER)) {
707 DEBUG0(MAKE, "- unmade children\n"); 707 DEBUG0(MAKE, "- unmade children\n");
708 continue; 708 continue;
709 } 709 }
710 if (pgn->made != DEFERRED) { 710 if (pgn->made != DEFERRED) {
711 /* 711 /*
712 * Either this parent is on a different branch of the tree, 712 * Either this parent is on a different branch of the tree,
713 * or it on the RHS of a .WAIT directive 713 * or it on the RHS of a .WAIT directive
714 * or it is already on the toBeMade list. 714 * or it is already on the toBeMade list.
715 */ 715 */
716 DEBUG0(MAKE, "- not deferred\n"); 716 DEBUG0(MAKE, "- not deferred\n");
717 continue; 717 continue;
718 } 718 }
719 assert(pgn->order_pred != NULL); 719 assert(pgn->order_pred != NULL);
720 if (Lst_ForEachUntil(pgn->order_pred, MakeCheckOrder, 0)) { 720 if (Lst_ForEachUntil(pgn->order_pred, MakeCheckOrder, 0)) {
721 /* A .ORDER rule stops us building this */ 721 /* A .ORDER rule stops us building this */
722 continue; 722 continue;
723 } 723 }
724 if (DEBUG(MAKE)) { 724 if (DEBUG(MAKE)) {
725 debug_printf("- %s%s made, schedule %s%s (made %d)\n", 725 debug_printf("- %s%s made, schedule %s%s (made %d)\n",
726 cgn->name, cgn->cohort_num, 726 cgn->name, cgn->cohort_num,
727 pgn->name, pgn->cohort_num, pgn->made); 727 pgn->name, pgn->cohort_num, pgn->made);
728 Targ_PrintNode(pgn, 2); 728 Targ_PrintNode(pgn, 2);
729 } 729 }
730 /* Ok, we can schedule the parent again */ 730 /* Ok, we can schedule the parent again */
731 pgn->made = REQUESTED; 731 pgn->made = REQUESTED;
732 Lst_Enqueue(toBeMade, pgn); 732 Lst_Enqueue(toBeMade, pgn);
733 } 733 }
734 734
735 UpdateImplicitParentsVars(cgn, cname); 735 UpdateImplicitParentsVars(cgn, cname);
736} 736}
737 737
738static void 738static void
739UnmarkChildren(GNode *gn) 739UnmarkChildren(GNode *gn)
740{ 740{
741 GNodeListNode *ln; 741 GNodeListNode *ln;
742 742
743 for (ln = gn->children->first; ln != NULL; ln = ln->next) { 743 for (ln = gn->children->first; ln != NULL; ln = ln->next) {
744 GNode *child = ln->datum; 744 GNode *child = ln->datum;
745 child->type &= ~OP_MARK; 745 child->type &= ~OP_MARK;
746 } 746 }
747} 747}
748 748
749/* Add a child's name to the ALLSRC and OODATE variables of the given 749/* Add a child's name to the ALLSRC and OODATE variables of the given
750 * node, but only if it has not been given the .EXEC, .USE or .INVISIBLE 750 * node, but only if it has not been given the .EXEC, .USE or .INVISIBLE
751 * attributes. .EXEC and .USE children are very rarely going to be files, 751 * attributes. .EXEC and .USE children are very rarely going to be files,
752 * so... 752 * so...
753 * 753 *
754 * If the child is a .JOIN node, its ALLSRC is propagated to the parent. 754 * If the child is a .JOIN node, its ALLSRC is propagated to the parent.
755 * 755 *
756 * A child is added to the OODATE variable if its modification time is 756 * A child is added to the OODATE variable if its modification time is
757 * later than that of its parent, as defined by Make, except if the 757 * later than that of its parent, as defined by Make, except if the
758 * parent is a .JOIN node. In that case, it is only added to the OODATE 758 * parent is a .JOIN node. In that case, it is only added to the OODATE
759 * variable if it was actually made (since .JOIN nodes don't have 759 * variable if it was actually made (since .JOIN nodes don't have
760 * modification times, the comparison is rather unfair...).. 760 * modification times, the comparison is rather unfair...)..
761 * 761 *
762 * Input: 762 * Input:
763 * cgn The child to add 763 * cgn The child to add
764 * pgn The parent to whose ALLSRC variable it should 764 * pgn The parent to whose ALLSRC variable it should
765 * be added 765 * be added
766 */ 766 */
767static void 767static void
768MakeAddAllSrc(GNode *cgn, GNode *pgn) 768MakeAddAllSrc(GNode *cgn, GNode *pgn)
769{ 769{
770 if (cgn->type & OP_MARK) 770 if (cgn->type & OP_MARK)
771 return; 771 return;
772 cgn->type |= OP_MARK; 772 cgn->type |= OP_MARK;
773 773
774 if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) { 774 if ((cgn->type & (OP_EXEC|OP_USE|OP_USEBEFORE|OP_INVISIBLE)) == 0) {
775 const char *child, *allsrc; 775 const char *child, *allsrc;
776 776
777 if (cgn->type & OP_ARCHV) 777 if (cgn->type & OP_ARCHV)
778 child = GNode_VarMember(cgn); 778 child = GNode_VarMember(cgn);
779 else 779 else
780 child = GNode_Path(cgn); 780 child = GNode_Path(cgn);
781 if (cgn->type & OP_JOIN) { 781 if (cgn->type & OP_JOIN) {
782 allsrc = GNode_VarAllsrc(cgn); 782 allsrc = GNode_VarAllsrc(cgn);
783 } else { 783 } else {
784 allsrc = child; 784 allsrc = child;
785 } 785 }
786 if (allsrc != NULL) 786 if (allsrc != NULL)
787 Var_Append(ALLSRC, allsrc, pgn); 787 Var_Append(ALLSRC, allsrc, pgn);
788 if (pgn->type & OP_JOIN) { 788 if (pgn->type & OP_JOIN) {
789 if (cgn->made == MADE) { 789 if (cgn->made == MADE) {
790 Var_Append(OODATE, child, pgn); 790 Var_Append(OODATE, child, pgn);
791 } 791 }
792 } else if ((pgn->mtime < cgn->mtime) || 792 } else if ((pgn->mtime < cgn->mtime) ||
793 (cgn->mtime >= now && cgn->made == MADE)) 793 (cgn->mtime >= now && cgn->made == MADE))
794 { 794 {
795 /* 795 /*
796 * It goes in the OODATE variable if the parent is younger than the 796 * It goes in the OODATE variable if the parent is younger than the
797 * child or if the child has been modified more recently than 797 * child or if the child has been modified more recently than
798 * the start of the make. This is to keep pmake from getting 798 * the start of the make. This is to keep pmake from getting
799 * confused if something else updates the parent after the 799 * confused if something else updates the parent after the
800 * make starts (shouldn't happen, I know, but sometimes it 800 * make starts (shouldn't happen, I know, but sometimes it
801 * does). In such a case, if we've updated the kid, the parent 801 * does). In such a case, if we've updated the kid, the parent
802 * is likely to have a modification time later than that of 802 * is likely to have a modification time later than that of
803 * the kid and anything that relies on the OODATE variable will 803 * the kid and anything that relies on the OODATE variable will
804 * be hosed. 804 * be hosed.
805 * 805 *
806 * XXX: This will cause all made children to go in the OODATE 806 * XXX: This will cause all made children to go in the OODATE
807 * variable, even if they're not touched, if RECHECK isn't defined, 807 * variable, even if they're not touched, if RECHECK isn't defined,
808 * since cgn->mtime is set to now in Make_Update. According to 808 * since cgn->mtime is set to now in Make_Update. According to
809 * some people, this is good... 809 * some people, this is good...
810 */ 810 */
811 Var_Append(OODATE, child, pgn); 811 Var_Append(OODATE, child, pgn);
812 } 812 }
813 } 813 }
814} 814}
815 815
816/* Set up the ALLSRC and OODATE variables. Sad to say, it must be 816/* Set up the ALLSRC and OODATE variables. Sad to say, it must be
817 * done separately, rather than while traversing the graph. This is 817 * done separately, rather than while traversing the graph. This is
818 * because Make defined OODATE to contain all sources whose modification 818 * because Make defined OODATE to contain all sources whose modification
819 * times were later than that of the target, *not* those sources that 819 * times were later than that of the target, *not* those sources that
820 * were out-of-date. Since in both compatibility and native modes, 820 * were out-of-date. Since in both compatibility and native modes,
821 * the modification time of the parent isn't found until the child 821 * the modification time of the parent isn't found until the child
822 * has been dealt with, we have to wait until now to fill in the 822 * has been dealt with, we have to wait until now to fill in the
823 * variable. As for ALLSRC, the ordering is important and not 823 * variable. As for ALLSRC, the ordering is important and not
824 * guaranteed when in native mode, so it must be set here, too. 824 * guaranteed when in native mode, so it must be set here, too.
825 * 825 *
826 * If the node is a .JOIN node, its TARGET variable will be set to 826 * If the node is a .JOIN node, its TARGET variable will be set to
827 * match its ALLSRC variable. 827 * match its ALLSRC variable.
828 */ 828 */
829void 829void
830Make_DoAllVar(GNode *gn) 830Make_DoAllVar(GNode *gn)
831{ 831{
832 GNodeListNode *ln; 832 GNodeListNode *ln;
833 833
834 if (gn->flags & DONE_ALLSRC) 834 if (gn->flags & DONE_ALLSRC)
835 return; 835 return;
836 836
837 UnmarkChildren(gn); 837 UnmarkChildren(gn);
838 for (ln = gn->children->first; ln != NULL; ln = ln->next) 838 for (ln = gn->children->first; ln != NULL; ln = ln->next)
839 MakeAddAllSrc(ln->datum, gn); 839 MakeAddAllSrc(ln->datum, gn);
840 840
841 if (!Var_Exists(OODATE, gn)) { 841 if (!Var_Exists(OODATE, gn)) {
842 Var_Set(OODATE, "", gn); 842 Var_Set(OODATE, "", gn);
843 } 843 }
844 if (!Var_Exists(ALLSRC, gn)) { 844 if (!Var_Exists(ALLSRC, gn)) {
845 Var_Set(ALLSRC, "", gn); 845 Var_Set(ALLSRC, "", gn);
846 } 846 }
847 847
848 if (gn->type & OP_JOIN) 848 if (gn->type & OP_JOIN)
849 Var_Set(TARGET, GNode_VarAllsrc(gn), gn); 849 Var_Set(TARGET, GNode_VarAllsrc(gn), gn);
850 gn->flags |= DONE_ALLSRC; 850 gn->flags |= DONE_ALLSRC;
851} 851}
852 852
853static int 853static int
854MakeCheckOrder(void *v_bn, void *ignore MAKE_ATTR_UNUSED) 854MakeCheckOrder(void *v_bn, void *ignore MAKE_ATTR_UNUSED)
855{ 855{
856 GNode *bn = v_bn; 856 GNode *bn = v_bn;
857 857
858 if (bn->made >= MADE || !(bn->flags & REMAKE)) 858 if (bn->made >= MADE || !(bn->flags & REMAKE))
859 return 0; 859 return 0;
860 860
861 DEBUG2(MAKE, "MakeCheckOrder: Waiting for .ORDER node %s%s\n", 861 DEBUG2(MAKE, "MakeCheckOrder: Waiting for .ORDER node %s%s\n",
862 bn->name, bn->cohort_num); 862 bn->name, bn->cohort_num);
863 return 1; 863 return 1;
864} 864}
865 865
866static int 866static int
867MakeBuildChild(void *v_cn, void *toBeMade_next) 867MakeBuildChild(void *v_cn, void *toBeMade_next)
868{ 868{
869 GNode *cn = v_cn; 869 GNode *cn = v_cn;
870 870
871 DEBUG4(MAKE, "MakeBuildChild: inspect %s%s, made %d, type %x\n", 871 DEBUG4(MAKE, "MakeBuildChild: inspect %s%s, made %d, type %x\n",
872 cn->name, cn->cohort_num, cn->made, cn->type); 872 cn->name, cn->cohort_num, cn->made, cn->type);
873 if (cn->made > DEFERRED) 873 if (cn->made > DEFERRED)
874 return 0; 874 return 0;
875 875
876 /* If this node is on the RHS of a .ORDER, check LHSs. */ 876 /* If this node is on the RHS of a .ORDER, check LHSs. */
877 assert(cn->order_pred); 877 assert(cn->order_pred);
878 if (Lst_ForEachUntil(cn->order_pred, MakeCheckOrder, 0)) { 878 if (Lst_ForEachUntil(cn->order_pred, MakeCheckOrder, 0)) {
879 /* Can't build this (or anything else in this child list) yet */ 879 /* Can't build this (or anything else in this child list) yet */
880 cn->made = DEFERRED; 880 cn->made = DEFERRED;
881 return 0; /* but keep looking */ 881 return 0; /* but keep looking */
882 } 882 }
883 883
884 DEBUG2(MAKE, "MakeBuildChild: schedule %s%s\n", cn->name, cn->cohort_num); 884 DEBUG2(MAKE, "MakeBuildChild: schedule %s%s\n", cn->name, cn->cohort_num);
885 885
886 cn->made = REQUESTED; 886 cn->made = REQUESTED;
887 if (toBeMade_next == NULL) 887 if (toBeMade_next == NULL)
888 Lst_Append(toBeMade, cn); 888 Lst_Append(toBeMade, cn);
889 else 889 else
890 Lst_InsertBefore(toBeMade, toBeMade_next, cn); 890 Lst_InsertBefore(toBeMade, toBeMade_next, cn);
891 891
892 if (cn->unmade_cohorts != 0) 892 if (cn->unmade_cohorts != 0)
893 Lst_ForEachUntil(cn->cohorts, MakeBuildChild, toBeMade_next); 893 Lst_ForEachUntil(cn->cohorts, MakeBuildChild, toBeMade_next);
894 894
895 /* 895 /*
896 * If this node is a .WAIT node with unmade children 896 * If this node is a .WAIT node with unmade children
897 * then don't add the next sibling. 897 * then don't add the next sibling.
898 */ 898 */
899 return cn->type & OP_WAIT && cn->unmade > 0; 899 return cn->type & OP_WAIT && cn->unmade > 0;
900} 900}
901 901
902/* When a .ORDER LHS node completes we do this on each RHS */ 902/* When a .ORDER LHS node completes we do this on each RHS */
903static int 903static int
904MakeBuildParent(void *v_pn, void *toBeMade_next) 904MakeBuildParent(void *v_pn, void *toBeMade_next)
905{ 905{
906 GNode *pn = v_pn; 906 GNode *pn = v_pn;
907 907
908 if (pn->made != DEFERRED) 908 if (pn->made != DEFERRED)
909 return 0; 909 return 0;
910 910
911 if (MakeBuildChild(pn, toBeMade_next) == 0) { 911 if (MakeBuildChild(pn, toBeMade_next) == 0) {
912 /* Mark so that when this node is built we reschedule its parents */ 912 /* Mark so that when this node is built we reschedule its parents */
913 pn->flags |= DONE_ORDER; 913 pn->flags |= DONE_ORDER;
914 } 914 }
915 915
916 return 0; 916 return 0;
917} 917}
918 918
919/* Start as many jobs as possible, taking them from the toBeMade queue. 919/* Start as many jobs as possible, taking them from the toBeMade queue.
920 * 920 *
921 * If the query flag was given to pmake, no job will be started, 921 * If the query flag was given to pmake, no job will be started,
922 * but as soon as an out-of-date target is found, this function 922 * but as soon as an out-of-date target is found, this function
923 * returns TRUE. At all other times, this function returns FALSE. 923 * returns TRUE. At all other times, this function returns FALSE.
924 */ 924 */
925static Boolean 925static Boolean
926MakeStartJobs(void) 926MakeStartJobs(void)
927{ 927{
928 GNode *gn; 928 GNode *gn;
929 int have_token = 0; 929 int have_token = 0;
930 930
931 while (!Lst_IsEmpty(toBeMade)) { 931 while (!Lst_IsEmpty(toBeMade)) {
932 /* Get token now to avoid cycling job-list when we only have 1 token */ 932 /* Get token now to avoid cycling job-list when we only have 1 token */
933 if (!have_token && !Job_TokenWithdraw()) 933 if (!have_token && !Job_TokenWithdraw())
934 break; 934 break;
935 have_token = 1; 935 have_token = 1;
936 936
937 gn = Lst_Dequeue(toBeMade); 937 gn = Lst_Dequeue(toBeMade);
938 DEBUG2(MAKE, "Examining %s%s...\n", gn->name, gn->cohort_num); 938 DEBUG2(MAKE, "Examining %s%s...\n", gn->name, gn->cohort_num);
939 939
940 if (gn->made != REQUESTED) { 940 if (gn->made != REQUESTED) {
941 DEBUG1(MAKE, "state %d\n", gn->made); 941 DEBUG1(MAKE, "state %d\n", gn->made);
942 942
943 make_abort(gn, __LINE__); 943 make_abort(gn, __LINE__);
944 } 944 }
945 945
946 if (gn->checked_seqno == checked) { 946 if (gn->checked_seqno == checked) {
947 /* We've already looked at this node since a job finished... */ 947 /* We've already looked at this node since a job finished... */
948 DEBUG2(MAKE, "already checked %s%s\n", gn->name, gn->cohort_num); 948 DEBUG2(MAKE, "already checked %s%s\n", gn->name, gn->cohort_num);
949 gn->made = DEFERRED; 949 gn->made = DEFERRED;
950 continue; 950 continue;
951 } 951 }
952 gn->checked_seqno = checked; 952 gn->checked_seqno = checked;
953 953
954 if (gn->unmade != 0) { 954 if (gn->unmade != 0) {
955 /* 955 /*
956 * We can't build this yet, add all unmade children to toBeMade, 956 * We can't build this yet, add all unmade children to toBeMade,
957 * just before the current first element. 957 * just before the current first element.
958 */ 958 */
959 gn->made = DEFERRED; 959 gn->made = DEFERRED;
960 Lst_ForEachUntil(gn->children, MakeBuildChild, toBeMade->first); 960 Lst_ForEachUntil(gn->children, MakeBuildChild, toBeMade->first);
961 /* and drop this node on the floor */ 961 /* and drop this node on the floor */
962 DEBUG2(MAKE, "dropped %s%s\n", gn->name, gn->cohort_num); 962 DEBUG2(MAKE, "dropped %s%s\n", gn->name, gn->cohort_num);
963 continue; 963 continue;
964 } 964 }
965 965
966 gn->made = BEINGMADE; 966 gn->made = BEINGMADE;
967 if (Make_OODate(gn)) { 967 if (Make_OODate(gn)) {
968 DEBUG0(MAKE, "out-of-date\n"); 968 DEBUG0(MAKE, "out-of-date\n");
969 if (opts.queryFlag) { 969 if (opts.queryFlag) {
970 return TRUE; 970 return TRUE;
971 } 971 }
972 Make_DoAllVar(gn); 972 Make_DoAllVar(gn);
973 Job_Make(gn); 973 Job_Make(gn);
974 have_token = 0; 974 have_token = 0;
975 } else { 975 } else {
976 DEBUG0(MAKE, "up-to-date\n"); 976 DEBUG0(MAKE, "up-to-date\n");
977 gn->made = UPTODATE; 977 gn->made = UPTODATE;
978 if (gn->type & OP_JOIN) { 978 if (gn->type & OP_JOIN) {
979 /* 979 /*
980 * Even for an up-to-date .JOIN node, we need it to have its 980 * Even for an up-to-date .JOIN node, we need it to have its
981 * context variables so references to it get the correct 981 * context variables so references to it get the correct
982 * value for .TARGET when building up the context variables 982 * value for .TARGET when building up the context variables
983 * of its parent(s)... 983 * of its parent(s)...
984 */ 984 */
985 Make_DoAllVar(gn); 985 Make_DoAllVar(gn);
986 } 986 }
987 Make_Update(gn); 987 Make_Update(gn);
988 } 988 }
989 } 989 }
990 990
991 if (have_token) 991 if (have_token)
992 Job_TokenReturn(); 992 Job_TokenReturn();
993 993
994 return FALSE; 994 return FALSE;
995} 995}
996 996
997static void 997static void
998MakePrintStatusOrderNode(GNode *ogn, GNode *gn) 998MakePrintStatusOrderNode(GNode *ogn, GNode *gn)
999{ 999{
1000 if (!(ogn->flags & REMAKE) || ogn->made > REQUESTED) 1000 if (!(ogn->flags & REMAKE) || ogn->made > REQUESTED)
1001 /* not waiting for this one */ 1001 /* not waiting for this one */
1002 return; 1002 return;
1003 1003
1004 printf(" `%s%s' has .ORDER dependency against %s%s ", 1004 printf(" `%s%s' has .ORDER dependency against %s%s ",
1005 gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); 1005 gn->name, gn->cohort_num, ogn->name, ogn->cohort_num);
1006 GNode_FprintDetails(stdout, "(", ogn, ")\n"); 1006 GNode_FprintDetails(stdout, "(", ogn, ")\n");
1007 1007
1008 if (DEBUG(MAKE) && opts.debug_file != stdout) { 1008 if (DEBUG(MAKE) && opts.debug_file != stdout) {
1009 debug_printf(" `%s%s' has .ORDER dependency against %s%s ", 1009 debug_printf(" `%s%s' has .ORDER dependency against %s%s ",
1010 gn->name, gn->cohort_num, ogn->name, ogn->cohort_num); 1010 gn->name, gn->cohort_num, ogn->name, ogn->cohort_num);
1011 GNode_FprintDetails(opts.debug_file, "(", ogn, ")\n"); 1011 GNode_FprintDetails(opts.debug_file, "(", ogn, ")\n");
1012 } 1012 }
1013} 1013}
1014 1014
1015static void 1015static void
1016MakePrintStatusOrder(GNode *gn) 1016MakePrintStatusOrder(GNode *gn)
1017{ 1017{
1018 GNodeListNode *ln; 1018 GNodeListNode *ln;
1019 for (ln = gn->order_pred->first; ln != NULL; ln = ln->next) 1019 for (ln = gn->order_pred->first; ln != NULL; ln = ln->next)
1020 MakePrintStatusOrderNode(ln->datum, gn); 1020 MakePrintStatusOrderNode(ln->datum, gn);
1021} 1021}
1022 1022
1023static void MakePrintStatusList(GNodeList *, int *); 1023static void MakePrintStatusList(GNodeList *, int *);
1024 1024
1025/* Print the status of a top-level node, viz. it being up-to-date already 1025/* Print the status of a top-level node, viz. it being up-to-date already
1026 * or not created due to an error in a lower level. 1026 * or not created due to an error in a lower level.
1027 * Callback function for Make_Run via Lst_ForEachUntil. 1027 * Callback function for Make_Run via Lst_ForEachUntil.
1028 */ 1028 */
1029static Boolean 1029static Boolean
1030MakePrintStatus(GNode *gn, int *errors) 1030MakePrintStatus(GNode *gn, int *errors)
1031{ 1031{
1032 if (gn->flags & DONECYCLE) 1032 if (gn->flags & DONECYCLE)
1033 /* We've completely processed this node before, don't do it again. */ 1033 /* We've completely processed this node before, don't do it again. */
1034 return FALSE; 1034 return FALSE;
1035 1035
1036 if (gn->unmade == 0) { 1036 if (gn->unmade == 0) {
1037 gn->flags |= DONECYCLE; 1037 gn->flags |= DONECYCLE;
1038 switch (gn->made) { 1038 switch (gn->made) {
1039 case UPTODATE: 1039 case UPTODATE:
1040 printf("`%s%s' is up to date.\n", gn->name, gn->cohort_num); 1040 printf("`%s%s' is up to date.\n", gn->name, gn->cohort_num);
1041 break; 1041 break;
1042 case MADE: 1042 case MADE:
1043 break; 1043 break;
1044 case UNMADE: 1044 case UNMADE:
1045 case DEFERRED: 1045 case DEFERRED:
1046 case REQUESTED: 1046 case REQUESTED:
1047 case BEINGMADE: 1047 case BEINGMADE:
1048 (*errors)++; 1048 (*errors)++;
1049 printf("`%s%s' was not built", gn->name, gn->cohort_num); 1049 printf("`%s%s' was not built", gn->name, gn->cohort_num);
1050 GNode_FprintDetails(stdout, " (", gn, ")!\n"); 1050 GNode_FprintDetails(stdout, " (", gn, ")!\n");
1051 if (DEBUG(MAKE) && opts.debug_file != stdout) { 1051 if (DEBUG(MAKE) && opts.debug_file != stdout) {
1052 debug_printf("`%s%s' was not built", gn->name, gn->cohort_num); 1052 debug_printf("`%s%s' was not built", gn->name, gn->cohort_num);
1053 GNode_FprintDetails(opts.debug_file, " (", gn, ")!\n"); 1053 GNode_FprintDetails(opts.debug_file, " (", gn, ")!\n");
1054 } 1054 }
1055 /* Most likely problem is actually caused by .ORDER */ 1055 /* Most likely problem is actually caused by .ORDER */
1056 MakePrintStatusOrder(gn); 1056 MakePrintStatusOrder(gn);
1057 break; 1057 break;
1058 default: 1058 default:
1059 /* Errors - already counted */ 1059 /* Errors - already counted */
1060 printf("`%s%s' not remade because of errors.\n", 1060 printf("`%s%s' not remade because of errors.\n",
1061 gn->name, gn->cohort_num); 1061 gn->name, gn->cohort_num);
1062 if (DEBUG(MAKE) && opts.debug_file != stdout) 1062 if (DEBUG(MAKE) && opts.debug_file != stdout)
1063 debug_printf("`%s%s' not remade because of errors.\n", 1063 debug_printf("`%s%s' not remade because of errors.\n",
1064 gn->name, gn->cohort_num); 1064 gn->name, gn->cohort_num);
1065 break; 1065 break;
1066 } 1066 }
1067 return FALSE; 1067 return FALSE;
1068 } 1068 }
1069 1069
1070 DEBUG3(MAKE, "MakePrintStatus: %s%s has %d unmade children\n", 1070 DEBUG3(MAKE, "MakePrintStatus: %s%s has %d unmade children\n",
1071 gn->name, gn->cohort_num, gn->unmade); 1071 gn->name, gn->cohort_num, gn->unmade);
1072 /* 1072 /*
1073 * If printing cycles and came to one that has unmade children, 1073 * If printing cycles and came to one that has unmade children,
1074 * print out the cycle by recursing on its children. 1074 * print out the cycle by recursing on its children.
1075 */ 1075 */
1076 if (!(gn->flags & CYCLE)) { 1076 if (!(gn->flags & CYCLE)) {
1077 /* Fist time we've seen this node, check all children */ 1077 /* Fist time we've seen this node, check all children */
1078 gn->flags |= CYCLE; 1078 gn->flags |= CYCLE;
1079 MakePrintStatusList(gn->children, errors); 1079 MakePrintStatusList(gn->children, errors);
1080 /* Mark that this node needn't be processed again */ 1080 /* Mark that this node needn't be processed again */
1081 gn->flags |= DONECYCLE; 1081 gn->flags |= DONECYCLE;
1082 return FALSE; 1082 return FALSE;
1083 } 1083 }
1084 1084
1085 /* Only output the error once per node */ 1085 /* Only output the error once per node */
1086 gn->flags |= DONECYCLE; 1086 gn->flags |= DONECYCLE;
1087 Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num); 1087 Error("Graph cycles through `%s%s'", gn->name, gn->cohort_num);
1088 if ((*errors)++ > 100) 1088 if ((*errors)++ > 100)
1089 /* Abandon the whole error report */ 1089 /* Abandon the whole error report */
1090 return TRUE; 1090 return TRUE;
1091 1091
1092 /* Reporting for our children will give the rest of the loop */ 1092 /* Reporting for our children will give the rest of the loop */
1093 MakePrintStatusList(gn->children, errors); 1093 MakePrintStatusList(gn->children, errors);
1094 return FALSE; 1094 return FALSE;
1095} 1095}
1096 1096
1097static void 1097static void
1098MakePrintStatusList(GNodeList *gnodes, int *errors) 1098MakePrintStatusList(GNodeList *gnodes, int *errors)
1099{ 1099{
1100 GNodeListNode *ln; 1100 GNodeListNode *ln;
1101 for (ln = gnodes->first; ln != NULL; ln = ln->next) 1101 for (ln = gnodes->first; ln != NULL; ln = ln->next)
1102 if (MakePrintStatus(ln->datum, errors)) 1102 if (MakePrintStatus(ln->datum, errors))
1103 break; 1103 break;
1104} 1104}
1105 1105
1106/* Expand .USE nodes and create a new targets list. 1106/* Expand .USE nodes and create a new targets list.
1107 * 1107 *
1108 * Input: 1108 * Input:
1109 * targs the initial list of targets 1109 * targs the initial list of targets
1110 */ 1110 */
1111void 1111void
1112Make_ExpandUse(GNodeList *targs) 1112Make_ExpandUse(GNodeList *targs)
1113{ 1113{
1114 GNodeList *examine; /* List of targets to examine */ 1114 GNodeList *examine; /* List of targets to examine */
1115 1115
1116 { 1116 {
1117 /* XXX: Why is it necessary to copy the list? There shouldn't be 1117 /* XXX: Why is it necessary to copy the list? There shouldn't be
1118 * any modifications to the list, at least the function name 1118 * any modifications to the list, at least the function name
1119 * ExpandUse doesn't suggest that. */ 1119 * ExpandUse doesn't suggest that. */
1120 GNodeListNode *ln; 1120 GNodeListNode *ln;
1121 examine = Lst_New(); 1121 examine = Lst_New();
1122 for (ln = targs->first; ln != NULL; ln = ln->next) 1122 for (ln = targs->first; ln != NULL; ln = ln->next)
1123 Lst_Append(examine, ln->datum); 1123 Lst_Append(examine, ln->datum);
1124 } 1124 }
1125 1125
1126 /* 1126 /*
1127 * Make an initial downward pass over the graph, marking nodes to be made 1127 * Make an initial downward pass over the graph, marking nodes to be made
1128 * as we go down. We call Suff_FindDeps to find where a node is and 1128 * as we go down. We call Suff_FindDeps to find where a node is and
1129 * to get some children for it if it has none and also has no commands. 1129 * to get some children for it if it has none and also has no commands.
1130 * If the node is a leaf, we stick it on the toBeMade queue to 1130 * If the node is a leaf, we stick it on the toBeMade queue to
1131 * be looked at in a minute, otherwise we add its children to our queue 1131 * be looked at in a minute, otherwise we add its children to our queue
1132 * and go on about our business. 1132 * and go on about our business.
1133 */ 1133 */
1134 while (!Lst_IsEmpty(examine)) { 1134 while (!Lst_IsEmpty(examine)) {
1135 GNode *gn = Lst_Dequeue(examine); 1135 GNode *gn = Lst_Dequeue(examine);
1136 1136
1137 if (gn->flags & REMAKE) 1137 if (gn->flags & REMAKE)
1138 /* We've looked at this one already */ 1138 /* We've looked at this one already */
1139 continue; 1139 continue;
1140 gn->flags |= REMAKE; 1140 gn->flags |= REMAKE;
1141 DEBUG2(MAKE, "Make_ExpandUse: examine %s%s\n", 1141 DEBUG2(MAKE, "Make_ExpandUse: examine %s%s\n",
1142 gn->name, gn->cohort_num); 1142 gn->name, gn->cohort_num);
1143 1143
1144 if (gn->type & OP_DOUBLEDEP) 1144 if (gn->type & OP_DOUBLEDEP)
1145 Lst_PrependAll(examine, gn->cohorts); 1145 Lst_PrependAll(examine, gn->cohorts);
1146 1146
1147 /* 1147 /*
1148 * Apply any .USE rules before looking for implicit dependencies 1148 * Apply any .USE rules before looking for implicit dependencies
1149 * to make sure everything has commands that should... 1149 * to make sure everything has commands that should...
1150 * Make sure that the TARGET is set, so that we can make 1150 * Make sure that the TARGET is set, so that we can make
1151 * expansions. 1151 * expansions.
1152 */ 1152 */
1153 if (gn->type & OP_ARCHV) { 1153 if (gn->type & OP_ARCHV) {
1154 char *eoa, *eon; 1154 char *eoa, *eon;
1155 eoa = strchr(gn->name, '('); 1155 eoa = strchr(gn->name, '(');
1156 eon = strchr(gn->name, ')'); 1156 eon = strchr(gn->name, ')');
1157 if (eoa == NULL || eon == NULL) 1157 if (eoa == NULL || eon == NULL)
1158 continue; 1158 continue;
1159 *eoa = '\0'; 1159 *eoa = '\0';
1160 *eon = '\0'; 1160 *eon = '\0';
1161 Var_Set(MEMBER, eoa + 1, gn); 1161 Var_Set(MEMBER, eoa + 1, gn);
1162 Var_Set(ARCHIVE, gn->name, gn); 1162 Var_Set(ARCHIVE, gn->name, gn);
1163 *eoa = '('; 1163 *eoa = '(';
1164 *eon = ')'; 1164 *eon = ')';
1165 } 1165 }
1166 1166
1167 (void)Dir_MTime(gn, 0); 1167 (void)Dir_MTime(gn, 0);
1168 Var_Set(TARGET, GNode_Path(gn), gn); 1168 Var_Set(TARGET, GNode_Path(gn), gn);
1169 UnmarkChildren(gn); 1169 UnmarkChildren(gn);
1170 HandleUseNodes(gn); 1170 HandleUseNodes(gn);
1171 1171
1172 if ((gn->type & OP_MADE) == 0) 1172 if ((gn->type & OP_MADE) == 0)
1173 Suff_FindDeps(gn); 1173 Suff_FindDeps(gn);
1174 else { 1174 else {
1175 /* Pretend we made all this node's children */ 1175 /* Pretend we made all this node's children */
1176 Lst_ForEachUntil(gn->children, MakeFindChild, gn); 1176 Lst_ForEachUntil(gn->children, MakeFindChild, gn);
1177 if (gn->unmade != 0) 1177 if (gn->unmade != 0)
1178 printf("Warning: %s%s still has %d unmade children\n", 1178 printf("Warning: %s%s still has %d unmade children\n",
1179 gn->name, gn->cohort_num, gn->unmade); 1179 gn->name, gn->cohort_num, gn->unmade);
1180 } 1180 }
1181 1181
1182 if (gn->unmade != 0) 1182 if (gn->unmade != 0)
1183 Lst_ForEachUntil(gn->children, MakeAddChild, examine); 1183 Lst_ForEachUntil(gn->children, MakeAddChild, examine);
1184 } 1184 }
1185 1185
1186 Lst_Free(examine); 1186 Lst_Free(examine);
1187} 1187}
1188 1188
1189/* Make the .WAIT node depend on the previous children */ 1189/* Make the .WAIT node depend on the previous children */
1190static void 1190static void
1191add_wait_dependency(GNodeListNode *owln, GNode *wn) 1191add_wait_dependency(GNodeListNode *owln, GNode *wn)
1192{ 1192{
1193 GNodeListNode *cln; 1193 GNodeListNode *cln;
1194 GNode *cn; 1194 GNode *cn;
1195 1195
1196 for (cln = owln; (cn = cln->datum) != wn; cln = cln->next) { 1196 for (cln = owln; (cn = cln->datum) != wn; cln = cln->next) {
1197 DEBUG3(MAKE, ".WAIT: add dependency %s%s -> %s\n", 1197 DEBUG3(MAKE, ".WAIT: add dependency %s%s -> %s\n",
1198 cn->name, cn->cohort_num, wn->name); 1198 cn->name, cn->cohort_num, wn->name);
1199 1199
1200 /* XXX: This pattern should be factored out, it repeats often */ 1200 /* XXX: This pattern should be factored out, it repeats often */
1201 Lst_Append(wn->children, cn); 1201 Lst_Append(wn->children, cn);
1202 wn->unmade++; 1202 wn->unmade++;
1203 Lst_Append(cn->parents, wn); 1203 Lst_Append(cn->parents, wn);
1204 } 1204 }
1205} 1205}
1206 1206
1207/* Convert .WAIT nodes into dependencies. */ 1207/* Convert .WAIT nodes into dependencies. */
1208static void 1208static void
1209Make_ProcessWait(GNodeList *targs) 1209Make_ProcessWait(GNodeList *targs)
1210{ 1210{
1211 GNode *pgn; /* 'parent' node we are examining */ 1211 GNode *pgn; /* 'parent' node we are examining */
1212 GNodeListNode *owln; /* Previous .WAIT node */ 1212 GNodeListNode *owln; /* Previous .WAIT node */
1213 GNodeList *examine; /* List of targets to examine */ 1213 GNodeList *examine; /* List of targets to examine */
1214 1214
1215 /* 1215 /*
1216 * We need all the nodes to have a common parent in order for the 1216 * We need all the nodes to have a common parent in order for the
1217 * .WAIT and .ORDER scheduling to work. 1217 * .WAIT and .ORDER scheduling to work.
1218 * Perhaps this should be done earlier... 1218 * Perhaps this should be done earlier...
1219 */ 1219 */
1220 1220
1221 pgn = Targ_NewGN(".MAIN"); 1221 pgn = Targ_NewGN(".MAIN");
1222 pgn->flags = REMAKE; 1222 pgn->flags = REMAKE;
1223 pgn->type = OP_PHONY | OP_DEPENDS; 1223 pgn->type = OP_PHONY | OP_DEPENDS;
1224 /* Get it displayed in the diag dumps */ 1224 /* Get it displayed in the diag dumps */
1225 Lst_Prepend(Targ_List(), pgn); 1225 Lst_Prepend(Targ_List(), pgn);
1226 1226
1227 { 1227 {
1228 GNodeListNode *ln; 1228 GNodeListNode *ln;
1229 for (ln = targs->first; ln != NULL; ln = ln->next) { 1229 for (ln = targs->first; ln != NULL; ln = ln->next) {
1230 GNode *cgn = ln->datum; 1230 GNode *cgn = ln->datum;
1231 1231
1232 Lst_Append(pgn->children, cgn); 1232 Lst_Append(pgn->children, cgn);
1233 Lst_Append(cgn->parents, pgn); 1233 Lst_Append(cgn->parents, pgn);
1234 pgn->unmade++; 1234 pgn->unmade++;
1235 } 1235 }
1236 } 1236 }
1237 1237
1238 /* Start building with the 'dummy' .MAIN' node */ 1238 /* Start building with the 'dummy' .MAIN' node */
1239 MakeBuildChild(pgn, NULL); 1239 MakeBuildChild(pgn, NULL);
1240 1240
1241 examine = Lst_New(); 1241 examine = Lst_New();
1242 Lst_Append(examine, pgn); 1242 Lst_Append(examine, pgn);
1243 1243
1244 while (!Lst_IsEmpty(examine)) { 1244 while (!Lst_IsEmpty(examine)) {
1245 GNodeListNode *ln; 1245 GNodeListNode *ln;
1246 1246
1247 pgn = Lst_Dequeue(examine); 1247 pgn = Lst_Dequeue(examine);
1248 1248
1249 /* We only want to process each child-list once */ 1249 /* We only want to process each child-list once */
1250 if (pgn->flags & DONE_WAIT) 1250 if (pgn->flags & DONE_WAIT)
1251 continue; 1251 continue;
1252 pgn->flags |= DONE_WAIT; 1252 pgn->flags |= DONE_WAIT;
1253 DEBUG1(MAKE, "Make_ProcessWait: examine %s\n", pgn->name); 1253 DEBUG1(MAKE, "Make_ProcessWait: examine %s\n", pgn->name);
1254 1254
1255 if (pgn->type & OP_DOUBLEDEP) 1255 if (pgn->type & OP_DOUBLEDEP)
1256 Lst_PrependAll(examine, pgn->cohorts); 1256 Lst_PrependAll(examine, pgn->cohorts);
1257 1257
1258 owln = pgn->children->first; 1258 owln = pgn->children->first;
1259 for (ln = pgn->children->first; ln != NULL; ln = ln->next) { 1259 for (ln = pgn->children->first; ln != NULL; ln = ln->next) {
1260 GNode *cgn = ln->datum; 1260 GNode *cgn = ln->datum;
1261 if (cgn->type & OP_WAIT) { 1261 if (cgn->type & OP_WAIT) {
1262 add_wait_dependency(owln, cgn); 1262 add_wait_dependency(owln, cgn);
1263 owln = ln; 1263 owln = ln;
1264 } else { 1264 } else {
1265 Lst_Append(examine, cgn); 1265 Lst_Append(examine, cgn);
1266 } 1266 }
1267 } 1267 }
1268 } 1268 }
1269 1269
1270 Lst_Free(examine); 1270 Lst_Free(examine);
1271} 1271}
1272 1272
1273/*- 1273/*-
1274 *----------------------------------------------------------------------- 1274 *-----------------------------------------------------------------------
1275 * Make_Run -- 1275 * Make_Run --
1276 * Initialize the nodes to remake and the list of nodes which are 1276 * Initialize the nodes to remake and the list of nodes which are
1277 * ready to be made by doing a breadth-first traversal of the graph 1277 * ready to be made by doing a breadth-first traversal of the graph
1278 * starting from the nodes in the given list. Once this traversal 1278 * starting from the nodes in the given list. Once this traversal
1279 * is finished, all the 'leaves' of the graph are in the toBeMade 1279 * is finished, all the 'leaves' of the graph are in the toBeMade
1280 * queue. 1280 * queue.
1281 * Using this queue and the Job module, work back up the graph, 1281 * Using this queue and the Job module, work back up the graph,
1282 * calling on MakeStartJobs to keep the job table as full as 1282 * calling on MakeStartJobs to keep the job table as full as
1283 * possible. 1283 * possible.
1284 * 1284 *
1285 * Input: 1285 * Input:
1286 * targs the initial list of targets 1286 * targs the initial list of targets
1287 * 1287 *
1288 * Results: 1288 * Results:
1289 * TRUE if work was done. FALSE otherwise. 1289 * TRUE if work was done. FALSE otherwise.
1290 * 1290 *
1291 * Side Effects: 1291 * Side Effects:
1292 * The make field of all nodes involved in the creation of the given 1292 * The make field of all nodes involved in the creation of the given
1293 * targets is set to 1. The toBeMade list is set to contain all the 1293 * targets is set to 1. The toBeMade list is set to contain all the
1294 * 'leaves' of these subgraphs. 1294 * 'leaves' of these subgraphs.
1295 *----------------------------------------------------------------------- 1295 *-----------------------------------------------------------------------
1296 */ 1296 */
1297Boolean 1297Boolean
1298Make_Run(GNodeList *targs) 1298Make_Run(GNodeList *targs)
1299{ 1299{
1300 int errors; /* Number of errors the Job module reports */ 1300 int errors; /* Number of errors the Job module reports */
1301 1301
1302 /* Start trying to make the current targets... */ 1302 /* Start trying to make the current targets... */
1303 toBeMade = Lst_New(); 1303 toBeMade = Lst_New();
1304 1304
1305 Make_ExpandUse(targs); 1305 Make_ExpandUse(targs);
1306 Make_ProcessWait(targs); 1306 Make_ProcessWait(targs);
1307 1307
1308 if (DEBUG(MAKE)) { 1308 if (DEBUG(MAKE)) {
1309 debug_printf("#***# full graph\n"); 1309 debug_printf("#***# full graph\n");
1310 Targ_PrintGraph(1); 1310 Targ_PrintGraph(1);
1311 } 1311 }
1312 1312
1313 if (opts.queryFlag) { 1313 if (opts.queryFlag) {
1314 /* 1314 /*
1315 * We wouldn't do any work unless we could start some jobs in the 1315 * We wouldn't do any work unless we could start some jobs in the
1316 * next loop... (we won't actually start any, of course, this is just 1316 * next loop... (we won't actually start any, of course, this is just
1317 * to see if any of the targets was out of date) 1317 * to see if any of the targets was out of date)
1318 */ 1318 */
1319 return MakeStartJobs(); 1319 return MakeStartJobs();
1320 } 1320 }
1321 /* 1321 /*
1322 * Initialization. At the moment, no jobs are running and until some 1322 * Initialization. At the moment, no jobs are running and until some
1323 * get started, nothing will happen since the remaining upward 1323 * get started, nothing will happen since the remaining upward
1324 * traversal of the graph is performed by the routines in job.c upon 1324 * traversal of the graph is performed by the routines in job.c upon
1325 * the finishing of a job. So we fill the Job table as much as we can 1325 * the finishing of a job. So we fill the Job table as much as we can
1326 * before going into our loop. 1326 * before going into our loop.
1327 */ 1327 */
1328 (void)MakeStartJobs(); 1328 (void)MakeStartJobs();
1329 1329
1330 /* 1330 /*
1331 * Main Loop: The idea here is that the ending of jobs will take 1331 * Main Loop: The idea here is that the ending of jobs will take
1332 * care of the maintenance of data structures and the waiting for output 1332 * care of the maintenance of data structures and the waiting for output
1333 * will cause us to be idle most of the time while our children run as 1333 * will cause us to be idle most of the time while our children run as
1334 * much as possible. Because the job table is kept as full as possible, 1334 * much as possible. Because the job table is kept as full as possible,
1335 * the only time when it will be empty is when all the jobs which need 1335 * the only time when it will be empty is when all the jobs which need
1336 * running have been run, so that is the end condition of this loop. 1336 * running have been run, so that is the end condition of this loop.
1337 * Note that the Job module will exit if there were any errors unless the 1337 * Note that the Job module will exit if there were any errors unless the
1338 * keepgoing flag was given. 1338 * keepgoing flag was given.
1339 */ 1339 */
1340 while (!Lst_IsEmpty(toBeMade) || jobTokensRunning > 0) { 1340 while (!Lst_IsEmpty(toBeMade) || jobTokensRunning > 0) {
1341 Job_CatchOutput(); 1341 Job_CatchOutput();
1342 (void)MakeStartJobs(); 1342 (void)MakeStartJobs();
1343 } 1343 }
1344 1344
1345 errors = Job_Finish(); 1345 errors = Job_Finish();
1346 1346
1347 /* 1347 /*
1348 * Print the final status of each target. E.g. if it wasn't made 1348 * Print the final status of each target. E.g. if it wasn't made
1349 * because some inferior reported an error. 1349 * because some inferior reported an error.
1350 */ 1350 */
1351 DEBUG1(MAKE, "done: errors %d\n", errors); 1351 DEBUG1(MAKE, "done: errors %d\n", errors);
1352 if (errors == 0) { 1352 if (errors == 0) {
1353 MakePrintStatusList(targs, &errors); 1353 MakePrintStatusList(targs, &errors);
1354 if (DEBUG(MAKE)) { 1354 if (DEBUG(MAKE)) {
1355 debug_printf("done: errors %d\n", errors); 1355 debug_printf("done: errors %d\n", errors);
1356 if (errors) 1356 if (errors)
1357 Targ_PrintGraph(4); 1357 Targ_PrintGraph(4);
1358 } 1358 }
1359 } 1359 }
1360 return errors != 0; 1360 return errors != 0;
1361} 1361}

cvs diff -r1.178 -r1.179 src/usr.bin/make/make.h (switch to unified diff)

--- src/usr.bin/make/make.h 2020/10/31 11:54:33 1.178
+++ src/usr.bin/make/make.h 2020/11/01 17:47:26 1.179
@@ -1,726 +1,726 @@ @@ -1,726 +1,726 @@
1/* $NetBSD: make.h,v 1.178 2020/10/31 11:54:33 rillig Exp $ */ 1/* $NetBSD: make.h,v 1.179 2020/11/01 17:47:26 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.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * from: @(#)make.h 8.3 (Berkeley) 6/13/95 34 * from: @(#)make.h 8.3 (Berkeley) 6/13/95
35 */ 35 */
36 36
37/* 37/*
38 * Copyright (c) 1989 by Berkeley Softworks 38 * Copyright (c) 1989 by Berkeley Softworks
39 * All rights reserved. 39 * All rights reserved.
40 * 40 *
41 * This code is derived from software contributed to Berkeley by 41 * This code is derived from software contributed to Berkeley by
42 * Adam de Boor. 42 * Adam de Boor.
43 * 43 *
44 * Redistribution and use in source and binary forms, with or without 44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions 45 * modification, are permitted provided that the following conditions
46 * are met: 46 * are met:
47 * 1. Redistributions of source code must retain the above copyright 47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer. 48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright 49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the 50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution. 51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software 52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement: 53 * must display the following acknowledgement:
54 * This product includes software developed by the University of 54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors. 55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors 56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software 57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission. 58 * without specific prior written permission.
59 * 59 *
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * SUCH DAMAGE. 70 * SUCH DAMAGE.
71 * 71 *
72 * from: @(#)make.h 8.3 (Berkeley) 6/13/95 72 * from: @(#)make.h 8.3 (Berkeley) 6/13/95
73 */ 73 */
74 74
75/*- 75/*-
76 * make.h -- 76 * make.h --
77 * The global definitions for pmake 77 * The global definitions for pmake
78 */ 78 */
79 79
80#ifndef MAKE_MAKE_H 80#ifndef MAKE_MAKE_H
81#define MAKE_MAKE_H 81#define MAKE_MAKE_H
82 82
83#include <sys/types.h> 83#include <sys/types.h>
84#include <sys/param.h> 84#include <sys/param.h>
85#include <sys/stat.h> 85#include <sys/stat.h>
86 86
87#include <assert.h> 87#include <assert.h>
88#include <ctype.h> 88#include <ctype.h>
89#include <fcntl.h> 89#include <fcntl.h>
90#include <stdarg.h> 90#include <stdarg.h>
91#include <stdio.h> 91#include <stdio.h>
92#include <stdlib.h> 92#include <stdlib.h>
93#include <string.h> 93#include <string.h>
94#include <unistd.h> 94#include <unistd.h>
95 95
96#ifdef BSD4_4 96#ifdef BSD4_4
97# include <sys/cdefs.h> 97# include <sys/cdefs.h>
98#endif 98#endif
99 99
100#ifndef FD_CLOEXEC 100#ifndef FD_CLOEXEC
101#define FD_CLOEXEC 1 101#define FD_CLOEXEC 1
102#endif 102#endif
103 103
104#if defined(__GNUC__) 104#if defined(__GNUC__)
105#define MAKE_GNUC_PREREQ(x, y) \ 105#define MAKE_GNUC_PREREQ(x, y) \
106 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ 106 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
107 (__GNUC__ > (x))) 107 (__GNUC__ > (x)))
108#else /* defined(__GNUC__) */ 108#else /* defined(__GNUC__) */
109#define MAKE_GNUC_PREREQ(x, y) 0 109#define MAKE_GNUC_PREREQ(x, y) 0
110#endif /* defined(__GNUC__) */ 110#endif /* defined(__GNUC__) */
111 111
112#if MAKE_GNUC_PREREQ(2, 7) 112#if MAKE_GNUC_PREREQ(2, 7)
113#define MAKE_ATTR_UNUSED __attribute__((__unused__)) 113#define MAKE_ATTR_UNUSED __attribute__((__unused__))
114#else 114#else
115#define MAKE_ATTR_UNUSED /* delete */ 115#define MAKE_ATTR_UNUSED /* delete */
116#endif 116#endif
117 117
118#if MAKE_GNUC_PREREQ(2, 5) 118#if MAKE_GNUC_PREREQ(2, 5)
119#define MAKE_ATTR_DEAD __attribute__((__noreturn__)) 119#define MAKE_ATTR_DEAD __attribute__((__noreturn__))
120#elif defined(__GNUC__) 120#elif defined(__GNUC__)
121#define MAKE_ATTR_DEAD __volatile 121#define MAKE_ATTR_DEAD __volatile
122#else 122#else
123#define MAKE_ATTR_DEAD /* delete */ 123#define MAKE_ATTR_DEAD /* delete */
124#endif 124#endif
125 125
126#if MAKE_GNUC_PREREQ(2, 7) 126#if MAKE_GNUC_PREREQ(2, 7)
127#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \ 127#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \
128 __attribute__((__format__ (__printf__, fmtarg, firstvararg))) 128 __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
129#else 129#else
130#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */ 130#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */
131#endif 131#endif
132 132
133/* 133/*
134 * A boolean type is defined as an integer, not an enum, for historic reasons. 134 * A boolean type is defined as an integer, not an enum, for historic reasons.
135 * The only allowed values are the constants TRUE and FALSE (1 and 0). 135 * The only allowed values are the constants TRUE and FALSE (1 and 0).
136 */ 136 */
137 137
138#ifdef USE_DOUBLE_BOOLEAN 138#ifdef USE_DOUBLE_BOOLEAN
139/* During development, to find type mismatches in function declarations. */ 139/* During development, to find type mismatches in function declarations. */
140typedef double Boolean; 140typedef double Boolean;
141#define TRUE 1.0 141#define TRUE 1.0
142#define FALSE 0.0 142#define FALSE 0.0
143#elif defined(USE_UCHAR_BOOLEAN) 143#elif defined(USE_UCHAR_BOOLEAN)
144/* During development, to find code that depends on the exact value of TRUE or 144/* During development, to find code that depends on the exact value of TRUE or
145 * that stores other values in Boolean variables. */ 145 * that stores other values in Boolean variables. */
146typedef unsigned char Boolean; 146typedef unsigned char Boolean;
147#define TRUE ((unsigned char)0xFF) 147#define TRUE ((unsigned char)0xFF)
148#define FALSE ((unsigned char)0x00) 148#define FALSE ((unsigned char)0x00)
149#elif defined(USE_CHAR_BOOLEAN) 149#elif defined(USE_CHAR_BOOLEAN)
150/* During development, to find code that uses a boolean as array index, via 150/* During development, to find code that uses a boolean as array index, via
151 * -Wchar-subscripts. */ 151 * -Wchar-subscripts. */
152typedef char Boolean; 152typedef char Boolean;
153#define TRUE ((char)-1) 153#define TRUE ((char)-1)
154#define FALSE ((char)0x00) 154#define FALSE ((char)0x00)
155#elif defined(USE_ENUM_BOOLEAN) 155#elif defined(USE_ENUM_BOOLEAN)
156typedef enum Boolean { FALSE, TRUE } Boolean; 156typedef enum Boolean { FALSE, TRUE } Boolean;
157#else 157#else
158typedef int Boolean; 158typedef int Boolean;
159#ifndef TRUE 159#ifndef TRUE
160#define TRUE 1 160#define TRUE 1
161#endif 161#endif
162#ifndef FALSE 162#ifndef FALSE
163#define FALSE 0 163#define FALSE 0
164#endif 164#endif
165#endif 165#endif
166 166
167#include "lst.h" 167#include "lst.h"
168#include "enum.h" 168#include "enum.h"
169#include "hash.h" 169#include "hash.h"
170#include "config.h" 170#include "config.h"
171#include "buf.h" 171#include "buf.h"
172#include "make_malloc.h" 172#include "make_malloc.h"
173 173
174typedef enum { 174typedef enum {
175 UNMADE, /* Not examined yet */ 175 UNMADE, /* Not examined yet */
176 DEFERRED, /* Examined once (building child) */ 176 DEFERRED, /* Examined once (building child) */
177 REQUESTED, /* on toBeMade list */ 177 REQUESTED, /* on toBeMade list */
178 BEINGMADE, /* Target is already being made. 178 BEINGMADE, /* Target is already being made.
179 * Indicates a cycle in the graph. */ 179 * Indicates a cycle in the graph. */
180 MADE, /* Was out-of-date and has been made */ 180 MADE, /* Was out-of-date and has been made */
181 UPTODATE, /* Was already up-to-date */ 181 UPTODATE, /* Was already up-to-date */
182 ERROR, /* An error occurred while it was being 182 ERROR, /* An error occurred while it was being
183 * made (used only in compat mode) */ 183 * made (used only in compat mode) */
184 ABORTED /* The target was aborted due to an error 184 ABORTED /* The target was aborted due to an error
185 * making an inferior (compat). */ 185 * making an inferior (compat). */
186} GNodeMade; 186} GNodeMade;
187 187
188/* The OP_ constants are used when parsing a dependency line as a way of 188/* The OP_ constants are used when parsing a dependency line as a way of
189 * communicating to other parts of the program the way in which a target 189 * communicating to other parts of the program the way in which a target
190 * should be made. 190 * should be made.
191 * 191 *
192 * Some of the OP_ constants can be combined, others cannot. */ 192 * Some of the OP_ constants can be combined, others cannot. */
193typedef enum GNodeType { 193typedef enum GNodeType {
194 /* The dependency operator ':' is the most common one. The commands of 194 /* The dependency operator ':' is the most common one. The commands of
195 * this node are executed if any child is out-of-date. */ 195 * this node are executed if any child is out-of-date. */
196 OP_DEPENDS = 1 << 0, 196 OP_DEPENDS = 1 << 0,
197 /* The dependency operator '!' always executes its commands, even if 197 /* The dependency operator '!' always executes its commands, even if
198 * its children are up-to-date. */ 198 * its children are up-to-date. */
199 OP_FORCE = 1 << 1, 199 OP_FORCE = 1 << 1,
200 /* The dependency operator '::' behaves like ':', except that it allows 200 /* The dependency operator '::' behaves like ':', except that it allows
201 * multiple dependency groups to be defined. Each of these groups is 201 * multiple dependency groups to be defined. Each of these groups is
202 * executed on its own, independently from the others. */ 202 * executed on its own, independently from the others. */
203 OP_DOUBLEDEP = 1 << 2, 203 OP_DOUBLEDEP = 1 << 2,
204 204
205 /* Matches the dependency operators ':', '!' and '::'. */ 205 /* Matches the dependency operators ':', '!' and '::'. */
206 OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP, 206 OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP,
207 207
208 /* Don't care if the target doesn't exist and can't be created */ 208 /* Don't care if the target doesn't exist and can't be created */
209 OP_OPTIONAL = 1 << 3, 209 OP_OPTIONAL = 1 << 3,
210 /* Use associated commands for parents */ 210 /* Use associated commands for parents */
211 OP_USE = 1 << 4, 211 OP_USE = 1 << 4,
212 /* Target is never out of date, but always execute commands anyway. 212 /* Target is never out of date, but always execute commands anyway.
213 * Its time doesn't matter, so it has none...sort of */ 213 * Its time doesn't matter, so it has none...sort of */
214 OP_EXEC = 1 << 5, 214 OP_EXEC = 1 << 5,
215 /* Ignore non-zero exit status from shell commands when creating the node */ 215 /* Ignore non-zero exit status from shell commands when creating the node */
216 OP_IGNORE = 1 << 6, 216 OP_IGNORE = 1 << 6,
217 /* Don't remove the target when interrupted */ 217 /* Don't remove the target when interrupted */
218 OP_PRECIOUS = 1 << 7, 218 OP_PRECIOUS = 1 << 7,
219 /* Don't echo commands when executed */ 219 /* Don't echo commands when executed */
220 OP_SILENT = 1 << 8, 220 OP_SILENT = 1 << 8,
221 /* Target is a recursive make so its commands should always be executed 221 /* Target is a recursive make so its commands should always be executed
222 * when it is out of date, regardless of the state of the -n or -t flags */ 222 * when it is out of date, regardless of the state of the -n or -t flags */
223 OP_MAKE = 1 << 9, 223 OP_MAKE = 1 << 9,
224 /* Target is out-of-date only if any of its children was out-of-date */ 224 /* Target is out-of-date only if any of its children was out-of-date */
225 OP_JOIN = 1 << 10, 225 OP_JOIN = 1 << 10,
226 /* Assume the children of the node have been already made */ 226 /* Assume the children of the node have been already made */
227 OP_MADE = 1 << 11, 227 OP_MADE = 1 << 11,
228 /* Special .BEGIN, .END, .INTERRUPT */ 228 /* Special .BEGIN, .END, .INTERRUPT */
229 OP_SPECIAL = 1 << 12, 229 OP_SPECIAL = 1 << 12,
230 /* Like .USE, only prepend commands */ 230 /* Like .USE, only prepend commands */
231 OP_USEBEFORE = 1 << 13, 231 OP_USEBEFORE = 1 << 13,
232 /* The node is invisible to its parents. I.e. it doesn't show up in the 232 /* The node is invisible to its parents. I.e. it doesn't show up in the
233 * parents' local variables. */ 233 * parents' local variables. */
234 OP_INVISIBLE = 1 << 14, 234 OP_INVISIBLE = 1 << 14,
235 /* The node is exempt from normal 'main target' processing in parse.c */ 235 /* The node is exempt from normal 'main target' processing in parse.c */
236 OP_NOTMAIN = 1 << 15, 236 OP_NOTMAIN = 1 << 15,
237 /* Not a file target; run always */ 237 /* Not a file target; run always */
238 OP_PHONY = 1 << 16, 238 OP_PHONY = 1 << 16,
239 /* Don't search for file in the path */ 239 /* Don't search for file in the path */
240 OP_NOPATH = 1 << 17, 240 OP_NOPATH = 1 << 17,
241 /* .WAIT phony node */ 241 /* .WAIT phony node */
242 OP_WAIT = 1 << 18, 242 OP_WAIT = 1 << 18,
243 /* .NOMETA do not create a .meta file */ 243 /* .NOMETA do not create a .meta file */
244 OP_NOMETA = 1 << 19, 244 OP_NOMETA = 1 << 19,
245 /* .META we _do_ want a .meta file */ 245 /* .META we _do_ want a .meta file */
246 OP_META = 1 << 20, 246 OP_META = 1 << 20,
247 /* Do not compare commands in .meta file */ 247 /* Do not compare commands in .meta file */
248 OP_NOMETA_CMP = 1 << 21, 248 OP_NOMETA_CMP = 1 << 21,
249 /* Possibly a submake node */ 249 /* Possibly a submake node */
250 OP_SUBMAKE = 1 << 22, 250 OP_SUBMAKE = 1 << 22,
251 251
252 /* Attributes applied by PMake */ 252 /* Attributes applied by PMake */
253 253
254 /* The node is a transformation rule */ 254 /* The node is a transformation rule */
255 OP_TRANSFORM = 1 << 31, 255 OP_TRANSFORM = 1 << 31,
256 /* Target is a member of an archive */ 256 /* Target is a member of an archive */
257 /* XXX: How does this differ from OP_ARCHV? */ 257 /* XXX: How does this differ from OP_ARCHV? */
258 OP_MEMBER = 1 << 30, 258 OP_MEMBER = 1 << 30,
259 /* The node is a library, 259 /* The node is a library,
260 * its name has the form "-l<libname>" */ 260 * its name has the form "-l<libname>" */
261 OP_LIB = 1 << 29, 261 OP_LIB = 1 << 29,
262 /* The node is an archive member, 262 /* The node is an archive member,
263 * its name has the form "archive(member)" */ 263 * its name has the form "archive(member)" */
264 /* XXX: How does this differ from OP_MEMBER? */ 264 /* XXX: How does this differ from OP_MEMBER? */
265 OP_ARCHV = 1 << 28, 265 OP_ARCHV = 1 << 28,
266 /* Target has all the commands it should. Used when parsing to catch 266 /* Target has all the commands it should. Used when parsing to catch
267 * multiple command groups for a target. Only applies to the dependency 267 * multiple command groups for a target. Only applies to the dependency
268 * operators ':' and '!', but not to '::'. */ 268 * operators ':' and '!', but not to '::'. */
269 OP_HAS_COMMANDS = 1 << 27, 269 OP_HAS_COMMANDS = 1 << 27,
270 /* The special command "..." has been seen. All further commands from 270 /* The special command "..." has been seen. All further commands from
271 * this node will be saved on the .END node instead, to be executed at 271 * this node will be saved on the .END node instead, to be executed at
272 * the very end. */ 272 * the very end. */
273 OP_SAVE_CMDS = 1 << 26, 273 OP_SAVE_CMDS = 1 << 26,
274 /* Already processed by Suff_FindDeps */ 274 /* Already processed by Suff_FindDeps */
275 OP_DEPS_FOUND = 1 << 25, 275 OP_DEPS_FOUND = 1 << 25,
276 /* Node found while expanding .ALLSRC */ 276 /* Node found while expanding .ALLSRC */
277 OP_MARK = 1 << 24, 277 OP_MARK = 1 << 24,
278 278
279 OP_NOTARGET = OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM 279 OP_NOTARGET = OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM
280} GNodeType; 280} GNodeType;
281 281
282typedef enum GNodeFlags { 282typedef enum GNodeFlags {
283 REMAKE = 0x0001, /* this target needs to be (re)made */ 283 REMAKE = 0x0001, /* this target needs to be (re)made */
284 CHILDMADE = 0x0002, /* children of this target were made */ 284 CHILDMADE = 0x0002, /* children of this target were made */
285 FORCE = 0x0004, /* children don't exist, and we pretend made */ 285 FORCE = 0x0004, /* children don't exist, and we pretend made */
286 DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */ 286 DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */
287 DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */ 287 DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */
288 FROM_DEPEND = 0x0020, /* Node created from .depend */ 288 FROM_DEPEND = 0x0020, /* Node created from .depend */
289 DONE_ALLSRC = 0x0040, /* We do it once only */ 289 DONE_ALLSRC = 0x0040, /* We do it once only */
290 CYCLE = 0x1000, /* Used by MakePrintStatus */ 290 CYCLE = 0x1000, /* Used by MakePrintStatus */
291 DONECYCLE = 0x2000, /* Used by MakePrintStatus */ 291 DONECYCLE = 0x2000, /* Used by MakePrintStatus */
292 INTERNAL = 0x4000 /* Internal use only */ 292 INTERNAL = 0x4000 /* Internal use only */
293} GNodeFlags; 293} GNodeFlags;
294 294
295typedef struct List StringList; 295typedef struct List StringList;
296typedef struct ListNode StringListNode; 296typedef struct ListNode StringListNode;
297 297
298typedef struct List GNodeList; 298typedef struct List GNodeList;
299typedef struct ListNode GNodeListNode; 299typedef struct ListNode GNodeListNode;
300 300
301typedef struct List /* of CachedDir */ SearchPath; 301typedef struct List /* of CachedDir */ SearchPath;
302 302
303/* A graph node represents a target that can possibly be made, including its 303/* A graph node represents a target that can possibly be made, including its
304 * relation to other targets and a lot of other details. */ 304 * relation to other targets and a lot of other details. */
305typedef struct GNode { 305typedef struct GNode {
306 /* The target's name, such as "clean" or "make.c" */ 306 /* The target's name, such as "clean" or "make.c" */
307 char *name; 307 char *name;
308 /* The unexpanded name of a .USE node */ 308 /* The unexpanded name of a .USE node */
309 char *uname; 309 char *uname;
310 /* The full pathname of the file belonging to the target. 310 /* The full pathname of the file belonging to the target.
311 * XXX: What about .PHONY targets? These don't have an associated path. */ 311 * XXX: What about .PHONY targets? These don't have an associated path. */
312 char *path; 312 char *path;
313 313
314 /* The type of operator used to define the sources (see the OP flags below). 314 /* The type of operator used to define the sources (see the OP flags below).
315 * XXX: This looks like a wild mixture of type and flags. */ 315 * XXX: This looks like a wild mixture of type and flags. */
316 GNodeType type; 316 GNodeType type;
317 GNodeFlags flags; 317 GNodeFlags flags;
318 318
319 /* The state of processing on this node */ 319 /* The state of processing on this node */
320 GNodeMade made; 320 GNodeMade made;
321 int unmade; /* The number of unmade children */ 321 int unmade; /* The number of unmade children */
322 322
323 /* The modification time; 0 means the node does not have a corresponding 323 /* The modification time; 0 means the node does not have a corresponding
324 * file; see Make_OODate. */ 324 * file; see Make_OODate. */
325 time_t mtime; 325 time_t mtime;
326 struct GNode *youngestChild; 326 struct GNode *youngestChild;
327 327
328 /* The GNodes for which this node is an implied source. May be empty. 328 /* The GNodes for which this node is an implied source. May be empty.
329 * For example, when there is an inference rule for .c.o, the node for 329 * For example, when there is an inference rule for .c.o, the node for
330 * file.c has the node for file.o in this list. */ 330 * file.c has the node for file.o in this list. */
331 GNodeList *implicitParents; 331 GNodeList *implicitParents;
332 332
333 /* Other nodes of the same name, for the '::' operator. */ 333 /* Other nodes of the same name, for the '::' operator. */
334 GNodeList *cohorts; 334 GNodeList *cohorts;
335 335
336 /* The nodes that depend on this one, or in other words, the nodes for 336 /* The nodes that depend on this one, or in other words, the nodes for
337 * which this is a source. */ 337 * which this is a source. */
338 GNodeList *parents; 338 GNodeList *parents;
339 /* The nodes on which this one depends. */ 339 /* The nodes on which this one depends. */
340 GNodeList *children; 340 GNodeList *children;
341 341
342 /* .ORDER nodes we need made. The nodes that must be made (if they're 342 /* .ORDER nodes we need made. The nodes that must be made (if they're
343 * made) before this node can be made, but that do not enter into the 343 * made) before this node can be made, but that do not enter into the
344 * datedness of this node. */ 344 * datedness of this node. */
345 GNodeList *order_pred; 345 GNodeList *order_pred;
346 /* .ORDER nodes who need us. The nodes that must be made (if they're made 346 /* .ORDER nodes who need us. The nodes that must be made (if they're made
347 * at all) after this node is made, but that do not depend on this node, 347 * at all) after this node is made, but that do not depend on this node,
348 * in the normal sense. */ 348 * in the normal sense. */
349 GNodeList *order_succ; 349 GNodeList *order_succ;
350 350
351 /* The "#n" suffix for this cohort, or "" for other nodes */ 351 /* The "#n" suffix for this cohort, or "" for other nodes */
352 char cohort_num[8]; 352 char cohort_num[8];
353 /* The number of unmade instances on the cohorts list */ 353 /* The number of unmade instances on the cohorts list */
354 int unmade_cohorts; 354 int unmade_cohorts;
355 /* Pointer to the first instance of a '::' node; only set when on a 355 /* Pointer to the first instance of a '::' node; only set when on a
356 * cohorts list */ 356 * cohorts list */
357 struct GNode *centurion; 357 struct GNode *centurion;
358 358
359 /* Last time (sequence number) we tried to make this node */ 359 /* Last time (sequence number) we tried to make this node */
360 unsigned int checked_seqno; 360 unsigned int checked_seqno;
361 361
362 /* The "local" variables that are specific to this target and this target 362 /* The "local" variables that are specific to this target and this target
363 * only, such as $@, $<, $?. 363 * only, such as $@, $<, $?.
364 * 364 *
365 * Also used for the global variable scopes VAR_GLOBAL, VAR_CMDLINE, 365 * Also used for the global variable scopes VAR_GLOBAL, VAR_CMDLINE,
366 * VAR_INTERNAL, which contain variables with arbitrary names. */ 366 * VAR_INTERNAL, which contain variables with arbitrary names. */
367 HashTable /* of Var pointer */ context; 367 HashTable /* of Var pointer */ context;
368 368
369 /* The commands to be given to a shell to create this target. */ 369 /* The commands to be given to a shell to create this target. */
370 StringList *commands; 370 StringList *commands;
371 371
372 /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone 372 /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone
373 * but the Suff module) */ 373 * but the Suff module) */
374 struct Suff *suffix; 374 struct Suff *suffix;
375 375
376 /* filename where the GNode got defined */ 376 /* filename where the GNode got defined */
377 const char *fname; 377 const char *fname;
378 /* line number where the GNode got defined */ 378 /* line number where the GNode got defined */
379 int lineno; 379 int lineno;
380} GNode; 380} GNode;
381 381
382/* 382/*
383 * Error levels for parsing. PARSE_FATAL means the process cannot continue 383 * Error levels for parsing. PARSE_FATAL means the process cannot continue
384 * once the top-level makefile has been parsed. PARSE_WARNING and PARSE_INFO 384 * once the top-level makefile has been parsed. PARSE_WARNING and PARSE_INFO
385 * mean it can. 385 * mean it can.
386 */ 386 */
387typedef enum ParseErrorLevel { 387typedef enum ParseErrorLevel {
388 PARSE_FATAL = 1, 388 PARSE_FATAL = 1,
389 PARSE_WARNING, 389 PARSE_WARNING,
390 PARSE_INFO 390 PARSE_INFO
391} ParseErrorLevel; 391} ParseErrorLevel;
392 392
393/* 393/*
394 * Values returned by Cond_EvalLine and Cond_EvalCondition. 394 * Values returned by Cond_EvalLine and Cond_EvalCondition.
395 */ 395 */
396typedef enum CondEvalResult { 396typedef enum CondEvalResult {
397 COND_PARSE, /* Parse the next lines */ 397 COND_PARSE, /* Parse the next lines */
398 COND_SKIP, /* Skip the next lines */ 398 COND_SKIP, /* Skip the next lines */
399 COND_INVALID /* Not a conditional statement */ 399 COND_INVALID /* Not a conditional statement */
400} CondEvalResult; 400} CondEvalResult;
401 401
402/* 402/*
403 * Definitions for the "local" variables. Used only for clarity. 403 * Definitions for the "local" variables. Used only for clarity.
404 */ 404 */
405#define TARGET "@" /* Target of dependency */ 405#define TARGET "@" /* Target of dependency */
406#define OODATE "?" /* All out-of-date sources */ 406#define OODATE "?" /* All out-of-date sources */
407#define ALLSRC ">" /* All sources */ 407#define ALLSRC ">" /* All sources */
408#define IMPSRC "<" /* Source implied by transformation */ 408#define IMPSRC "<" /* Source implied by transformation */
409#define PREFIX "*" /* Common prefix */ 409#define PREFIX "*" /* Common prefix */
410#define ARCHIVE "!" /* Archive in "archive(member)" syntax */ 410#define ARCHIVE "!" /* Archive in "archive(member)" syntax */
411#define MEMBER "%" /* Member in "archive(member)" syntax */ 411#define MEMBER "%" /* Member in "archive(member)" syntax */
412 412
413#define FTARGET "@F" /* file part of TARGET */ 413#define FTARGET "@F" /* file part of TARGET */
414#define DTARGET "@D" /* directory part of TARGET */ 414#define DTARGET "@D" /* directory part of TARGET */
415#define FIMPSRC "<F" /* file part of IMPSRC */ 415#define FIMPSRC "<F" /* file part of IMPSRC */
416#define DIMPSRC "<D" /* directory part of IMPSRC */ 416#define DIMPSRC "<D" /* directory part of IMPSRC */
417#define FPREFIX "*F" /* file part of PREFIX */ 417#define FPREFIX "*F" /* file part of PREFIX */
418#define DPREFIX "*D" /* directory part of PREFIX */ 418#define DPREFIX "*D" /* directory part of PREFIX */
419 419
420/* 420/*
421 * Global Variables 421 * Global Variables
422 */ 422 */
423extern SearchPath *dirSearchPath; 423extern SearchPath *dirSearchPath;
424 /* The list of directories to search when 424 /* The list of directories to search when
425 * looking for targets */ 425 * looking for targets */
426extern Boolean allPrecious; /* True if every target is precious */ 426extern Boolean allPrecious; /* True if every target is precious */
427extern Boolean deleteOnError; /* True if failed targets should be deleted */ 427extern Boolean deleteOnError; /* True if failed targets should be deleted */
428extern Boolean doing_depend; /* TRUE if processing .depend */ 428extern Boolean doing_depend; /* TRUE if processing .depend */
429 429
430extern GNode *DEFAULT; /* .DEFAULT rule */ 430extern GNode *DEFAULT; /* .DEFAULT rule */
431 431
432extern GNode *VAR_INTERNAL; /* Variables defined internally by make 432extern GNode *VAR_INTERNAL; /* Variables defined internally by make
433 * which should not override those set by 433 * which should not override those set by
434 * makefiles. 434 * makefiles.
435 */ 435 */
436extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g 436extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g
437 * in the Makefile itself */ 437 * in the Makefile itself */
438extern GNode *VAR_CMDLINE; /* Variables defined on the command line */ 438extern GNode *VAR_CMDLINE; /* Variables defined on the command line */
439extern char var_Error[]; /* Value returned by Var_Parse when an error 439extern char var_Error[]; /* Value returned by Var_Parse when an error
440 * is encountered. It actually points to 440 * is encountered. It actually points to
441 * an empty string, so naive callers needn't 441 * an empty string, so naive callers needn't
442 * worry about it. */ 442 * worry about it. */
443 443
444extern time_t now; /* The time at the start of this whole 444extern time_t now; /* The time at the start of this whole
445 * process */ 445 * process */
446 446
447extern Boolean oldVars; /* Do old-style variable substitution */ 447extern Boolean oldVars; /* Do old-style variable substitution */
448 448
449extern SearchPath *sysIncPath; /* The system include path. */ 449extern SearchPath *sysIncPath; /* The system include path. */
450extern SearchPath *defSysIncPath; /* The default system include path. */ 450extern SearchPath *defSysIncPath; /* The default system include path. */
451 451
452extern char curdir[]; /* Startup directory */ 452extern char curdir[]; /* Startup directory */
453extern char *progname; /* The program name */ 453extern char *progname; /* The program name */
454extern char *makeDependfile; /* .depend */ 454extern char *makeDependfile; /* .depend */
455extern char **savedEnv; /* if we replaced environ this will be non-NULL */ 455extern char **savedEnv; /* if we replaced environ this will be non-NULL */
456 456
457extern int makelevel; 457extern int makelevel;
458 458
459/* 459/*
460 * We cannot vfork() in a child of vfork(). 460 * We cannot vfork() in a child of vfork().
461 * Most systems do not enforce this but some do. 461 * Most systems do not enforce this but some do.
462 */ 462 */
463#define vFork() ((getpid() == myPid) ? vfork() : fork()) 463#define vFork() ((getpid() == myPid) ? vfork() : fork())
464extern pid_t myPid; 464extern pid_t myPid;
465 465
466#define MAKEFLAGS ".MAKEFLAGS" 466#define MAKEFLAGS ".MAKEFLAGS"
467#define MAKEOVERRIDES ".MAKEOVERRIDES" 467#define MAKEOVERRIDES ".MAKEOVERRIDES"
468#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" /* prefix for job target output */ 468#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" /* prefix for job target output */
469#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */ 469#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */
470#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all makefiles already loaded */ 470#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all makefiles already loaded */
471#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */ 471#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */
472#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE" 472#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
473#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */ 473#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */
474#define MAKE_MODE ".MAKE.MODE" 474#define MAKE_MODE ".MAKE.MODE"
475#ifndef MAKE_LEVEL_ENV 475#ifndef MAKE_LEVEL_ENV
476# define MAKE_LEVEL_ENV "MAKELEVEL" 476# define MAKE_LEVEL_ENV "MAKELEVEL"
477#endif 477#endif
478 478
479typedef enum DebugFlags { 479typedef enum DebugFlags {
480 DEBUG_ARCH = 1 << 0, 480 DEBUG_ARCH = 1 << 0,
481 DEBUG_COND = 1 << 1, 481 DEBUG_COND = 1 << 1,
482 DEBUG_DIR = 1 << 2, 482 DEBUG_DIR = 1 << 2,
483 DEBUG_GRAPH1 = 1 << 3, 483 DEBUG_GRAPH1 = 1 << 3,
484 DEBUG_GRAPH2 = 1 << 4, 484 DEBUG_GRAPH2 = 1 << 4,
485 DEBUG_JOB = 1 << 5, 485 DEBUG_JOB = 1 << 5,
486 DEBUG_MAKE = 1 << 6, 486 DEBUG_MAKE = 1 << 6,
487 DEBUG_SUFF = 1 << 7, 487 DEBUG_SUFF = 1 << 7,
488 DEBUG_TARG = 1 << 8, 488 DEBUG_TARG = 1 << 8,
489 DEBUG_VAR = 1 << 9, 489 DEBUG_VAR = 1 << 9,
490 DEBUG_FOR = 1 << 10, 490 DEBUG_FOR = 1 << 10,
491 DEBUG_SHELL = 1 << 11, 491 DEBUG_SHELL = 1 << 11,
492 DEBUG_ERROR = 1 << 12, 492 DEBUG_ERROR = 1 << 12,
493 DEBUG_LOUD = 1 << 13, 493 DEBUG_LOUD = 1 << 13,
494 DEBUG_META = 1 << 14, 494 DEBUG_META = 1 << 14,
495 DEBUG_HASH = 1 << 15, 495 DEBUG_HASH = 1 << 15,
496 496
497 DEBUG_GRAPH3 = 1 << 16, 497 DEBUG_GRAPH3 = 1 << 16,
498 DEBUG_SCRIPT = 1 << 17, 498 DEBUG_SCRIPT = 1 << 17,
499 DEBUG_PARSE = 1 << 18, 499 DEBUG_PARSE = 1 << 18,
500 DEBUG_CWD = 1 << 19, 500 DEBUG_CWD = 1 << 19,
501 501
502 DEBUG_LINT = 1 << 20 502 DEBUG_LINT = 1 << 20
503} DebugFlags; 503} DebugFlags;
504 504
505#define CONCAT(a,b) a##b 505#define CONCAT(a,b) a##b
506 506
507#define DEBUG(module) (opts.debug & CONCAT(DEBUG_,module)) 507#define DEBUG(module) (opts.debug & CONCAT(DEBUG_,module))
508 508
509void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); 509void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
510 510
511#define DEBUG0(module, text) \ 511#define DEBUG0(module, text) \
512 if (!DEBUG(module)) (void)0; \ 512 if (!DEBUG(module)) (void)0; \
513 else debug_printf("%s", text) 513 else debug_printf("%s", text)
514 514
515#define DEBUG1(module, fmt, arg1) \ 515#define DEBUG1(module, fmt, arg1) \
516 if (!DEBUG(module)) (void)0; \ 516 if (!DEBUG(module)) (void)0; \
517 else debug_printf(fmt, arg1) 517 else debug_printf(fmt, arg1)
518 518
519#define DEBUG2(module, fmt, arg1, arg2) \ 519#define DEBUG2(module, fmt, arg1, arg2) \
520 if (!DEBUG(module)) (void)0; \ 520 if (!DEBUG(module)) (void)0; \
521 else debug_printf(fmt, arg1, arg2) 521 else debug_printf(fmt, arg1, arg2)
522 522
523#define DEBUG3(module, fmt, arg1, arg2, arg3) \ 523#define DEBUG3(module, fmt, arg1, arg2, arg3) \
524 if (!DEBUG(module)) (void)0; \ 524 if (!DEBUG(module)) (void)0; \
525 else debug_printf(fmt, arg1, arg2, arg3) 525 else debug_printf(fmt, arg1, arg2, arg3)
526 526
527#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \ 527#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \
528 if (!DEBUG(module)) (void)0; \ 528 if (!DEBUG(module)) (void)0; \
529 else debug_printf(fmt, arg1, arg2, arg3, arg4) 529 else debug_printf(fmt, arg1, arg2, arg3, arg4)
530 530
531#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \ 531#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \
532 if (!DEBUG(module)) (void)0; \ 532 if (!DEBUG(module)) (void)0; \
533 else debug_printf(fmt, arg1, arg2, arg3, arg4, arg5) 533 else debug_printf(fmt, arg1, arg2, arg3, arg4, arg5)
534 534
535typedef enum PrintVarsMode { 535typedef enum PrintVarsMode {
536 COMPAT_VARS = 1, 536 COMPAT_VARS = 1,
537 EXPAND_VARS 537 EXPAND_VARS
538} PrintVarsMode; 538} PrintVarsMode;
539 539
540/* Command line options */ 540/* Command line options */
541typedef struct CmdOpts { 541typedef struct CmdOpts {
542 /* -B: whether we are make compatible */ 542 /* -B: whether we are make compatible */
543 Boolean compatMake; 543 Boolean compatMake;
544 544
545 /* -d: debug control: There is one bit per module. It is up to the 545 /* -d: debug control: There is one bit per module. It is up to the
546 * module what debug information to print. */ 546 * module what debug information to print. */
547 DebugFlags debug; 547 DebugFlags debug;
548 548
549 /* -df: debug output is written here - default stderr */ 549 /* -df: debug output is written here - default stderr */
550 FILE *debug_file; 550 FILE *debug_file;
551 551
552 /* -dV: for the -V option, print unexpanded variable values */ 552 /* -dV: for the -V option, print unexpanded variable values */
553 Boolean debugVflag; 553 Boolean debugVflag;
554 554
555 /* -e: check environment variables before global variables */ 555 /* -e: check environment variables before global variables */
556 Boolean checkEnvFirst; 556 Boolean checkEnvFirst;
557 557
558 /* -f: the makefiles to read */ 558 /* -f: the makefiles to read */
559 StringList *makefiles; 559 StringList *makefiles;
560 560
561 /* -i: if true, ignore all errors from shell commands */ 561 /* -i: if true, ignore all errors from shell commands */
562 Boolean ignoreErrors; 562 Boolean ignoreErrors;
563 563
564 /* -j: the maximum number of jobs that can run in parallel; 564 /* -j: the maximum number of jobs that can run in parallel;
565 * this is coordinated with the submakes */ 565 * this is coordinated with the submakes */
566 int maxJobs; 566 int maxJobs;
567 567
568 /* -k: if true, continue on unaffected portions of the graph when an 568 /* -k: if true, continue on unaffected portions of the graph when an
569 * error occurs in one portion */ 569 * error occurs in one portion */
570 Boolean keepgoing; 570 Boolean keepgoing;
571 571
572 /* -N: execute no commands from the targets */ 572 /* -N: execute no commands from the targets */
573 Boolean noRecursiveExecute; 573 Boolean noRecursiveExecute;
574 574
575 /* -n: execute almost no commands from the targets */ 575 /* -n: execute almost no commands from the targets */
576 Boolean noExecute; 576 Boolean noExecute;
577 577
578 /* -q: if true, we aren't supposed to really make anything, just see if 578 /* -q: if true, we aren't supposed to really make anything, just see if
579 * the targets are out-of-date */ 579 * the targets are out-of-date */
580 Boolean queryFlag; 580 Boolean queryFlag;
581 581
582 /* -r: raw mode, without loading the builtin rules. */ 582 /* -r: raw mode, without loading the builtin rules. */
583 Boolean noBuiltins; 583 Boolean noBuiltins;
584 584
585 /* -s: don't echo the shell commands before executing them */ 585 /* -s: don't echo the shell commands before executing them */
586 Boolean beSilent; 586 Boolean beSilent;
587 587
588 /* -t: touch the targets if they are out-of-date, but don't actually 588 /* -t: touch the targets if they are out-of-date, but don't actually
589 * make them */ 589 * make them */
590 Boolean touchFlag; 590 Boolean touchFlag;
591 591
592 /* -[Vv]: print expanded or unexpanded selected variables */ 592 /* -[Vv]: print expanded or unexpanded selected variables */
593 PrintVarsMode printVars; 593 PrintVarsMode printVars;
594 /* -[Vv]: the variables to print */ 594 /* -[Vv]: the variables to print */
595 StringList *variables; 595 StringList *variables;
596 596
597 /* -W: if true, makefile parsing warnings are treated as errors */ 597 /* -W: if true, makefile parsing warnings are treated as errors */
598 Boolean parseWarnFatal; 598 Boolean parseWarnFatal;
599 599
600 /* -w: print Entering and Leaving for submakes */ 600 /* -w: print Entering and Leaving for submakes */
601 Boolean enterFlag; 601 Boolean enterFlag;
602 602
603 /* -X: if true, do not export variables set on the command line to the 603 /* -X: if true, do not export variables set on the command line to the
604 * environment. */ 604 * environment. */
605 Boolean varNoExportEnv; 605 Boolean varNoExportEnv;
606 606
607 /* The target names specified on the command line. 607 /* The target names specified on the command line.
608 * Used to resolve .if make(...) statements. */ 608 * Used to resolve .if make(...) statements. */
609 StringList *create; 609 StringList *create;
610 610
611} CmdOpts; 611} CmdOpts;
612 612
613extern CmdOpts opts; 613extern CmdOpts opts;
614 614
615#include "nonints.h" 615#include "nonints.h"
616 616
617void Make_TimeStamp(GNode *, GNode *); 617void Make_TimeStamp(GNode *, GNode *);
618Boolean Make_OODate(GNode *); 618Boolean Make_OODate(GNode *);
619void Make_ExpandUse(GNodeList *); 619void Make_ExpandUse(GNodeList *);
620time_t Make_Recheck(GNode *); 620time_t Make_Recheck(GNode *);
621void Make_HandleUse(GNode *, GNode *); 621void Make_HandleUse(GNode *, GNode *);
622void Make_Update(GNode *); 622void Make_Update(GNode *);
623void Make_DoAllVar(GNode *); 623void Make_DoAllVar(GNode *);
624Boolean Make_Run(GNodeList *); 624Boolean Make_Run(GNodeList *);
625int dieQuietly(GNode *, int); 625int dieQuietly(GNode *, int);
626void PrintOnError(GNode *, const char *); 626void PrintOnError(GNode *, const char *);
627void Main_ExportMAKEFLAGS(Boolean); 627void Main_ExportMAKEFLAGS(Boolean);
628Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); 628Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
629int mkTempFile(const char *, char **); 629int mkTempFile(const char *, char **);
630int str2Lst_Append(StringList *, char *, const char *); 630int str2Lst_Append(StringList *, char *, const char *);
631void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *); 631void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
632Boolean NoExecute(GNode *gn); 632Boolean GNode_ShouldExecute(GNode *gn);
633 633
634/* See if the node was seen on the left-hand side of a dependency operator. */ 634/* See if the node was seen on the left-hand side of a dependency operator. */
635static MAKE_ATTR_UNUSED Boolean 635static MAKE_ATTR_UNUSED Boolean
636GNode_IsTarget(const GNode *gn) 636GNode_IsTarget(const GNode *gn)
637{ 637{
638 return (gn->type & OP_OPMASK) != 0; 638 return (gn->type & OP_OPMASK) != 0;
639} 639}
640 640
641static MAKE_ATTR_UNUSED const char * 641static MAKE_ATTR_UNUSED const char *
642GNode_Path(const GNode *gn) 642GNode_Path(const GNode *gn)
643{ 643{
644 return gn->path != NULL ? gn->path : gn->name; 644 return gn->path != NULL ? gn->path : gn->name;
645} 645}
646 646
647static MAKE_ATTR_UNUSED const char * 647static MAKE_ATTR_UNUSED const char *
648GNode_VarTarget(GNode *gn) { return Var_ValueDirect(TARGET, gn); } 648GNode_VarTarget(GNode *gn) { return Var_ValueDirect(TARGET, gn); }
649static MAKE_ATTR_UNUSED const char * 649static MAKE_ATTR_UNUSED const char *
650GNode_VarOodate(GNode *gn) { return Var_ValueDirect(OODATE, gn); } 650GNode_VarOodate(GNode *gn) { return Var_ValueDirect(OODATE, gn); }
651static MAKE_ATTR_UNUSED const char * 651static MAKE_ATTR_UNUSED const char *
652GNode_VarAllsrc(GNode *gn) { return Var_ValueDirect(ALLSRC, gn); } 652GNode_VarAllsrc(GNode *gn) { return Var_ValueDirect(ALLSRC, gn); }
653static MAKE_ATTR_UNUSED const char * 653static MAKE_ATTR_UNUSED const char *
654GNode_VarImpsrc(GNode *gn) { return Var_ValueDirect(IMPSRC, gn); } 654GNode_VarImpsrc(GNode *gn) { return Var_ValueDirect(IMPSRC, gn); }
655static MAKE_ATTR_UNUSED const char * 655static MAKE_ATTR_UNUSED const char *
656GNode_VarPrefix(GNode *gn) { return Var_ValueDirect(PREFIX, gn); } 656GNode_VarPrefix(GNode *gn) { return Var_ValueDirect(PREFIX, gn); }
657static MAKE_ATTR_UNUSED const char * 657static MAKE_ATTR_UNUSED const char *
658GNode_VarArchive(GNode *gn) { return Var_ValueDirect(ARCHIVE, gn); } 658GNode_VarArchive(GNode *gn) { return Var_ValueDirect(ARCHIVE, gn); }
659static MAKE_ATTR_UNUSED const char * 659static MAKE_ATTR_UNUSED const char *
660GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); } 660GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); }
661 661
662#ifdef __GNUC__ 662#ifdef __GNUC__
663#define UNCONST(ptr) ({ \ 663#define UNCONST(ptr) ({ \
664 union __unconst { \ 664 union __unconst { \
665 const void *__cp; \ 665 const void *__cp; \
666 void *__p; \ 666 void *__p; \
667 } __d; \ 667 } __d; \
668 __d.__cp = ptr, __d.__p; }) 668 __d.__cp = ptr, __d.__p; })
669#else 669#else
670#define UNCONST(ptr) (void *)(ptr) 670#define UNCONST(ptr) (void *)(ptr)
671#endif 671#endif
672 672
673/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */ 673/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
674#include <limits.h> 674#include <limits.h>
675#ifndef MAXPATHLEN 675#ifndef MAXPATHLEN
676#define MAXPATHLEN 4096 676#define MAXPATHLEN 4096
677#endif 677#endif
678#ifndef PATH_MAX 678#ifndef PATH_MAX
679#define PATH_MAX MAXPATHLEN 679#define PATH_MAX MAXPATHLEN
680#endif 680#endif
681 681
682#if defined(SYSV) 682#if defined(SYSV)
683#define KILLPG(pid, sig) kill(-(pid), (sig)) 683#define KILLPG(pid, sig) kill(-(pid), (sig))
684#else 684#else
685#define KILLPG(pid, sig) killpg((pid), (sig)) 685#define KILLPG(pid, sig) killpg((pid), (sig))
686#endif 686#endif
687 687
688static inline MAKE_ATTR_UNUSED Boolean ch_isalnum(char ch) 688static inline MAKE_ATTR_UNUSED Boolean ch_isalnum(char ch)
689{ return isalnum((unsigned char)ch) != 0; } 689{ return isalnum((unsigned char)ch) != 0; }
690static inline MAKE_ATTR_UNUSED Boolean ch_isalpha(char ch) 690static inline MAKE_ATTR_UNUSED Boolean ch_isalpha(char ch)
691{ return isalpha((unsigned char)ch) != 0; } 691{ return isalpha((unsigned char)ch) != 0; }
692static inline MAKE_ATTR_UNUSED Boolean ch_isdigit(char ch) 692static inline MAKE_ATTR_UNUSED Boolean ch_isdigit(char ch)
693{ return isdigit((unsigned char)ch) != 0; } 693{ return isdigit((unsigned char)ch) != 0; }
694static inline MAKE_ATTR_UNUSED Boolean ch_isspace(char ch) 694static inline MAKE_ATTR_UNUSED Boolean ch_isspace(char ch)
695{ return isspace((unsigned char)ch) != 0; } 695{ return isspace((unsigned char)ch) != 0; }
696static inline MAKE_ATTR_UNUSED Boolean ch_isupper(char ch) 696static inline MAKE_ATTR_UNUSED Boolean ch_isupper(char ch)
697{ return isupper((unsigned char)ch) != 0; } 697{ return isupper((unsigned char)ch) != 0; }
698static inline MAKE_ATTR_UNUSED char ch_tolower(char ch) 698static inline MAKE_ATTR_UNUSED char ch_tolower(char ch)
699{ return (char)tolower((unsigned char)ch); } 699{ return (char)tolower((unsigned char)ch); }
700static inline MAKE_ATTR_UNUSED char ch_toupper(char ch) 700static inline MAKE_ATTR_UNUSED char ch_toupper(char ch)
701{ return (char)toupper((unsigned char)ch); } 701{ return (char)toupper((unsigned char)ch); }
702 702
703static inline MAKE_ATTR_UNUSED void 703static inline MAKE_ATTR_UNUSED void
704cpp_skip_whitespace(const char **pp) 704cpp_skip_whitespace(const char **pp)
705{ 705{
706 while (ch_isspace(**pp)) 706 while (ch_isspace(**pp))
707 (*pp)++; 707 (*pp)++;
708} 708}
709 709
710static inline MAKE_ATTR_UNUSED void 710static inline MAKE_ATTR_UNUSED void
711pp_skip_whitespace(char **pp) 711pp_skip_whitespace(char **pp)
712{ 712{
713 while (ch_isspace(**pp)) 713 while (ch_isspace(**pp))
714 (*pp)++; 714 (*pp)++;
715} 715}
716 716
717#ifdef MAKE_NATIVE 717#ifdef MAKE_NATIVE
718# include <sys/cdefs.h> 718# include <sys/cdefs.h>
719# ifndef lint 719# ifndef lint
720# define MAKE_RCSID(id) __RCSID(id) 720# define MAKE_RCSID(id) __RCSID(id)
721# endif 721# endif
722#else 722#else
723# define MAKE_RCSID(id) static volatile char rcsid[] = id 723# define MAKE_RCSID(id) static volatile char rcsid[] = id
724#endif 724#endif
725 725
726#endif /* MAKE_MAKE_H */ 726#endif /* MAKE_MAKE_H */