Annotation of src/usr.bin/make/main.c, Revision 1.169
1.169 ! perry 1: /* $NetBSD: main.c,v 1.168 2009/03/18 22:02:49 christos Exp $ */
1.19 christos 2:
1.1 cgd 3: /*
1.31 christos 4: * Copyright (c) 1988, 1989, 1990, 1993
5: * The Regents of the University of California. All rights reserved.
1.91 agc 6: *
7: * This code is derived from software contributed to Berkeley by
8: * Adam de Boor.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
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
20: * without specific prior written permission.
21: *
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
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
32: * SUCH DAMAGE.
33: */
34:
35: /*
1.1 cgd 36: * Copyright (c) 1989 by Berkeley Softworks
37: * All rights reserved.
38: *
39: * This code is derived from software contributed to Berkeley by
40: * Adam de Boor.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. All advertising materials mentioning features or use of this software
51: * must display the following acknowledgement:
52: * This product includes software developed by the University of
53: * California, Berkeley and 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
56: * without specific prior written permission.
57: *
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
60: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
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
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
68: * SUCH DAMAGE.
69: */
70:
1.102 ross 71: #ifndef MAKE_NATIVE
1.169 ! perry 72: static char rcsid[] = "$NetBSD: main.c,v 1.168 2009/03/18 22:02:49 christos Exp $";
1.38 lukem 73: #else
1.37 christos 74: #include <sys/cdefs.h>
1.1 cgd 75: #ifndef lint
1.150 lukem 76: __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
77: The Regents of the University of California. All rights reserved.");
1.1 cgd 78: #endif /* not lint */
79:
80: #ifndef lint
1.19 christos 81: #if 0
1.31 christos 82: static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
1.19 christos 83: #else
1.169 ! perry 84: __RCSID("$NetBSD: main.c,v 1.168 2009/03/18 22:02:49 christos Exp $");
1.19 christos 85: #endif
1.1 cgd 86: #endif /* not lint */
1.38 lukem 87: #endif
1.1 cgd 88:
89: /*-
90: * main.c --
91: * The main file for this entire program. Exit routines etc
92: * reside here.
93: *
94: * Utility functions defined in this file:
95: * Main_ParseArgLine Takes a line of arguments, breaks them and
96: * treats them as if they were given when first
97: * invoked. Used by the parse module to implement
98: * the .MFLAGS target.
99: *
100: * Error Print a tagged error message. The global
101: * MAKE variable must have been defined. This
102: * takes a format string and two optional
103: * arguments for it.
104: *
105: * Fatal Print an error message and exit. Also takes
106: * a format string and two arguments.
107: *
108: * Punt Aborts all jobs and exits with a message. Also
109: * takes a format string and two arguments.
110: *
111: * Finish Finish things up by printing the number of
1.72 wiz 112: * errors which occurred, as passed to it, and
1.1 cgd 113: * exiting.
114: */
115:
1.13 cgd 116: #include <sys/types.h>
117: #include <sys/time.h>
1.1 cgd 118: #include <sys/param.h>
1.13 cgd 119: #include <sys/resource.h>
1.21 christos 120: #include <sys/signal.h>
1.1 cgd 121: #include <sys/stat.h>
1.102 ross 122: #ifdef MAKE_NATIVE
1.17 gwr 123: #include <sys/utsname.h>
1.31 christos 124: #endif
1.29 christos 125: #include <sys/wait.h>
1.85 wiz 126:
1.1 cgd 127: #include <errno.h>
128: #include <fcntl.h>
1.85 wiz 129: #include <stdarg.h>
1.1 cgd 130: #include <stdio.h>
1.32 christos 131: #include <stdlib.h>
1.42 kleink 132: #include <time.h>
1.85 wiz 133:
1.1 cgd 134: #include "make.h"
1.13 cgd 135: #include "hash.h"
136: #include "dir.h"
137: #include "job.h"
1.1 cgd 138: #include "pathnames.h"
1.58 sommerfe 139: #include "trace.h"
1.1 cgd 140:
1.66 christos 141: #ifdef USE_IOVEC
142: #include <sys/uio.h>
143: #endif
144:
1.1 cgd 145: #ifndef DEFMAXLOCAL
146: #define DEFMAXLOCAL DEFMAXJOBS
1.24 christos 147: #endif /* DEFMAXLOCAL */
1.1 cgd 148:
149: Lst create; /* Targets to be made */
150: time_t now; /* Time at start of make */
151: GNode *DEFAULT; /* .DEFAULT node */
152: Boolean allPrecious; /* .PRECIOUS given on line by itself */
153:
154: static Boolean noBuiltins; /* -r flag */
155: static Lst makefiles; /* ordered list of makefiles to read */
1.31 christos 156: static Boolean printVars; /* print value of one or more vars */
157: static Lst variables; /* list of variables to print */
1.21 christos 158: int maxJobs; /* -j argument */
1.132 dsl 159: static int maxJobTokens; /* -j argument */
1.13 cgd 160: Boolean compatMake; /* -B argument */
1.113 christos 161: int debug; /* -d argument */
1.1 cgd 162: Boolean noExecute; /* -n flag */
1.61 sommerfe 163: Boolean noRecursiveExecute; /* -N flag */
1.1 cgd 164: Boolean keepgoing; /* -k flag */
165: Boolean queryFlag; /* -q flag */
166: Boolean touchFlag; /* -t flag */
167: Boolean ignoreErrors; /* -i flag */
168: Boolean beSilent; /* -s flag */
169: Boolean oldVars; /* variable substitution style */
170: Boolean checkEnvFirst; /* -e flag */
1.63 christos 171: Boolean parseWarnFatal; /* -W flag */
1.58 sommerfe 172: Boolean jobServer; /* -J flag */
1.132 dsl 173: static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
1.87 thorpej 174: Boolean varNoExportEnv; /* -X flag */
1.145 dsl 175: Boolean doing_depend; /* Set while reading .depend */
1.1 cgd 176: static Boolean jobsRunning; /* TRUE if the jobs might be running */
1.58 sommerfe 177: static const char * tracefile;
1.149 christos 178: static char * Check_Cwd_av(int, char **, int);
179: static void MainParseArgs(int, char **);
1.165 dsl 180: static int ReadMakefile(const void *, const void *);
1.85 wiz 181: static void usage(void);
1.1 cgd 182:
1.74 tv 183: static char curdir[MAXPATHLEN + 1]; /* startup directory */
184: static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
1.63 christos 185: char *progname; /* the program name */
1.1 cgd 186:
1.58 sommerfe 187: Boolean forceJobs = FALSE;
188:
1.63 christos 189: extern Lst parseIncPath;
190:
1.133 dsl 191: static void
192: parse_debug_options(const char *argvalue)
193: {
194: const char *modules;
1.136 dsl 195: const char *mode;
196: char *fname;
1.149 christos 197: int len;
1.133 dsl 198:
199: for (modules = argvalue; *modules; ++modules) {
200: switch (*modules) {
201: case 'A':
202: debug = ~0;
203: break;
204: case 'a':
205: debug |= DEBUG_ARCH;
206: break;
1.155 christos 207: case 'C':
208: debug |= DEBUG_CWD;
209: break;
1.133 dsl 210: case 'c':
211: debug |= DEBUG_COND;
212: break;
213: case 'd':
214: debug |= DEBUG_DIR;
215: break;
216: case 'e':
217: debug |= DEBUG_ERROR;
218: break;
219: case 'f':
220: debug |= DEBUG_FOR;
221: break;
222: case 'g':
223: if (modules[1] == '1') {
224: debug |= DEBUG_GRAPH1;
225: ++modules;
226: }
227: else if (modules[1] == '2') {
228: debug |= DEBUG_GRAPH2;
229: ++modules;
230: }
231: else if (modules[1] == '3') {
232: debug |= DEBUG_GRAPH3;
233: ++modules;
234: }
235: break;
236: case 'j':
237: debug |= DEBUG_JOB;
238: break;
1.146 sjg 239: case 'l':
240: debug |= DEBUG_LOUD;
241: break;
1.133 dsl 242: case 'm':
243: debug |= DEBUG_MAKE;
244: break;
245: case 'n':
246: debug |= DEBUG_SCRIPT;
247: break;
248: case 'p':
249: debug |= DEBUG_PARSE;
250: break;
251: case 's':
252: debug |= DEBUG_SUFF;
253: break;
254: case 't':
255: debug |= DEBUG_TARG;
256: break;
257: case 'v':
258: debug |= DEBUG_VAR;
259: break;
260: case 'x':
261: debug |= DEBUG_SHELL;
262: break;
263: case 'F':
264: if (debug_file != stdout && debug_file != stderr)
265: fclose(debug_file);
266: if (*++modules == '+')
1.136 dsl 267: mode = "a";
1.153 apb 268: else
1.136 dsl 269: mode = "w";
1.153 apb 270: if (strcmp(modules, "stdout") == 0) {
1.152 apb 271: debug_file = stdout;
1.153 apb 272: goto debug_setbuf;
1.152 apb 273: }
1.153 apb 274: if (strcmp(modules, "stderr") == 0) {
1.152 apb 275: debug_file = stderr;
1.153 apb 276: goto debug_setbuf;
1.152 apb 277: }
1.136 dsl 278: len = strlen(modules);
279: fname = malloc(len + 20);
280: memcpy(fname, modules, len + 1);
281: /* Let the filename be modified by the pid */
282: if (strcmp(fname + len - 3, ".%d") == 0)
1.149 christos 283: snprintf(fname + len - 2, 20, "%d", getpid());
1.136 dsl 284: debug_file = fopen(fname, mode);
1.133 dsl 285: if (!debug_file) {
1.139 dsl 286: fprintf(stderr, "Cannot open debug file %s\n",
1.136 dsl 287: fname);
1.133 dsl 288: usage();
289: }
1.136 dsl 290: free(fname);
1.153 apb 291: goto debug_setbuf;
1.133 dsl 292: default:
293: (void)fprintf(stderr,
294: "%s: illegal argument to d option -- %c\n",
295: progname, *modules);
296: usage();
297: }
298: }
1.153 apb 299: debug_setbuf:
300: /*
301: * Make the debug_file unbuffered, and make
302: * stdout line buffered (unless debugfile == stdout).
303: */
304: setvbuf(debug_file, NULL, _IONBF, 0);
305: if (debug_file != stdout) {
306: setvbuf(stdout, NULL, _IOLBF, 0);
307: }
1.133 dsl 308: }
309:
1.1 cgd 310: /*-
311: * MainParseArgs --
312: * Parse a given argument vector. Called from main() and from
313: * Main_ParseArgLine() when the .MAKEFLAGS target is used.
314: *
315: * XXX: Deal with command line overriding .MAKEFLAGS in makefile
316: *
317: * Results:
318: * None
319: *
320: * Side Effects:
321: * Various global and local flags will be set depending on the flags
322: * given
323: */
324: static void
1.149 christos 325: MainParseArgs(int argc, char **argv)
1.1 cgd 326: {
1.47 hubertf 327: char *p;
1.122 christos 328: int c = '?';
1.98 ross 329: int arginc;
1.133 dsl 330: char *argvalue;
1.98 ross 331: const char *getopt_def;
332: char *optscan;
1.101 ross 333: Boolean inOption, dashDash = FALSE;
1.97 chuck 334: char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
1.1 cgd 335:
1.131 dsl 336: #define OPTFLAGS "BD:I:J:NST:V:WXd:ef:ij:km:nqrst"
1.98 ross 337: /* Can't actually use getopt(3) because rescanning is not portable */
338:
339: getopt_def = OPTFLAGS;
340: rearg:
341: inOption = FALSE;
1.108 lukem 342: optscan = NULL;
1.98 ross 343: while(argc > 1) {
344: char *getopt_spec;
345: if(!inOption)
346: optscan = argv[1];
347: c = *optscan++;
348: arginc = 0;
349: if(inOption) {
350: if(c == '\0') {
351: ++argv;
352: --argc;
353: inOption = FALSE;
354: continue;
355: }
356: } else {
1.101 ross 357: if (c != '-' || dashDash)
1.98 ross 358: break;
359: inOption = TRUE;
360: c = *optscan++;
361: }
362: /* '-' found at some earlier point */
363: getopt_spec = strchr(getopt_def, c);
364: if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
365: /* -<something> found, and <something> should have an arg */
366: inOption = FALSE;
367: arginc = 1;
368: argvalue = optscan;
369: if(*argvalue == '\0') {
1.122 christos 370: if (argc < 3)
371: goto noarg;
1.98 ross 372: argvalue = argv[2];
373: arginc = 2;
374: }
1.108 lukem 375: } else {
376: argvalue = NULL;
1.98 ross 377: }
1.1 cgd 378: switch(c) {
1.98 ross 379: case '\0':
380: arginc = 1;
381: inOption = FALSE;
382: break;
1.92 sjg 383: case 'B':
384: compatMake = TRUE;
385: Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
386: break;
1.1 cgd 387: case 'D':
1.156 dsl 388: if (argvalue == NULL || argvalue[0] == 0) goto noarg;
1.122 christos 389: Var_Set(argvalue, "1", VAR_GLOBAL, 0);
1.1 cgd 390: Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
1.122 christos 391: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.1 cgd 392: break;
393: case 'I':
1.122 christos 394: if (argvalue == NULL) goto noarg;
395: Parse_AddIncludeDir(argvalue);
1.1 cgd 396: Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
1.122 christos 397: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.1 cgd 398: break;
1.58 sommerfe 399: case 'J':
1.122 christos 400: if (argvalue == NULL) goto noarg;
1.132 dsl 401: if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) {
1.63 christos 402: (void)fprintf(stderr,
1.132 dsl 403: "%s: internal error -- J option malformed (%s)\n",
1.122 christos 404: progname, argvalue);
1.58 sommerfe 405: usage();
406: }
1.132 dsl 407: if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
408: (fcntl(jp_1, F_GETFD, 0) < 0)) {
1.61 sommerfe 409: #if 0
1.58 sommerfe 410: (void)fprintf(stderr,
1.121 dsl 411: "%s: ###### warning -- J descriptors were closed!\n",
1.63 christos 412: progname);
1.118 dsl 413: exit(2);
1.61 sommerfe 414: #endif
1.132 dsl 415: jp_0 = -1;
416: jp_1 = -1;
1.61 sommerfe 417: compatMake = TRUE;
1.58 sommerfe 418: } else {
419: Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
1.122 christos 420: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.58 sommerfe 421: jobServer = TRUE;
422: }
423: break;
1.61 sommerfe 424: case 'N':
425: noExecute = TRUE;
426: noRecursiveExecute = TRUE;
427: Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
428: break;
1.1 cgd 429: case 'S':
430: keepgoing = FALSE;
431: Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
432: break;
1.58 sommerfe 433: case 'T':
1.122 christos 434: if (argvalue == NULL) goto noarg;
1.151 joerg 435: tracefile = bmake_strdup(argvalue);
1.58 sommerfe 436: Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
1.122 christos 437: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.58 sommerfe 438: break;
1.92 sjg 439: case 'V':
1.122 christos 440: if (argvalue == NULL) goto noarg;
1.92 sjg 441: printVars = TRUE;
1.134 dsl 442: (void)Lst_AtEnd(variables, argvalue);
1.92 sjg 443: Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
1.122 christos 444: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.92 sjg 445: break;
1.63 christos 446: case 'W':
447: parseWarnFatal = TRUE;
1.87 thorpej 448: break;
449: case 'X':
450: varNoExportEnv = TRUE;
451: Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
1.63 christos 452: break;
1.133 dsl 453: case 'd':
1.122 christos 454: if (argvalue == NULL) goto noarg;
1.133 dsl 455: /* If '-d-opts' don't pass to children */
456: if (argvalue[0] == '-')
457: argvalue++;
458: else {
459: Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
460: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
461: }
462: parse_debug_options(argvalue);
1.1 cgd 463: break;
464: case 'e':
465: checkEnvFirst = TRUE;
466: Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
467: break;
468: case 'f':
1.122 christos 469: if (argvalue == NULL) goto noarg;
1.134 dsl 470: (void)Lst_AtEnd(makefiles, argvalue);
1.1 cgd 471: break;
472: case 'i':
473: ignoreErrors = TRUE;
474: Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
475: break;
476: case 'j':
1.122 christos 477: if (argvalue == NULL) goto noarg;
1.22 christos 478: forceJobs = TRUE;
1.122 christos 479: maxJobs = strtol(argvalue, &p, 0);
1.47 hubertf 480: if (*p != '\0' || maxJobs < 1) {
1.112 christos 481: (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
1.63 christos 482: progname);
1.46 hubertf 483: exit(1);
484: }
1.9 jtc 485: Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
1.122 christos 486: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.123 dsl 487: maxJobTokens = maxJobs;
1.1 cgd 488: break;
489: case 'k':
490: keepgoing = TRUE;
491: Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
492: break;
1.25 christos 493: case 'm':
1.122 christos 494: if (argvalue == NULL) goto noarg;
1.97 chuck 495: /* look for magic parent directory search string */
1.122 christos 496: if (strncmp(".../", argvalue, 4) == 0) {
497: if (!Dir_FindHereOrAbove(curdir, argvalue+4,
1.97 chuck 498: found_path, sizeof(found_path)))
499: break; /* nothing doing */
1.112 christos 500: (void)Dir_AddDir(sysIncPath, found_path);
1.97 chuck 501:
502: } else {
1.122 christos 503: (void)Dir_AddDir(sysIncPath, argvalue);
1.97 chuck 504: }
1.25 christos 505: Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
1.122 christos 506: Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
1.25 christos 507: break;
1.1 cgd 508: case 'n':
509: noExecute = TRUE;
510: Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
511: break;
512: case 'q':
513: queryFlag = TRUE;
514: /* Kind of nonsensical, wot? */
515: Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
516: break;
517: case 'r':
518: noBuiltins = TRUE;
519: Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
520: break;
521: case 's':
522: beSilent = TRUE;
523: Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
524: break;
525: case 't':
526: touchFlag = TRUE;
527: Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
528: break;
1.101 ross 529: case '-':
530: dashDash = TRUE;
531: break;
1.1 cgd 532: default:
533: case '?':
534: usage();
535: }
1.98 ross 536: argv += arginc;
537: argc -= arginc;
1.1 cgd 538: }
539:
540: oldVars = TRUE;
541:
542: /*
543: * See if the rest of the arguments are variable assignments and
544: * perform them if so. Else take them to be targets and stuff them
545: * on the end of the "create" list.
546: */
1.98 ross 547: for (; argc > 1; ++argv, --argc)
548: if (Parse_IsVar(argv[1])) {
549: Parse_DoVar(argv[1], VAR_CMD);
1.67 sjg 550: } else {
1.98 ross 551: if (!*argv[1])
1.1 cgd 552: Punt("illegal (null) argument.");
1.101 ross 553: if (*argv[1] == '-' && !dashDash)
1.1 cgd 554: goto rearg;
1.151 joerg 555: (void)Lst_AtEnd(create, bmake_strdup(argv[1]));
1.1 cgd 556: }
1.122 christos 557:
558: return;
559: noarg:
560: (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
561: progname, c);
562: usage();
1.1 cgd 563: }
564:
565: /*-
566: * Main_ParseArgLine --
567: * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
568: * is encountered and by main() when reading the .MAKEFLAGS envariable.
569: * Takes a line of arguments and breaks it into its
570: * component words and passes those words and the number of them to the
571: * MainParseArgs function.
572: * The line should have all its leading whitespace removed.
573: *
1.85 wiz 574: * Input:
575: * line Line to fracture
576: *
1.1 cgd 577: * Results:
578: * None
579: *
580: * Side Effects:
581: * Only those that come from the various arguments.
582: */
583: void
1.161 dsl 584: Main_ParseArgLine(const char *line)
1.1 cgd 585: {
586: char **argv; /* Manufactured argument vector */
1.149 christos 587: int argc; /* Number of arguments in argv */
1.40 christos 588: char *args; /* Space used by the args */
589: char *buf, *p1;
590: char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
1.48 christos 591: size_t len;
1.1 cgd 592:
593: if (line == NULL)
594: return;
1.13 cgd 595: for (; *line == ' '; ++line)
596: continue;
1.1 cgd 597: if (!*line)
598: return;
599:
1.151 joerg 600: buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
1.48 christos 601: (void)snprintf(buf, len, "%s %s", argv0, line);
1.40 christos 602: if (p1)
603: free(p1);
604:
1.41 christos 605: argv = brk_string(buf, &argc, TRUE, &args);
1.159 christos 606: if (argv == NULL) {
607: Error("Unterminated quoted string [%s]", buf);
608: free(buf);
609: return;
610: }
1.45 itohy 611: free(buf);
1.1 cgd 612: MainParseArgs(argc, argv);
1.40 christos 613:
614: free(args);
615: free(argv);
1.1 cgd 616: }
617:
1.74 tv 618: Boolean
1.85 wiz 619: Main_SetObjdir(const char *path)
1.31 christos 620: {
621: struct stat sb;
1.74 tv 622: char *p = NULL;
623: char buf[MAXPATHLEN + 1];
1.76 tv 624: Boolean rc = FALSE;
1.31 christos 625:
1.74 tv 626: /* expand variable substitutions */
1.51 sjg 627: if (strchr(path, '$') != 0) {
1.74 tv 628: snprintf(buf, MAXPATHLEN, "%s", path);
629: path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
1.51 sjg 630: }
1.74 tv 631:
632: if (path[0] != '/') {
633: snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
634: path = buf;
635: }
636:
637: /* look for the directory and try to chdir there */
1.31 christos 638: if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
639: if (chdir(path)) {
640: (void)fprintf(stderr, "make warning: %s: %s.\n",
641: path, strerror(errno));
1.74 tv 642: } else {
643: strncpy(objdir, path, MAXPATHLEN);
644: Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
645: setenv("PWD", objdir, 1);
1.79 tv 646: Dir_InitDot();
1.74 tv 647: rc = TRUE;
1.31 christos 648: }
649: }
650:
1.74 tv 651: if (p)
652: free(p);
653: return rc;
1.31 christos 654: }
655:
1.124 sjg 656: /*-
657: * ReadAllMakefiles --
658: * wrapper around ReadMakefile() to read all.
659: *
660: * Results:
661: * TRUE if ok, FALSE on error
662: */
663: static int
1.165 dsl 664: ReadAllMakefiles(const void *p, const void *q)
1.124 sjg 665: {
666: return (ReadMakefile(p, q) == 0);
667: }
1.31 christos 668:
1.167 christos 669: #ifdef SIGINFO
670: /*ARGSUSED*/
671: static void
672: siginfo(int signo)
673: {
674: char dir[MAXPATHLEN];
675: char str[2 * MAXPATHLEN];
676: int len;
677: if (getcwd(dir, sizeof(dir)) == NULL)
678: return;
1.168 christos 679: len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir);
1.167 christos 680: if (len > 0)
681: (void)write(STDERR_FILENO, str, (size_t)len);
682: }
683: #endif
684:
1.1 cgd 685: /*-
686: * main --
687: * The main function, for obvious reasons. Initializes variables
688: * and a few modules, then parses the arguments give it in the
689: * environment and on the command line. Reads the system makefile
690: * followed by either Makefile, makefile or the file given by the
691: * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
692: * flags it has received by then uses either the Make or the Compat
693: * module to create the initial list of targets.
694: *
695: * Results:
696: * If -q was given, exits -1 if anything was out-of-date. Else it exits
697: * 0.
698: *
699: * Side Effects:
700: * The program exits when done. Targets are created. etc. etc. etc.
701: */
1.13 cgd 702: int
1.85 wiz 703: main(int argc, char **argv)
1.1 cgd 704: {
705: Lst targs; /* target nodes to create -- passed to Make_Init */
1.137 dsl 706: Boolean outOfDate = FALSE; /* FALSE if all targets up to date */
1.77 tv 707: struct stat sb, sa;
708: char *p1, *path, *pwd;
1.74 tv 709: char mdpath[MAXPATHLEN];
1.18 christos 710: char *machine = getenv("MACHINE");
1.89 christos 711: const char *machine_arch = getenv("MACHINE_ARCH");
1.55 sjg 712: char *syspath = getenv("MAKESYSPATH");
1.25 christos 713: Lst sysMkPath; /* Path of sys.mk */
714: char *cp = NULL, *start;
715: /* avoid faults on read-only strings */
1.55 sjg 716: static char defsyspath[] = _PATH_DEFSYSPATH;
1.97 chuck 717: char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
1.107 sjg 718: struct timeval rightnow; /* to initialize random seed */
1.119 tsutsui 719: #ifdef MAKE_NATIVE
720: struct utsname utsname;
721: #endif
1.107 sjg 722:
1.154 apb 723: /* default to writing debug to stderr */
724: debug_file = stderr;
1.133 dsl 725:
1.167 christos 726: #ifdef SIGINFO
727: (void)signal(SIGINFO, siginfo);
728: #endif
1.107 sjg 729: /*
1.158 dholland 730: * Set the seed to produce a different random sequence
1.107 sjg 731: * on each program execution.
732: */
733: gettimeofday(&rightnow, NULL);
1.149 christos 734: srandom(rightnow.tv_sec + rightnow.tv_usec);
1.55 sjg 735:
1.53 christos 736: if ((progname = strrchr(argv[0], '/')) != NULL)
737: progname++;
738: else
739: progname = argv[0];
1.21 christos 740: #ifdef RLIMIT_NOFILE
741: /*
742: * get rid of resource limit on file descriptors
743: */
744: {
745: struct rlimit rl;
746: if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
747: rl.rlim_cur != rl.rlim_max) {
748: rl.rlim_cur = rl.rlim_max;
1.112 christos 749: (void)setrlimit(RLIMIT_NOFILE, &rl);
1.21 christos 750: }
751: }
752: #endif
1.13 cgd 753: /*
754: * Find where we are and take care of PWD for the automounter...
755: * All this code is so that we know where we are when we start up
756: * on a different machine with pmake.
757: */
1.16 mycroft 758: if (getcwd(curdir, MAXPATHLEN) == NULL) {
1.63 christos 759: (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
1.13 cgd 760: exit(2);
761: }
762:
1.77 tv 763: if (stat(curdir, &sa) == -1) {
1.63 christos 764: (void)fprintf(stderr, "%s: %s: %s.\n",
765: progname, curdir, strerror(errno));
1.13 cgd 766: exit(2);
1.77 tv 767: }
768:
769: /*
770: * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
771: * since the value of curdir can very depending on how we got
772: * here. Ie sitting at a shell prompt (shell that provides $PWD)
773: * or via subdir.mk in which case its likely a shell which does
774: * not provide it.
775: * So, to stop it breaking this case only, we ignore PWD if
776: * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
777: */
778: if ((pwd = getenv("PWD")) != NULL && getenv("MAKEOBJDIRPREFIX") == NULL) {
779: const char *makeobjdir = getenv("MAKEOBJDIR");
780:
781: if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
782: if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
783: sa.st_dev == sb.st_dev)
1.112 christos 784: (void)strncpy(curdir, pwd, MAXPATHLEN);
1.77 tv 785: }
1.13 cgd 786: }
787:
1.17 gwr 788: /*
789: * Get the name of this type of MACHINE from utsname
790: * so we can share an executable for similar machines.
791: * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
792: *
1.33 christos 793: * Note that both MACHINE and MACHINE_ARCH are decided at
794: * run-time.
1.17 gwr 795: */
1.34 gwr 796: if (!machine) {
1.102 ross 797: #ifdef MAKE_NATIVE
1.23 christos 798: if (uname(&utsname) == -1) {
1.63 christos 799: (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
800: strerror(errno));
801: exit(2);
1.18 christos 802: }
803: machine = utsname.machine;
1.26 christos 804: #else
1.81 tv 805: #ifdef MAKE_MACHINE
1.80 thorpej 806: machine = MAKE_MACHINE;
1.81 tv 807: #else
808: machine = "unknown";
809: #endif
1.26 christos 810: #endif
1.17 gwr 811: }
1.1 cgd 812:
1.33 christos 813: if (!machine_arch) {
814: #ifndef MACHINE_ARCH
1.80 thorpej 815: #ifdef MAKE_MACHINE_ARCH
816: machine_arch = MAKE_MACHINE_ARCH;
1.43 wsanchez 817: #else
1.81 tv 818: machine_arch = "unknown";
1.43 wsanchez 819: #endif
1.33 christos 820: #else
821: machine_arch = MACHINE_ARCH;
822: #endif
823: }
824:
1.1 cgd 825: /*
1.51 sjg 826: * Just in case MAKEOBJDIR wants us to do something tricky.
827: */
828: Var_Init(); /* Initialize the lists of variables for
829: * parsing arguments */
1.71 sjg 830: Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
831: Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
832: Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
833: Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
1.51 sjg 834:
835: /*
1.74 tv 836: * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that,
837: * MAKEOBJDIR is set in the environment, try only that value
838: * and fall back to .CURDIR if it does not exist.
1.111 lukem 839: *
840: * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
841: * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
842: * of these paths exist, just use .CURDIR.
1.74 tv 843: */
1.79 tv 844: Dir_Init(curdir);
1.112 christos 845: (void)Main_SetObjdir(curdir);
1.79 tv 846:
1.74 tv 847: if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
1.112 christos 848: (void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
849: (void)Main_SetObjdir(mdpath);
1.74 tv 850: } else if ((path = getenv("MAKEOBJDIR")) != NULL) {
1.112 christos 851: (void)Main_SetObjdir(path);
1.111 lukem 852: } else {
1.112 christos 853: (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
1.111 lukem 854: if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
1.112 christos 855: (void)snprintf(mdpath, MAXPATHLEN, "%s%s",
1.111 lukem 856: _PATH_OBJDIRPREFIX, curdir);
1.112 christos 857: (void)Main_SetObjdir(mdpath);
1.111 lukem 858: }
1.4 cgd 859: }
1.13 cgd 860:
1.1 cgd 861: create = Lst_Init(FALSE);
862: makefiles = Lst_Init(FALSE);
1.31 christos 863: printVars = FALSE;
864: variables = Lst_Init(FALSE);
1.1 cgd 865: beSilent = FALSE; /* Print commands as executed */
866: ignoreErrors = FALSE; /* Pay attention to non-zero returns */
867: noExecute = FALSE; /* Execute all commands */
1.61 sommerfe 868: noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
1.1 cgd 869: keepgoing = FALSE; /* Stop on error */
870: allPrecious = FALSE; /* Remove targets when interrupted */
871: queryFlag = FALSE; /* This is not just a check-run */
872: noBuiltins = FALSE; /* Read the built-in rules */
873: touchFlag = FALSE; /* Actually update targets */
874: debug = 0; /* No debug verbosity, please. */
875: jobsRunning = FALSE;
876:
1.121 dsl 877: maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */
1.123 dsl 878: maxJobTokens = maxJobs;
1.21 christos 879: compatMake = FALSE; /* No compat mode */
1.31 christos 880:
1.13 cgd 881:
1.1 cgd 882: /*
883: * Initialize the parsing, directory and variable modules to prepare
884: * for the reading of inclusion paths and variable settings on the
885: * command line
886: */
1.36 gwr 887:
888: /*
1.1 cgd 889: * Initialize various variables.
890: * MAKE also gets this name, for compatibility
891: * .MAKEFLAGS gets set to the empty string just in case.
892: * MFLAGS also gets initialized empty, for compatibility.
893: */
1.79 tv 894: Parse_Init();
1.71 sjg 895: Var_Set("MAKE", argv[0], VAR_GLOBAL, 0);
896: Var_Set(".MAKE", argv[0], VAR_GLOBAL, 0);
897: Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
898: Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
899: Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
1.78 tv 900: Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
1.1 cgd 901:
902: /*
1.142 sjg 903: * Set some other useful macros
904: */
905: {
906: char tmp[64];
907:
1.149 christos 908: snprintf(tmp, sizeof(tmp), "%u", getpid());
1.142 sjg 909: Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
1.149 christos 910: snprintf(tmp, sizeof(tmp), "%u", getppid());
1.142 sjg 911: Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
912: }
913: Job_SetPrefix();
914:
915: /*
1.1 cgd 916: * First snag any flags out of the MAKE environment variable.
917: * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
918: * in a different format).
919: */
920: #ifdef POSIX
921: Main_ParseArgLine(getenv("MAKEFLAGS"));
922: #else
923: Main_ParseArgLine(getenv("MAKE"));
924: #endif
1.31 christos 925:
1.149 christos 926: MainParseArgs(argc, argv);
1.1 cgd 927:
928: /*
1.58 sommerfe 929: * Be compatible if user did not specify -j and did not explicitly
930: * turned compatibility on
931: */
932: if (!compatMake && !forceJobs) {
933: compatMake = TRUE;
934: }
935:
936: /*
1.1 cgd 937: * Initialize archive, target and suffix modules in preparation for
938: * parsing the makefile(s)
939: */
940: Arch_Init();
941: Targ_Init();
942: Suff_Init();
1.58 sommerfe 943: Trace_Init(tracefile);
1.1 cgd 944:
1.157 dsl 945: DEFAULT = NULL;
1.1 cgd 946: (void)time(&now);
947:
1.58 sommerfe 948: Trace_Log(MAKESTART, NULL);
949:
1.1 cgd 950: /*
951: * Set up the .TARGETS variable to contain the list of targets to be
952: * created. If none specified, make the variable empty -- the parser
953: * will fill the thing in with the default or .MAIN target.
954: */
955: if (!Lst_IsEmpty(create)) {
956: LstNode ln;
957:
1.157 dsl 958: for (ln = Lst_First(create); ln != NULL;
1.1 cgd 959: ln = Lst_Succ(ln)) {
960: char *name = (char *)Lst_Datum(ln);
961:
962: Var_Append(".TARGETS", name, VAR_GLOBAL);
963: }
964: } else
1.71 sjg 965: Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
1.1 cgd 966:
1.25 christos 967:
1.1 cgd 968: /*
1.25 christos 969: * If no user-supplied system path was given (through the -m option)
970: * add the directories from the DEFSYSPATH (more than one may be given
971: * as dir1:...:dirn) to the system include path.
1.1 cgd 972: */
1.73 tv 973: if (syspath == NULL || *syspath == '\0')
974: syspath = defsyspath;
975: else
1.151 joerg 976: syspath = bmake_strdup(syspath);
1.73 tv 977:
978: for (start = syspath; *start != '\0'; start = cp) {
979: for (cp = start; *cp != '\0' && *cp != ':'; cp++)
980: continue;
1.97 chuck 981: if (*cp == ':') {
982: *cp++ = '\0';
983: }
984: /* look for magic parent directory search string */
985: if (strncmp(".../", start, 4) != 0) {
1.112 christos 986: (void)Dir_AddDir(defIncPath, start);
1.73 tv 987: } else {
1.97 chuck 988: if (Dir_FindHereOrAbove(curdir, start+4,
989: found_path, sizeof(found_path))) {
1.112 christos 990: (void)Dir_AddDir(defIncPath, found_path);
1.97 chuck 991: }
1.25 christos 992: }
993: }
1.73 tv 994: if (syspath != defsyspath)
995: free(syspath);
1.25 christos 996:
997: /*
998: * Read in the built-in rules first, followed by the specified
1.115 christos 999: * makefile, if it was (makefile != NULL), or the default
1.99 fair 1000: * makefile and Makefile, in that order, if it wasn't.
1.25 christos 1001: */
1002: if (!noBuiltins) {
1003: LstNode ln;
1004:
1.106 christos 1005: sysMkPath = Lst_Init(FALSE);
1.73 tv 1006: Dir_Expand(_PATH_DEFSYSMK,
1007: Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
1008: sysMkPath);
1.25 christos 1009: if (Lst_IsEmpty(sysMkPath))
1.63 christos 1010: Fatal("%s: no system rules (%s).", progname,
1011: _PATH_DEFSYSMK);
1.134 dsl 1012: ln = Lst_Find(sysMkPath, NULL, ReadMakefile);
1.157 dsl 1013: if (ln == NULL)
1.63 christos 1014: Fatal("%s: cannot open %s.", progname,
1015: (char *)Lst_Datum(ln));
1.25 christos 1016: }
1.1 cgd 1017:
1018: if (!Lst_IsEmpty(makefiles)) {
1019: LstNode ln;
1020:
1.134 dsl 1021: ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
1.157 dsl 1022: if (ln != NULL)
1.63 christos 1023: Fatal("%s: cannot open %s.", progname,
1024: (char *)Lst_Datum(ln));
1.165 dsl 1025: } else if (ReadMakefile("makefile", NULL) != 0)
1026: (void)ReadMakefile("Makefile", NULL);
1.1 cgd 1027:
1.138 dsl 1028: /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1.145 dsl 1029: if (!noBuiltins || !printVars) {
1030: doing_depend = TRUE;
1.165 dsl 1031: (void)ReadMakefile(".depend", NULL);
1.145 dsl 1032: doing_depend = FALSE;
1033: }
1.1 cgd 1034:
1.14 jtc 1035: Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
1036: if (p1)
1037: free(p1);
1.1 cgd 1038:
1.132 dsl 1039: if (!compatMake)
1040: Job_ServerStart(maxJobTokens, jp_0, jp_1);
1.58 sommerfe 1041: if (DEBUG(JOB))
1.133 dsl 1042: fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1.132 dsl 1043: jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
1.58 sommerfe 1044:
1.73 tv 1045: Main_ExportMAKEFLAGS(TRUE); /* initial export */
1.1 cgd 1046:
1.54 sjg 1047: Check_Cwd_av(0, NULL, 0); /* initialize it */
1048:
1049:
1.1 cgd 1050: /*
1051: * For compatibility, look at the directories in the VPATH variable
1052: * and add them to the search path, if the variable is defined. The
1053: * variable's value is in the same format as the PATH envariable, i.e.
1054: * <directory>:<directory>:<directory>...
1055: */
1056: if (Var_Exists("VPATH", VAR_CMD)) {
1.82 reinoud 1057: char *vpath, savec;
1.1 cgd 1058: /*
1059: * GCC stores string constants in read-only memory, but
1060: * Var_Subst will want to write this thing, so store it
1061: * in an array
1062: */
1063: static char VPATH[] = "${VPATH}";
1064:
1.13 cgd 1065: vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
1.1 cgd 1066: path = vpath;
1067: do {
1068: /* skip to end of directory */
1.13 cgd 1069: for (cp = path; *cp != ':' && *cp != '\0'; cp++)
1070: continue;
1.1 cgd 1071: /* Save terminator character so know when to stop */
1072: savec = *cp;
1073: *cp = '\0';
1074: /* Add directory to search path */
1.112 christos 1075: (void)Dir_AddDir(dirSearchPath, path);
1.1 cgd 1076: *cp = savec;
1077: path = cp + 1;
1078: } while (savec == ':');
1.114 christos 1079: free(vpath);
1.1 cgd 1080: }
1081:
1082: /*
1083: * Now that all search paths have been read for suffixes et al, it's
1084: * time to add the default search path to their lists...
1085: */
1086: Suff_DoPaths();
1.50 mycroft 1087:
1088: /*
1089: * Propagate attributes through :: dependency lists.
1090: */
1091: Targ_Propagate();
1.1 cgd 1092:
1093: /* print the initial graph, if the user requested it */
1094: if (DEBUG(GRAPH1))
1095: Targ_PrintGraph(1);
1096:
1.31 christos 1097: /* print the values of any variables requested by the user */
1098: if (printVars) {
1099: LstNode ln;
1100:
1.157 dsl 1101: for (ln = Lst_First(variables); ln != NULL;
1.31 christos 1102: ln = Lst_Succ(ln)) {
1.92 sjg 1103: char *var = (char *)Lst_Datum(ln);
1104: char *value;
1105:
1106: if (strchr(var, '$')) {
1107: value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
1108: } else {
1109: value = Var_Value(var, VAR_GLOBAL, &p1);
1110: }
1.31 christos 1111: printf("%s\n", value ? value : "");
1112: if (p1)
1113: free(p1);
1114: }
1.138 dsl 1115: } else {
1.1 cgd 1116: /*
1.138 dsl 1117: * Have now read the entire graph and need to make a list of
1118: * targets to create. If none was given on the command line,
1119: * we consult the parsing module to find the main target(s)
1120: * to create.
1.1 cgd 1121: */
1.138 dsl 1122: if (Lst_IsEmpty(create))
1123: targs = Parse_MainName();
1124: else
1125: targs = Targ_FindList(create, TARG_CREATE);
1126:
1127: if (!compatMake) {
1128: /*
1129: * Initialize job module before traversing the graph
1130: * now that any .BEGIN and .END targets have been read.
1131: * This is done only if the -q flag wasn't given
1132: * (to prevent the .BEGIN from being executed should
1133: * it exist).
1134: */
1135: if (!queryFlag) {
1136: Job_Init();
1137: jobsRunning = TRUE;
1138: }
1139:
1140: /* Traverse the graph, checking on all the targets */
1141: outOfDate = Make_Run(targs);
1142: } else {
1143: /*
1144: * Compat_Init will take care of creating all the
1145: * targets as well as initializing the module.
1146: */
1147: Compat_Run(targs);
1.1 cgd 1148: }
1.31 christos 1149: }
1150:
1.49 mycroft 1151: #ifdef CLEANUP
1.157 dsl 1152: Lst_Destroy(targs, NULL);
1153: Lst_Destroy(variables, NULL);
1154: Lst_Destroy(makefiles, NULL);
1.116 christos 1155: Lst_Destroy(create, (FreeProc *)free);
1.49 mycroft 1156: #endif
1.14 jtc 1157:
1.1 cgd 1158: /* print the graph now it's been processed if the user requested it */
1159: if (DEBUG(GRAPH2))
1160: Targ_PrintGraph(2);
1161:
1.58 sommerfe 1162: Trace_Log(MAKEEND, 0);
1163:
1.14 jtc 1164: Suff_End();
1165: Targ_End();
1166: Arch_End();
1167: Var_End();
1168: Parse_End();
1169: Dir_End();
1.40 christos 1170: Job_End();
1.58 sommerfe 1171: Trace_End();
1.14 jtc 1172:
1.137 dsl 1173: return outOfDate ? 1 : 0;
1.1 cgd 1174: }
1175:
1176: /*-
1177: * ReadMakefile --
1178: * Open and parse the given makefile.
1179: *
1180: * Results:
1.124 sjg 1181: * 0 if ok. -1 if couldn't open file.
1.1 cgd 1182: *
1183: * Side Effects:
1184: * lots
1185: */
1.124 sjg 1186: static int
1.165 dsl 1187: ReadMakefile(const void *p, const void *q __unused)
1.1 cgd 1188: {
1.165 dsl 1189: const char *fname = p; /* makefile to read */
1.140 dsl 1190: int fd;
1.48 christos 1191: size_t len = MAXPATHLEN;
1.151 joerg 1192: char *name, *path = bmake_malloc(len);
1.67 sjg 1193: int setMAKEFILE;
1.1 cgd 1194:
1195: if (!strcmp(fname, "-")) {
1.140 dsl 1196: Parse_File("(stdin)", dup(fileno(stdin)));
1.71 sjg 1197: Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
1.1 cgd 1198: } else {
1.67 sjg 1199: setMAKEFILE = strcmp(fname, ".depend");
1200:
1.1 cgd 1201: /* if we've chdir'd, rebuild the path name */
1.74 tv 1202: if (strcmp(curdir, objdir) && *fname != '/') {
1.48 christos 1203: size_t plen = strlen(curdir) + strlen(fname) + 2;
1204: if (len < plen)
1.151 joerg 1205: path = bmake_realloc(path, len = 2 * plen);
1.48 christos 1206:
1207: (void)snprintf(path, len, "%s/%s", curdir, fname);
1.140 dsl 1208: fd = open(path, O_RDONLY);
1209: if (fd != -1) {
1.1 cgd 1210: fname = path;
1211: goto found;
1212: }
1.95 jmc 1213:
1214: /* If curdir failed, try objdir (ala .depend) */
1215: plen = strlen(objdir) + strlen(fname) + 2;
1216: if (len < plen)
1.151 joerg 1217: path = bmake_realloc(path, len = 2 * plen);
1.95 jmc 1218: (void)snprintf(path, len, "%s/%s", objdir, fname);
1.140 dsl 1219: fd = open(path, O_RDONLY);
1220: if (fd != -1) {
1.95 jmc 1221: fname = path;
1222: goto found;
1223: }
1.140 dsl 1224: } else {
1225: fd = open(fname, O_RDONLY);
1226: if (fd != -1)
1227: goto found;
1228: }
1.1 cgd 1229: /* look in -I and system include directories. */
1230: name = Dir_FindFile(fname, parseIncPath);
1231: if (!name)
1.73 tv 1232: name = Dir_FindFile(fname,
1233: Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1.140 dsl 1234: if (!name || (fd = open(name, O_RDONLY)) == -1) {
1.126 christos 1235: if (name)
1236: free(name);
1.48 christos 1237: free(path);
1.124 sjg 1238: return(-1);
1.48 christos 1239: }
1.1 cgd 1240: fname = name;
1241: /*
1242: * set the MAKEFILE variable desired by System V fans -- the
1243: * placement of the setting here means it gets set to the last
1244: * makefile specified, as it is set by SysV make.
1245: */
1.67 sjg 1246: found:
1247: if (setMAKEFILE)
1.71 sjg 1248: Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
1.140 dsl 1249: Parse_File(fname, fd);
1.1 cgd 1250: }
1.48 christos 1251: free(path);
1.124 sjg 1252: return(0);
1.54 sjg 1253: }
1254:
1255:
1256: /*
1257: * If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR
1258: * in situations that would not arrise with ./obj (links or not).
1259: * This tends to break things like:
1260: *
1261: * build:
1262: * ${MAKE} includes
1263: *
1264: * This function spots when ${.MAKE:T} or ${.MAKE} is a command (as
1265: * opposed to an argument) in a command line and if so returns
1266: * ${.CURDIR} so caller can chdir() so that the assumptions made by
1267: * the Makefile hold true.
1268: *
1269: * If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped.
1270: *
1271: * The chdir() only happens in the child process, and does nothing if
1272: * MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it
1273: * should not break anything. Also if NOCHECKMAKECHDIR is set we
1274: * do nothing - to ensure historic semantics can be retained.
1275: */
1276: static int Check_Cwd_Off = 0;
1277:
1278: static char *
1.149 christos 1279: Check_Cwd_av(int ac, char **av, int copy)
1.54 sjg 1280: {
1281: static char *make[4];
1.82 reinoud 1282: static char *cur_dir = NULL;
1.89 christos 1283: char **mp;
1284: char *cp;
1.54 sjg 1285: int is_cmd, next_cmd;
1286: int i;
1287: int n;
1288:
1.155 christos 1289: if (Check_Cwd_Off) {
1290: if (DEBUG(CWD))
1291: fprintf(debug_file, "check_cwd: check is off.\n");
1.54 sjg 1292: return NULL;
1.155 christos 1293: }
1.54 sjg 1294:
1295: if (make[0] == NULL) {
1296: if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) {
1297: Check_Cwd_Off = 1;
1.155 christos 1298: if (DEBUG(CWD))
1299: fprintf(debug_file, "check_cwd: turning check off.\n");
1.54 sjg 1300: return NULL;
1301: }
1302:
1303: make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp);
1304: if ((make[0] = strrchr(make[1], '/')) == NULL) {
1305: make[0] = make[1];
1306: make[1] = NULL;
1307: } else
1308: ++make[0];
1309: make[2] = NULL;
1.82 reinoud 1310: cur_dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
1.54 sjg 1311: }
1.155 christos 1312: if (ac == 0 || av == NULL) {
1313: if (DEBUG(CWD))
1314: fprintf(debug_file, "check_cwd: empty command.\n");
1.54 sjg 1315: return NULL; /* initialization only */
1.155 christos 1316: }
1.54 sjg 1317:
1318: if (getenv("MAKEOBJDIR") == NULL &&
1.155 christos 1319: getenv("MAKEOBJDIRPREFIX") == NULL) {
1320: if (DEBUG(CWD))
1321: fprintf(debug_file, "check_cwd: no obj dirs.\n");
1.54 sjg 1322: return NULL;
1.155 christos 1323: }
1.54 sjg 1324:
1325:
1326: next_cmd = 1;
1327: for (i = 0; i < ac; ++i) {
1328: is_cmd = next_cmd;
1329:
1330: n = strlen(av[i]);
1331: cp = &(av[i])[n - 1];
1.127 rillig 1332: if (strspn(av[i], "|&;") == (size_t)n) {
1.54 sjg 1333: next_cmd = 1;
1334: continue;
1335: } else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') {
1336: next_cmd = 1;
1337: if (copy) {
1338: do {
1339: *cp-- = '\0';
1340: } while (*cp == ';' || *cp == '&' || *cp == '|' ||
1341: *cp == ')' || *cp == '}') ;
1342: } else {
1343: /*
1344: * XXX this should not happen.
1345: */
1.155 christos 1346: fprintf(stderr, "%s: WARNING: raw arg ends in shell meta '%s'\n",
1347: progname, av[i]);
1.54 sjg 1348: }
1349: } else
1350: next_cmd = 0;
1351:
1352: cp = av[i];
1353: if (*cp == ';' || *cp == '&' || *cp == '|')
1354: is_cmd = 1;
1355:
1.155 christos 1356: if (DEBUG(CWD))
1357: fprintf(debug_file, "av[%d] == %s '%s'",
1.54 sjg 1358: i, (is_cmd) ? "cmd" : "arg", av[i]);
1359: if (is_cmd != 0) {
1.57 sjg 1360: if (*cp == '(' || *cp == '{' ||
1361: *cp == ';' || *cp == '&' || *cp == '|') {
1362: do {
1363: ++cp;
1364: } while (*cp == '(' || *cp == '{' ||
1365: *cp == ';' || *cp == '&' || *cp == '|');
1366: if (*cp == '\0') {
1367: next_cmd = 1;
1368: continue;
1369: }
1370: }
1.54 sjg 1371: if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) {
1.155 christos 1372: if (DEBUG(CWD))
1373: fprintf(debug_file, " == cd, done.\n");
1.54 sjg 1374: return NULL;
1375: }
1376: for (mp = make; *mp != NULL; ++mp) {
1377: n = strlen(*mp);
1378: if (strcmp(cp, *mp) == 0) {
1.155 christos 1379: if (DEBUG(CWD))
1380: fprintf(debug_file, " %s == '%s', chdir(%s)\n",
1.82 reinoud 1381: cp, *mp, cur_dir);
1382: return cur_dir;
1.54 sjg 1383: }
1384: }
1385: }
1.155 christos 1386: if (DEBUG(CWD))
1387: fprintf(debug_file, "\n");
1.54 sjg 1388: }
1389: return NULL;
1390: }
1391:
1392: char *
1.89 christos 1393: Check_Cwd_Cmd(const char *cmd)
1.54 sjg 1394: {
1.89 christos 1395: char *cp, *bp;
1396: char **av;
1.149 christos 1397: int ac;
1.54 sjg 1398:
1399: if (Check_Cwd_Off)
1400: return NULL;
1401:
1402: if (cmd) {
1403: av = brk_string(cmd, &ac, TRUE, &bp);
1.155 christos 1404: if (DEBUG(CWD))
1405: fprintf(debug_file, "splitting: '%s' -> %d words\n",
1.54 sjg 1406: cmd, ac);
1407: } else {
1408: ac = 0;
1409: av = NULL;
1410: bp = NULL;
1411: }
1412: cp = Check_Cwd_av(ac, av, 1);
1.125 christos 1413: if (bp)
1414: free(bp);
1415: if (av)
1.54 sjg 1416: free(av);
1417: return cp;
1418: }
1419:
1420: void
1.89 christos 1421: Check_Cwd(const char **argv)
1.54 sjg 1422: {
1423: char *cp;
1.149 christos 1424: int ac;
1.54 sjg 1425:
1426: if (Check_Cwd_Off)
1427: return;
1428:
1429: for (ac = 0; argv[ac] != NULL; ++ac)
1430: /* NOTHING */;
1431: if (ac == 3 && *argv[1] == '-') {
1432: cp = Check_Cwd_Cmd(argv[2]);
1433: } else {
1.89 christos 1434: cp = Check_Cwd_av(ac, UNCONST(argv), 0);
1.54 sjg 1435: }
1436: if (cp) {
1437: chdir(cp);
1438: }
1.29 christos 1439: }
1440:
1441: /*-
1442: * Cmd_Exec --
1443: * Execute the command in cmd, and return the output of that command
1444: * in a string.
1445: *
1446: * Results:
1447: * A string containing the output of the command, or the empty string
1.129 christos 1448: * If errnum is not NULL, it contains the reason for the command failure
1.29 christos 1449: *
1450: * Side Effects:
1451: * The string must be freed by the caller.
1452: */
1453: char *
1.129 christos 1454: Cmd_Exec(const char *cmd, const char **errnum)
1.29 christos 1455: {
1.89 christos 1456: const char *args[4]; /* Args for invoking the shell */
1.29 christos 1457: int fds[2]; /* Pipe streams */
1.149 christos 1458: int cpid; /* Child PID */
1459: int pid; /* PID from wait() */
1.29 christos 1460: char *res; /* result */
1461: int status; /* command exit status */
1462: Buffer buf; /* buffer to store the result */
1463: char *cp;
1.149 christos 1464: int cc;
1.29 christos 1465:
1466:
1.129 christos 1467: *errnum = NULL;
1.29 christos 1468:
1.90 sjg 1469: if (!shellName)
1470: Shell_Init();
1.29 christos 1471: /*
1472: * Set up arguments for shell
1473: */
1.90 sjg 1474: args[0] = shellName;
1.29 christos 1475: args[1] = "-c";
1476: args[2] = cmd;
1477: args[3] = NULL;
1478:
1479: /*
1480: * Open a pipe for fetching its output
1481: */
1482: if (pipe(fds) == -1) {
1.129 christos 1483: *errnum = "Couldn't create pipe for \"%s\"";
1.29 christos 1484: goto bad;
1485: }
1486:
1487: /*
1488: * Fork
1489: */
1490: switch (cpid = vfork()) {
1491: case 0:
1492: /*
1493: * Close input side of pipe
1494: */
1.112 christos 1495: (void)close(fds[0]);
1.29 christos 1496:
1497: /*
1498: * Duplicate the output stream to the shell's output, then
1499: * shut the extra thing down. Note we don't fetch the error
1500: * stream...why not? Why?
1501: */
1.112 christos 1502: (void)dup2(fds[1], 1);
1503: (void)close(fds[1]);
1.31 christos 1504:
1.143 sjg 1505: Var_ExportVars();
1506:
1.112 christos 1507: (void)execv(shellPath, UNCONST(args));
1.29 christos 1508: _exit(1);
1509: /*NOTREACHED*/
1510:
1511: case -1:
1.129 christos 1512: *errnum = "Couldn't exec \"%s\"";
1.29 christos 1513: goto bad;
1514:
1515: default:
1516: /*
1517: * No need for the writing half
1518: */
1.112 christos 1519: (void)close(fds[1]);
1.31 christos 1520:
1.163 dsl 1521: Buf_Init(&buf, 0);
1.29 christos 1522:
1523: do {
1524: char result[BUFSIZ];
1525: cc = read(fds[0], result, sizeof(result));
1.31 christos 1526: if (cc > 0)
1.163 dsl 1527: Buf_AddBytes(&buf, cc, result);
1.29 christos 1528: }
1529: while (cc > 0 || (cc == -1 && errno == EINTR));
1530:
1531: /*
1532: * Close the input side of the pipe.
1533: */
1.112 christos 1534: (void)close(fds[0]);
1.29 christos 1535:
1536: /*
1537: * Wait for the process to exit.
1538: */
1.138 dsl 1539: while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0))
1.29 christos 1540: continue;
1541:
1.163 dsl 1542: cc = Buf_Size(&buf);
1543: res = Buf_Destroy(&buf, FALSE);
1.29 christos 1544:
1.149 christos 1545: if (cc == 0)
1.129 christos 1546: *errnum = "Couldn't read shell's output for \"%s\"";
1.29 christos 1547:
1548: if (status)
1.129 christos 1549: *errnum = "\"%s\" returned non-zero status";
1.29 christos 1550:
1551: /*
1552: * Null-terminate the result, convert newlines to spaces and
1553: * install it in the variable.
1554: */
1.149 christos 1555: res[cc] = '\0';
1556: cp = &res[cc];
1.29 christos 1557:
1.149 christos 1558: if (cc > 0 && *--cp == '\n') {
1.29 christos 1559: /*
1560: * A final newline is just stripped
1561: */
1562: *cp-- = '\0';
1563: }
1564: while (cp >= res) {
1565: if (*cp == '\n') {
1566: *cp = ' ';
1567: }
1568: cp--;
1569: }
1570: break;
1571: }
1572: return res;
1573: bad:
1.151 joerg 1574: res = bmake_malloc(1);
1.29 christos 1575: *res = '\0';
1576: return res;
1.1 cgd 1577: }
1578:
1579: /*-
1580: * Error --
1581: * Print an error message given its format.
1582: *
1583: * Results:
1584: * None.
1585: *
1586: * Side Effects:
1587: * The message is printed.
1588: */
1589: /* VARARGS */
1590: void
1.89 christos 1591: Error(const char *fmt, ...)
1.1 cgd 1592: {
1593: va_list ap;
1.162 dsl 1594: FILE *err_file;
1.85 wiz 1595:
1.162 dsl 1596: err_file = debug_file;
1597: if (err_file == stdout)
1598: err_file = stderr;
1599: for (;;) {
1600: va_start(ap, fmt);
1601: fprintf(err_file, "%s: ", progname);
1602: (void)vfprintf(err_file, fmt, ap);
1603: va_end(ap);
1604: (void)fprintf(err_file, "\n");
1605: (void)fflush(err_file);
1606: if (err_file == stderr)
1607: break;
1608: err_file = stderr;
1609: }
1.1 cgd 1610: }
1611:
1612: /*-
1613: * Fatal --
1614: * Produce a Fatal error message. If jobs are running, waits for them
1615: * to finish.
1616: *
1617: * Results:
1618: * None
1619: *
1620: * Side Effects:
1621: * The program exits
1622: */
1623: /* VARARGS */
1624: void
1.89 christos 1625: Fatal(const char *fmt, ...)
1.1 cgd 1626: {
1627: va_list ap;
1.85 wiz 1628:
1.13 cgd 1629: va_start(ap, fmt);
1.1 cgd 1630: if (jobsRunning)
1631: Job_Wait();
1632:
1633: (void)vfprintf(stderr, fmt, ap);
1634: va_end(ap);
1635: (void)fprintf(stderr, "\n");
1636: (void)fflush(stderr);
1637:
1.67 sjg 1638: PrintOnError(NULL);
1639:
1.94 dsl 1640: if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1.1 cgd 1641: Targ_PrintGraph(2);
1.58 sommerfe 1642: Trace_Log(MAKEERROR, 0);
1.1 cgd 1643: exit(2); /* Not 1 so -q can distinguish error */
1644: }
1645:
1646: /*
1647: * Punt --
1648: * Major exception once jobs are being created. Kills all jobs, prints
1649: * a message and exits.
1650: *
1651: * Results:
1.31 christos 1652: * None
1.1 cgd 1653: *
1654: * Side Effects:
1655: * All children are killed indiscriminately and the program Lib_Exits
1656: */
1657: /* VARARGS */
1658: void
1.89 christos 1659: Punt(const char *fmt, ...)
1.1 cgd 1660: {
1661: va_list ap;
1.85 wiz 1662:
1.13 cgd 1663: va_start(ap, fmt);
1.63 christos 1664: (void)fprintf(stderr, "%s: ", progname);
1.1 cgd 1665: (void)vfprintf(stderr, fmt, ap);
1666: va_end(ap);
1667: (void)fprintf(stderr, "\n");
1668: (void)fflush(stderr);
1669:
1.67 sjg 1670: PrintOnError(NULL);
1671:
1.1 cgd 1672: DieHorribly();
1673: }
1674:
1675: /*-
1676: * DieHorribly --
1677: * Exit without giving a message.
1678: *
1679: * Results:
1680: * None
1681: *
1682: * Side Effects:
1683: * A big one...
1684: */
1685: void
1.85 wiz 1686: DieHorribly(void)
1.1 cgd 1687: {
1688: if (jobsRunning)
1689: Job_AbortAll();
1690: if (DEBUG(GRAPH2))
1691: Targ_PrintGraph(2);
1.58 sommerfe 1692: Trace_Log(MAKEERROR, 0);
1.1 cgd 1693: exit(2); /* Not 1, so -q can distinguish error */
1694: }
1695:
1696: /*
1697: * Finish --
1698: * Called when aborting due to errors in child shell to signal
1.31 christos 1699: * abnormal exit.
1.1 cgd 1700: *
1701: * Results:
1.31 christos 1702: * None
1.1 cgd 1703: *
1704: * Side Effects:
1705: * The program exits
1706: */
1707: void
1.85 wiz 1708: Finish(int errors)
1709: /* number of errors encountered in Make_Make */
1.1 cgd 1710: {
1711: Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1712: }
1713:
1.21 christos 1714: /*
1715: * enunlink --
1716: * Remove a file carefully, avoiding directories.
1717: */
1718: int
1.85 wiz 1719: eunlink(const char *file)
1.21 christos 1720: {
1721: struct stat st;
1722:
1723: if (lstat(file, &st) == -1)
1724: return -1;
1725:
1726: if (S_ISDIR(st.st_mode)) {
1727: errno = EISDIR;
1728: return -1;
1729: }
1730: return unlink(file);
1.1 cgd 1731: }
1732:
1733: /*
1.66 christos 1734: * execError --
1735: * Print why exec failed, avoiding stdio.
1736: */
1737: void
1.85 wiz 1738: execError(const char *af, const char *av)
1.66 christos 1739: {
1740: #ifdef USE_IOVEC
1741: int i = 0;
1.83 pk 1742: struct iovec iov[8];
1.66 christos 1743: #define IOADD(s) \
1.89 christos 1744: (void)(iov[i].iov_base = UNCONST(s), \
1.66 christos 1745: iov[i].iov_len = strlen(iov[i].iov_base), \
1746: i++)
1747: #else
1.112 christos 1748: #define IOADD(void)write(2, s, strlen(s))
1.66 christos 1749: #endif
1750:
1751: IOADD(progname);
1.83 pk 1752: IOADD(": ");
1.89 christos 1753: IOADD(af);
1.83 pk 1754: IOADD("(");
1.89 christos 1755: IOADD(av);
1.83 pk 1756: IOADD(") failed (");
1.66 christos 1757: IOADD(strerror(errno));
1758: IOADD(")\n");
1759:
1760: #ifdef USE_IOVEC
1.83 pk 1761: (void)writev(2, iov, 8);
1.66 christos 1762: #endif
1763: }
1764:
1765: /*
1.1 cgd 1766: * usage --
1767: * exit with usage message
1768: */
1.13 cgd 1769: static void
1.85 wiz 1770: usage(void)
1.1 cgd 1771: {
1772: (void)fprintf(stderr,
1.105 wiz 1773: "usage: %s [-BeikNnqrstWX] [-D variable] [-d flags] [-f makefile]\n\
1774: [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
1775: [-V variable] [variable=value] [target ...]\n", progname);
1.1 cgd 1776: exit(2);
1.14 jtc 1777: }
1778:
1779:
1780: int
1.164 dsl 1781: PrintAddr(void *a, void *b)
1.14 jtc 1782: {
1783: printf("%lx ", (unsigned long) a);
1784: return b ? 0 : 0;
1.67 sjg 1785: }
1.149 christos 1786:
1.67 sjg 1787:
1788:
1789: void
1.89 christos 1790: PrintOnError(const char *s)
1.67 sjg 1791: {
1792: char tmp[64];
1.128 sjg 1793: char *cp;
1794:
1.67 sjg 1795: if (s)
1796: printf("%s", s);
1797:
1798: printf("\n%s: stopped in %s\n", progname, curdir);
1799: strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
1800: sizeof(tmp) - 1);
1.128 sjg 1801: cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
1802: if (cp) {
1803: if (*cp)
1804: printf("%s", cp);
1805: free(cp);
1806: }
1.68 sjg 1807: }
1808:
1809: void
1.85 wiz 1810: Main_ExportMAKEFLAGS(Boolean first)
1.68 sjg 1811: {
1812: static int once = 1;
1813: char tmp[64];
1814: char *s;
1815:
1816: if (once != first)
1817: return;
1818: once = 0;
1819:
1.70 sjg 1820: strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
1821: sizeof(tmp));
1822: s = Var_Subst(NULL, tmp, VAR_CMD, 0);
1.68 sjg 1823: if (s && *s) {
1824: #ifdef POSIX
1825: setenv("MAKEFLAGS", s, 1);
1826: #else
1827: setenv("MAKE", s, 1);
1828: #endif
1829: }
1.1 cgd 1830: }
CVSweb <webmaster@jp.NetBSD.org>