~ubuntu-branches/ubuntu/precise/pmake/precise

« back to all changes in this revision

Viewing changes to .pc/120_fixes.diff/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2011-01-19 06:48:29 UTC
  • Revision ID: james.westby@ubuntu.com-20110119064829-drz1dzha126g6x9r
Tags: 1.111-2ubuntu1
--whole-archive is a linker option, not a compiler option.

Show diffs side-by-side

added added

removed removed

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