patch-7.278
[dragonfly.git] / usr.bin / make / main.c
1 /*-
2  * Copyright (c) 1988, 1989, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1989 by Berkeley Softworks
5  * 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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * @(#) Copyright (c) 1988, 1989, 1990, 1993 The Regents of the University of California.  All rights reserved.
39  * @(#)main.c   8.3 (Berkeley) 3/19/94
40  * $FreeBSD: src/usr.bin/make/main.c,v 1.118 2005/02/13 13:33:56 harti Exp $
41  * $DragonFly: src/usr.bin/make/main.c,v 1.92 2005/05/16 17:29:42 okumoto Exp $
42  */
43
44 /*
45  * main.c
46  *      The main file for this entire program. Exit routines etc
47  *      reside here.
48  *
49  * Utility functions defined in this file:
50  *      Main_ParseArgLine
51  *                      Takes a line of arguments, breaks them and
52  *                      treats them as if they were given when first
53  *                      invoked. Used by the parse module to implement
54  *                      the .MFLAGS target.
55  */
56
57 #ifndef MACHINE
58 #include <sys/utsname.h>
59 #endif
60 #include <sys/param.h>
61 #include <sys/stat.h>
62 #include <sys/time.h>
63 #include <sys/queue.h>
64 #include <sys/resource.h>
65 #include <sys/wait.h>
66 #include <err.h>
67 #include <errno.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71
72 #include "arch.h"
73 #include "buf.h"
74 #include "config.h"
75 #include "dir.h"
76 #include "globals.h"
77 #include "job.h"
78 #include "make.h"
79 #include "parse.h"
80 #include "pathnames.h"
81 #include "str.h"
82 #include "suff.h"
83 #include "targ.h"
84 #include "util.h"
85 #include "var.h"
86
87 extern char **environ;  /* XXX what header declares this variable? */
88
89 #define WANT_ENV_MKLVL  1
90 #define MKLVL_MAXVAL    500
91 #define MKLVL_ENVVAR    "__MKLVL__"
92
93 /*
94  * DEFMAXJOBS
95  *      This control the default concurrency. On no occasion will more
96  *      than DEFMAXJOBS targets be created at once.
97  */
98 #define DEFMAXJOBS      1
99
100 /* ordered list of makefiles to read */
101 static Lst makefiles = Lst_Initializer(makefiles);
102
103 /* list of variables to print */
104 static Lst variables = Lst_Initializer(variables);
105
106 static Boolean  expandVars;     /* fully expand printed variables */
107 static Boolean  noBuiltins;     /* -r flag */
108 static Boolean  forceJobs;      /* -j argument given */
109 static char     *curdir;        /* startup directory */
110 static char     *objdir;        /* where we chdir'ed to */
111
112 /* (-E) vars to override from env */
113 Lst envFirstVars = Lst_Initializer(envFirstVars);
114
115 /* Targets to be made */
116 Lst create = Lst_Initializer(create);
117
118 Boolean         allPrecious;    /* .PRECIOUS given on line by itself */
119 Boolean         beSilent;       /* -s flag */
120 Boolean         beVerbose;      /* -v flag */
121 Boolean         compatMake;     /* -B argument */
122 Boolean         debug;          /* -d flag */
123 Boolean         ignoreErrors;   /* -i flag */
124 int             jobLimit;       /* -j argument */
125 Boolean         jobsRunning;    /* TRUE if the jobs might be running */
126 Boolean         keepgoing;      /* -k flag */
127 Boolean         noExecute;      /* -n flag */
128 Boolean         queryFlag;      /* -q flag */
129 Boolean         touchFlag;      /* -t flag */
130 Boolean         usePipes;       /* !-P flag */
131 uint32_t        warn_cmd;       /* command line warning flags */
132 uint32_t        warn_flags;     /* actual warning flags */
133 uint32_t        warn_nocmd;     /* command line no-warning flags */
134
135 time_t          now;            /* Time at start of make */
136 struct GNode    *DEFAULT;       /* .DEFAULT node */
137
138 /**
139  * Exit with usage message.
140  */
141 static void
142 usage(void)
143 {
144         fprintf(stderr,
145             "usage: make [-BPSXeiknqrstv] [-C directory] [-D variable]\n"
146             "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
147             "\t[-j max_jobs] [-m directory] [-V variable]\n"
148             "\t[variable=value] [target ...]\n");
149         exit(2);
150 }
151
152 /**
153  * MFLAGS_append
154  *      Append a flag with an optional argument to MAKEFLAGS and MFLAGS
155  */
156 static void
157 MFLAGS_append(const char *flag, char *arg)
158 {
159         char *str;
160
161         Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
162         if (arg != NULL) {
163                 str = MAKEFLAGS_quote(arg);
164                 Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
165                 free(str);
166         }
167
168         Var_Append("MFLAGS", flag, VAR_GLOBAL);
169         if (arg != NULL) {
170                 str = MAKEFLAGS_quote(arg);
171                 Var_Append("MFLAGS", str, VAR_GLOBAL);
172                 free(str);
173         }
174 }
175
176 /**
177  * Open and parse the given makefile.
178  *
179  * Results:
180  *      TRUE if ok. FALSE if couldn't open file.
181  */
182 static Boolean
183 ReadMakefile(const char p[])
184 {
185         char *fname;                    /* makefile to read */
186         FILE *stream;
187         char *name, path[MAXPATHLEN];
188         char *MAKEFILE;
189         int setMAKEFILE;
190
191         /* XXX - remove this once constification is done */
192         fname = estrdup(p);
193
194         if (!strcmp(fname, "-")) {
195                 Parse_File("(stdin)", stdin);
196                 Var_SetGlobal("MAKEFILE", "");
197         } else {
198                 setMAKEFILE = strcmp(fname, ".depend");
199
200                 /* if we've chdir'd, rebuild the path name */
201                 if (curdir != objdir && *fname != '/') {
202                         snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
203                         /*
204                          * XXX The realpath stuff breaks relative includes
205                          * XXX in some cases.   The problem likely is in
206                          * XXX parse.c where it does special things in
207                          * XXX ParseDoInclude if the file is relateive
208                          * XXX or absolute and not a system file.  There
209                          * XXX it assumes that if the current file that's
210                          * XXX being included is absolute, that any files
211                          * XXX that it includes shouldn't do the -I path
212                          * XXX stuff, which is inconsistant with historical
213                          * XXX behavior.  However, I can't pentrate the mists
214                          * XXX further, so I'm putting this workaround in
215                          * XXX here until such time as the underlying bug
216                          * XXX can be fixed.
217                          */
218 #if THIS_BREAKS_THINGS
219                         if (realpath(path, path) != NULL &&
220                             (stream = fopen(path, "r")) != NULL) {
221                                 MAKEFILE = fname;
222                                 fname = path;
223                                 goto found;
224                         }
225                 } else if (realpath(fname, path) != NULL) {
226                         MAKEFILE = fname;
227                         fname = path;
228                         if ((stream = fopen(fname, "r")) != NULL)
229                                 goto found;
230                 }
231 #else
232                         if ((stream = fopen(path, "r")) != NULL) {
233                                 MAKEFILE = fname;
234                                 fname = path;
235                                 goto found;
236                         }
237                 } else {
238                         MAKEFILE = fname;
239                         if ((stream = fopen(fname, "r")) != NULL)
240                                 goto found;
241                 }
242 #endif
243                 /* look in -I and system include directories. */
244                 name = Path_FindFile(fname, &parseIncPath);
245                 if (!name)
246                         name = Path_FindFile(fname, &sysIncPath);
247                 if (!name || !(stream = fopen(name, "r")))
248                         return (FALSE);
249                 MAKEFILE = fname = name;
250                 /*
251                  * set the MAKEFILE variable desired by System V fans -- the
252                  * placement of the setting here means it gets set to the last
253                  * makefile specified, as it is set by SysV make.
254                  */
255 found:
256                 if (setMAKEFILE)
257                         Var_SetGlobal("MAKEFILE", MAKEFILE);
258                 Parse_File(fname, stream);
259                 fclose(stream);
260         }
261         return (TRUE);
262 }
263
264 /**
265  * Main_ParseWarn
266  *
267  *      Handle argument to warning option.
268  */
269 int
270 Main_ParseWarn(const char *arg, int iscmd)
271 {
272         int i, neg;
273
274         static const struct {
275                 const char      *option;
276                 uint32_t        flag;
277         } options[] = {
278                 { "dirsyntax",  WARN_DIRSYNTAX },
279                 { NULL,         0 }
280         };
281
282         neg = 0;
283         if (arg[0] == 'n' && arg[1] == 'o') {
284                 neg = 1;
285                 arg += 2;
286         }
287
288         for (i = 0; options[i].option != NULL; i++)
289                 if (strcmp(arg, options[i].option) == 0)
290                         break;
291
292         if (options[i].option == NULL)
293                 /* unknown option */
294                 return (-1);
295
296         if (iscmd) {
297                 if (!neg) {
298                         warn_cmd |= options[i].flag;
299                         warn_nocmd &= ~options[i].flag;
300                         warn_flags |= options[i].flag;
301                 } else {
302                         warn_nocmd |= options[i].flag;
303                         warn_cmd &= ~options[i].flag;
304                         warn_flags &= ~options[i].flag;
305                 }
306         } else {
307                 if (!neg) {
308                         warn_flags |= (options[i].flag & ~warn_nocmd);
309                 } else {
310                         warn_flags &= ~(options[i].flag | warn_cmd);
311                 }
312         }
313         return (0);
314 }
315
316 /**
317  * MainParseArgs
318  *      Parse a given argument vector. Called from main() and from
319  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
320  *
321  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
322  *
323  * Side Effects:
324  *      Various global and local flags will be set depending on the flags
325  *      given
326  */
327 static void
328 MainParseArgs(int argc, char **argv)
329 {
330         int c;
331         Boolean found_dd = FALSE;
332
333 rearg:
334         optind = 1;     /* since we're called more than once */
335         optreset = 1;
336 #define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:nqrstvx:"
337         for (;;) {
338                 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
339                         found_dd = TRUE;
340                 }
341                 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
342                         break;
343                 }
344                 switch(c) {
345
346                 case 'A':
347                         arch_fatal = FALSE;
348                         MFLAGS_append("-A", NULL);
349                         break;
350                 case 'C':
351                         if (chdir(optarg) == -1)
352                                 err(1, "chdir %s", optarg);
353                         break;
354                 case 'D':
355                         Var_SetGlobal(optarg, "1");
356                         MFLAGS_append("-D", optarg);
357                         break;
358                 case 'I':
359                         Parse_AddIncludeDir(optarg);
360                         MFLAGS_append("-I", optarg);
361                         break;
362                 case 'V':
363                         Lst_AtEnd(&variables, estrdup(optarg));
364                         MFLAGS_append("-V", optarg);
365                         break;
366                 case 'X':
367                         expandVars = FALSE;
368                         break;
369                 case 'B':
370                         compatMake = TRUE;
371                         MFLAGS_append("-B", NULL);
372                         unsetenv("MAKE_JOBS_FIFO");
373                         break;
374                 case 'P':
375                         usePipes = FALSE;
376                         MFLAGS_append("-P", NULL);
377                         break;
378                 case 'S':
379                         keepgoing = FALSE;
380                         MFLAGS_append("-S", NULL);
381                         break;
382                 case 'd': {
383                         char *modules = optarg;
384
385                         for (; *modules; ++modules)
386                                 switch (*modules) {
387                                 case 'A':
388                                         debug = ~0;
389                                         break;
390                                 case 'a':
391                                         debug |= DEBUG_ARCH;
392                                         break;
393                                 case 'c':
394                                         debug |= DEBUG_COND;
395                                         break;
396                                 case 'd':
397                                         debug |= DEBUG_DIR;
398                                         break;
399                                 case 'f':
400                                         debug |= DEBUG_FOR;
401                                         break;
402                                 case 'g':
403                                         if (modules[1] == '1') {
404                                                 debug |= DEBUG_GRAPH1;
405                                                 ++modules;
406                                         }
407                                         else if (modules[1] == '2') {
408                                                 debug |= DEBUG_GRAPH2;
409                                                 ++modules;
410                                         }
411                                         break;
412                                 case 'j':
413                                         debug |= DEBUG_JOB;
414                                         break;
415                                 case 'l':
416                                         debug |= DEBUG_LOUD;
417                                         break;
418                                 case 'm':
419                                         debug |= DEBUG_MAKE;
420                                         break;
421                                 case 's':
422                                         debug |= DEBUG_SUFF;
423                                         break;
424                                 case 't':
425                                         debug |= DEBUG_TARG;
426                                         break;
427                                 case 'v':
428                                         debug |= DEBUG_VAR;
429                                         break;
430                                 default:
431                                         warnx("illegal argument to d option "
432                                             "-- %c", *modules);
433                                         usage();
434                                 }
435                         MFLAGS_append("-d", optarg);
436                         break;
437                 }
438                 case 'E':
439                         Lst_AtEnd(&envFirstVars, estrdup(optarg));
440                         MFLAGS_append("-E", optarg);
441                         break;
442                 case 'e':
443                         checkEnvFirst = TRUE;
444                         MFLAGS_append("-e", NULL);
445                         break;
446                 case 'f':
447                         Lst_AtEnd(&makefiles, estrdup(optarg));
448                         break;
449                 case 'i':
450                         ignoreErrors = TRUE;
451                         MFLAGS_append("-i", NULL);
452                         break;
453                 case 'j': {
454                         char *endptr;
455
456                         forceJobs = TRUE;
457                         jobLimit = strtol(optarg, &endptr, 10);
458                         if (jobLimit <= 0 || *endptr != '\0') {
459                                 warnx("illegal number, -j argument -- %s",
460                                     optarg);
461                                 usage();
462                         }
463                         MFLAGS_append("-j", optarg);
464                         break;
465                 }
466                 case 'k':
467                         keepgoing = TRUE;
468                         MFLAGS_append("-k", NULL);
469                         break;
470                 case 'm':
471                         Path_AddDir(&sysIncPath, optarg);
472                         MFLAGS_append("-m", optarg);
473                         break;
474                 case 'n':
475                         noExecute = TRUE;
476                         MFLAGS_append("-n", NULL);
477                         break;
478                 case 'q':
479                         queryFlag = TRUE;
480                         /* Kind of nonsensical, wot? */
481                         MFLAGS_append("-q", NULL);
482                         break;
483                 case 'r':
484                         noBuiltins = TRUE;
485                         MFLAGS_append("-r", NULL);
486                         break;
487                 case 's':
488                         beSilent = TRUE;
489                         MFLAGS_append("-s", NULL);
490                         break;
491                 case 't':
492                         touchFlag = TRUE;
493                         MFLAGS_append("-t", NULL);
494                         break;
495                 case 'v':
496                         beVerbose = TRUE;
497                         MFLAGS_append("-v", NULL);
498                         break;
499                 case 'x':
500                         if (Main_ParseWarn(optarg, 1) != -1)
501                                 MFLAGS_append("-x", optarg);
502                         break;
503                                 
504                 default:
505                 case '?':
506                         usage();
507                 }
508         }
509         argv += optind;
510         argc -= optind;
511
512         oldVars = TRUE;
513
514         /*
515          * Parse the rest of the arguments.
516          *      o Check for variable assignments and perform them if so.
517          *      o Check for more flags and restart getopt if so.
518          *      o Anything else is taken to be a target and added
519          *        to the end of the "create" list.
520          */
521         for (; *argv != NULL; ++argv, --argc) {
522                 if (Parse_IsVar(*argv)) {
523                         char *ptr = MAKEFLAGS_quote(*argv);
524
525                         Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
526                         Parse_DoVar(*argv, VAR_CMD);
527                         free(ptr);
528
529                 } else if ((*argv)[0] == '-') {
530                         if ((*argv)[1] == '\0') {
531                                 /*
532                                  * (*argv) is a single dash, so we
533                                  * just ignore it.
534                                  */
535                         } else if (found_dd) {
536                                 /*
537                                  * Double dash has been found, ignore
538                                  * any more options.  But what do we do
539                                  * with it?  For now treat it like a target.
540                                  */
541                                 Lst_AtEnd(&create, estrdup(*argv));
542                         } else {
543                                 /*
544                                  * (*argv) is a -flag, so backup argv and
545                                  * argc.  getopt() expects options to start
546                                  * in the 2nd position.
547                                  */
548                                 argc++;
549                                 argv--;
550                                 goto rearg;
551                         }
552
553                 } else if ((*argv)[0] == '\0') {
554                         Punt("illegal (null) argument.");
555
556                 } else {
557                         Lst_AtEnd(&create, estrdup(*argv));
558                 }
559         }
560 }
561
562 /**
563  * Main_ParseArgLine
564  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
565  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
566  *      Takes a line of arguments and breaks it into its
567  *      component words and passes those words and the number of them to the
568  *      MainParseArgs function.
569  *      The line should have all its leading whitespace removed.
570  *
571  * Side Effects:
572  *      Only those that come from the various arguments.
573  */
574 void
575 Main_ParseArgLine(char *line, int mflags)
576 {
577         ArgArray        aa;
578
579         if (line == NULL)
580                 return;
581         for (; *line == ' '; ++line)
582                 continue;
583         if (!*line)
584                 return;
585
586         if (mflags) {
587                 MAKEFLAGS_break(&aa, line);
588         } else {
589                 brk_string(&aa, line, TRUE);
590         }
591         MainParseArgs(aa.argc, aa.argv);
592         ArgArray_Done(&aa);
593 }
594
595 static char *
596 chdir_verify_path(const char *path, char *obpath)
597 {
598         struct stat sb;
599
600         if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
601                 if (chdir(path) == -1 || getcwd(obpath, MAXPATHLEN) == NULL) {
602                         warn("warning: %s", path);
603                         return (NULL);
604                 }
605                 return (obpath);
606         }
607
608         return (NULL);
609 }
610
611 /**
612  * In lieu of a good way to prevent every possible looping in make(1), stop
613  * there from being more than MKLVL_MAXVAL processes forked by make(1), to
614  * prevent a forkbomb from happening, in a dumb and mechanical way.
615  *
616  * Side Effects:
617  *      Creates or modifies enviornment variable MKLVL_ENVVAR via setenv().
618  */
619 static void
620 check_make_level(void)
621 {
622 #ifdef WANT_ENV_MKLVL
623         char    *value = getenv(MKLVL_ENVVAR);
624         int     level = (value == NULL) ? 0 : atoi(value);
625
626         if (level < 0) {
627                 errc(2, EAGAIN, "Invalid value for recursion level (%d).",
628                     level);
629         } else if (level > MKLVL_MAXVAL) {
630                 errc(2, EAGAIN, "Max recursion level (%d) exceeded.",
631                     MKLVL_MAXVAL);
632         } else {
633                 char new_value[32];
634                 sprintf(new_value, "%d", level + 1);
635                 setenv(MKLVL_ENVVAR, new_value, 1);
636         }
637 #endif /* WANT_ENV_MKLVL */
638 }
639
640 /**
641  * main
642  *      The main function, for obvious reasons. Initializes variables
643  *      and a few modules, then parses the arguments give it in the
644  *      environment and on the command line. Reads the system makefile
645  *      followed by either Makefile, makefile or the file given by the
646  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
647  *      flags it has received by then uses either the Make or the Compat
648  *      module to create the initial list of targets.
649  *
650  * Results:
651  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
652  *      0.
653  *
654  * Side Effects:
655  *      The program exits when done. Targets are created. etc. etc. etc.
656  */
657 int
658 main(int argc, char **argv)
659 {
660         const char *machine;
661         const char *machine_arch;
662         const char *machine_cpu;
663         Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
664         char *p;
665         const char *pathp;
666         const char *path;
667         char mdpath[MAXPATHLEN];
668         char obpath[MAXPATHLEN];
669         char cdpath[MAXPATHLEN];
670         char *cp = NULL, *start;
671
672         /*
673          * Initialize file global variables.
674          */
675         expandVars = TRUE;
676         noBuiltins = FALSE;             /* Read the built-in rules */
677         forceJobs = FALSE;              /* No -j flag */
678         curdir = cdpath;
679
680         /*
681          * Initialize program global variables.
682          */
683         beSilent = FALSE;               /* Print commands as executed */
684         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
685         noExecute = FALSE;              /* Execute all commands */
686         keepgoing = FALSE;              /* Stop on error */
687         allPrecious = FALSE;            /* Remove targets when interrupted */
688         queryFlag = FALSE;              /* This is not just a check-run */
689         touchFlag = FALSE;              /* Actually update targets */
690         usePipes = TRUE;                /* Catch child output in pipes */
691         debug = 0;                      /* No debug verbosity, please. */
692         jobsRunning = FALSE;
693
694         jobLimit = DEFMAXJOBS;
695         compatMake = FALSE;             /* No compat mode */
696
697         check_make_level();
698
699 #ifdef RLIMIT_NOFILE
700         /*
701          * get rid of resource limit on file descriptors
702          */
703         {
704                 struct rlimit rl;
705                 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
706                         err(2, "getrlimit");
707                 }
708                 rl.rlim_cur = rl.rlim_max;
709                 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
710                         err(2, "setrlimit");
711                 }
712         }
713 #endif
714         /*
715          * Get the name of this type of MACHINE from utsname
716          * so we can share an executable for similar machines.
717          * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
718          *
719          * Note that while MACHINE is decided at run-time,
720          * MACHINE_ARCH is always known at compile time.
721          */
722         if ((machine = getenv("MACHINE")) == NULL) {
723 #ifdef MACHINE
724                 machine = MACHINE;
725 #else
726                 static struct utsname utsname;
727
728                 if (uname(&utsname) == -1)
729                         err(2, "uname");
730                 machine = utsname.machine;
731 #endif
732         }
733
734         if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
735 #ifdef MACHINE_ARCH
736                 machine_arch = MACHINE_ARCH;
737 #else
738                 machine_arch = "unknown";
739 #endif
740         }
741
742         /*
743          * Set machine_cpu to the minumum supported CPU revision based
744          * on the target architecture, if not already set.
745          */
746         if ((machine_cpu = getenv("MACHINE_CPU")) == NULL) {
747                 if (!strcmp(machine_arch, "i386"))
748                         machine_cpu = "i386";
749                 else if (!strcmp(machine_arch, "alpha"))
750                         machine_cpu = "ev4";
751                 else
752                         machine_cpu = "unknown";
753         }
754
755         /*
756          * Initialize the parsing, directory and variable modules to prepare
757          * for the reading of inclusion paths and variable settings on the
758          * command line
759          */
760         Proc_Init();
761
762         Dir_Init();             /* Initialize directory structures so -I flags
763                                  * can be processed correctly */
764         Var_Init(environ);      /* As well as the lists of variables for
765                                  * parsing arguments */
766
767         /*
768          * Initialize various variables.
769          *      MAKE also gets this name, for compatibility
770          *      .MAKEFLAGS gets set to the empty string just in case.
771          *      MFLAGS also gets initialized empty, for compatibility.
772          */
773         Var_SetGlobal("MAKE", argv[0]);
774         Var_SetGlobal(".MAKEFLAGS", "");
775         Var_SetGlobal("MFLAGS", "");
776         Var_SetGlobal("MACHINE", machine);
777         Var_SetGlobal("MACHINE_ARCH", machine_arch);
778         Var_SetGlobal("MACHINE_CPU", machine_cpu);
779 #ifdef MAKE_VERSION
780         Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
781 #endif
782
783         /*
784          * First snag things out of the MAKEFLAGS environment
785          * variable.  Then parse the command line arguments.
786          */
787         Main_ParseArgLine(getenv("MAKEFLAGS"), 1);
788
789         MainParseArgs(argc, argv);
790
791         /*
792          * Find where we are...
793          */
794         if (getcwd(curdir, MAXPATHLEN) == NULL)
795                 err(2, NULL);
796
797         {
798         struct stat sa;
799
800         if (stat(curdir, &sa) == -1)
801             err(2, "%s", curdir);
802         }
803
804         /*
805          * The object directory location is determined using the
806          * following order of preference:
807          *
808          *      1. MAKEOBJDIRPREFIX`cwd`
809          *      2. MAKEOBJDIR
810          *      3. PATH_OBJDIR.${MACHINE}
811          *      4. PATH_OBJDIR
812          *      5. PATH_OBJDIRPREFIX`cwd`
813          *
814          * If one of the first two fails, use the current directory.
815          * If the remaining three all fail, use the current directory.
816          *
817          * Once things are initted,
818          * have to add the original directory to the search path,
819          * and modify the paths for the Makefiles apropriately.  The
820          * current directory is also placed as a variable for make scripts.
821          */
822         if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
823                 if (!(path = getenv("MAKEOBJDIR"))) {
824                         path = PATH_OBJDIR;
825                         pathp = PATH_OBJDIRPREFIX;
826                         snprintf(mdpath, MAXPATHLEN, "%s.%s", path, machine);
827                         if (!(objdir = chdir_verify_path(mdpath, obpath)))
828                                 if (!(objdir=chdir_verify_path(path, obpath))) {
829                                         snprintf(mdpath, MAXPATHLEN,
830                                                         "%s%s", pathp, curdir);
831                                         if (!(objdir=chdir_verify_path(mdpath,
832                                                                        obpath)))
833                                                 objdir = curdir;
834                                 }
835                 }
836                 else if (!(objdir = chdir_verify_path(path, obpath)))
837                         objdir = curdir;
838         }
839         else {
840                 snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
841                 if (!(objdir = chdir_verify_path(mdpath, obpath)))
842                         objdir = curdir;
843         }
844         Dir_InitDot();          /* Initialize the "." directory */
845         if (objdir != curdir)
846                 Path_AddDir(&dirSearchPath, curdir);
847         Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
848         Var_SetGlobal(".ST_EXPORTVAR", "YES");
849         Var_SetGlobal(".CURDIR", curdir);
850         Var_SetGlobal(".OBJDIR", objdir);
851
852         if (getenv("MAKE_JOBS_FIFO") != NULL)
853                 forceJobs = TRUE;
854         /*
855          * Be compatible if user did not specify -j and did not explicitly
856          * turned compatibility on
857          */
858         if (!compatMake && !forceJobs)
859                 compatMake = TRUE;
860
861         /*
862          * Initialize target and suffix modules in preparation for
863          * parsing the makefile(s)
864          */
865         Targ_Init();
866         Suff_Init();
867
868         DEFAULT = NULL;
869         time(&now);
870
871         /*
872          * Set up the .TARGETS variable to contain the list of targets to be
873          * created. If none specified, make the variable empty -- the parser
874          * will fill the thing in with the default or .MAIN target.
875          */
876         if (Lst_IsEmpty(&create)) {
877                 Var_SetGlobal(".TARGETS", "");
878         } else {
879                 LstNode *ln;
880
881                 for (ln = Lst_First(&create); ln != NULL; ln = Lst_Succ(ln)) {
882                         char *name = Lst_Datum(ln);
883
884                         Var_Append(".TARGETS", name, VAR_GLOBAL);
885                 }
886         }
887
888
889         /*
890          * If no user-supplied system path was given (through the -m option)
891          * add the directories from the DEFSYSPATH (more than one may be given
892          * as dir1:...:dirn) to the system include path.
893          */
894         if (TAILQ_EMPTY(&sysIncPath)) {
895                 char syspath[] = PATH_DEFSYSPATH;
896
897                 for (start = syspath; *start != '\0'; start = cp) {
898                         for (cp = start; *cp != '\0' && *cp != ':'; cp++)
899                                 continue;
900                         if (*cp == '\0') {
901                                 Path_AddDir(&sysIncPath, start);
902                         } else {
903                                 *cp++ = '\0';
904                                 Path_AddDir(&sysIncPath, start);
905                         }
906                 }
907         }
908
909         /*
910          * Read in the built-in rules first, followed by the specified
911          * makefile, if it was (makefile != (char *) NULL), or the default
912          * Makefile and makefile, in that order, if it wasn't.
913          */
914         if (!noBuiltins) {
915                 /* Path of sys.mk */
916                 Lst sysMkPath = Lst_Initializer(sysMkPath);
917                 LstNode *ln;
918                 char    defsysmk[] = PATH_DEFSYSMK;
919
920                 Path_Expand(defsysmk, &sysIncPath, &sysMkPath);
921                 if (Lst_IsEmpty(&sysMkPath))
922                         Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
923                 LST_FOREACH(ln, &sysMkPath) {
924                         if (!ReadMakefile(Lst_Datum(ln)))
925                                 break;
926                 }
927                 if (ln != NULL)
928                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
929                 Lst_Destroy(&sysMkPath, free);
930         }
931
932         if (!Lst_IsEmpty(&makefiles)) {
933                 LstNode *ln;
934
935                 LST_FOREACH(ln, &makefiles) {
936                         if (!ReadMakefile(Lst_Datum(ln)))
937                                 break;
938                 }
939                 if (ln != NULL)
940                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
941         } else if (!ReadMakefile("BSDmakefile"))
942             if (!ReadMakefile("makefile"))
943                 ReadMakefile("Makefile");
944
945         ReadMakefile(".depend");
946
947         /* Install all the flags into the MAKE envariable. */
948         if (((p = Var_Value(".MAKEFLAGS", VAR_GLOBAL)) != NULL) && *p)
949                 setenv("MAKEFLAGS", p, 1);
950
951         /*
952          * For compatibility, look at the directories in the VPATH variable
953          * and add them to the search path, if the variable is defined. The
954          * variable's value is in the same format as the PATH envariable, i.e.
955          * <directory>:<directory>:<directory>...
956          */
957         if (Var_Exists("VPATH", VAR_CMD)) {
958                 /*
959                  * GCC stores string constants in read-only memory, but
960                  * Var_Subst will want to write this thing, so store it
961                  * in an array
962                  */
963                 static char VPATH[] = "${VPATH}";
964                 Buffer  *buf;
965                 char    *vpath;
966                 char    *ptr;
967                 char    savec;
968
969                 buf = Var_Subst(VPATH, VAR_CMD, FALSE);
970
971                 vpath = Buf_Data(buf);
972                 do {
973                         /* skip to end of directory */
974                         for (ptr = vpath; *ptr != ':' && *ptr != '\0'; ptr++)
975                                 ;
976
977                         /* Save terminator character so know when to stop */
978                         savec = *ptr;
979                         *ptr = '\0';
980
981                         /* Add directory to search path */
982                         Path_AddDir(&dirSearchPath, vpath);
983
984                         vpath = ptr + 1;
985                 } while (savec != '\0');
986
987                 Buf_Destroy(buf, TRUE);
988         }
989
990         /*
991          * Now that all search paths have been read for suffixes et al, it's
992          * time to add the default search path to their lists...
993          */
994         Suff_DoPaths();
995
996         /* print the initial graph, if the user requested it */
997         if (DEBUG(GRAPH1))
998                 Targ_PrintGraph(1);
999
1000         /* print the values of any variables requested by the user */
1001         if (Lst_IsEmpty(&variables)) {
1002                 /*
1003                  * Since the user has not requested that any variables
1004                  * be printed, we can build targets.
1005                  *
1006                  * Have read the entire graph and need to make a list of targets
1007                  * to create. If none was given on the command line, we consult
1008                  * the parsing module to find the main target(s) to create.
1009                  */
1010                 Lst targs = Lst_Initializer(targs);
1011
1012                 if (Lst_IsEmpty(&create))
1013                         Parse_MainName(&targs);
1014                 else
1015                         Targ_FindList(&targs, &create, TARG_CREATE);
1016
1017                 if (compatMake) {
1018                         /*
1019                          * Compat_Init will take care of creating
1020                          * all the targets as well as initializing
1021                          * the module.
1022                          */
1023                         Compat_Run(&targs);
1024                         outOfDate = 0;
1025                 } else {
1026                         /*
1027                          * Initialize job module before traversing
1028                          * the graph, now that any .BEGIN and .END
1029                          * targets have been read.  This is done
1030                          * only if the -q flag wasn't given (to
1031                          * prevent the .BEGIN from being executed
1032                          * should it exist).
1033                          */
1034                         if (!queryFlag) {
1035                                 Job_Init(jobLimit);
1036                                 jobsRunning = TRUE;
1037                         }
1038
1039                         /* Traverse the graph, checking on all the targets */
1040                         outOfDate = Make_Run(&targs);
1041                 }
1042                 Lst_Destroy(&targs, NOFREE);
1043
1044         } else {
1045                 Var_Print(&variables, expandVars);
1046         }
1047
1048         Lst_Destroy(&variables, free);
1049         Lst_Destroy(&makefiles, free);
1050         Lst_Destroy(&create, free);
1051
1052         /* print the graph now it's been processed if the user requested it */
1053         if (DEBUG(GRAPH2))
1054                 Targ_PrintGraph(2);
1055
1056         if (queryFlag && outOfDate)
1057                 return (1);
1058         else
1059                 return (0);
1060 }
1061