Simplify code by using IF_DRAIN.
[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.90 2005/05/05 09:08: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 Boolean         jobsRunning;    /* TRUE if the jobs might be running */
125 Boolean         keepgoing;      /* -k flag */
126 Boolean         noExecute;      /* -n flag */
127 Boolean         queryFlag;      /* -q flag */
128 Boolean         touchFlag;      /* -t flag */
129 Boolean         usePipes;       /* !-P flag */
130 uint32_t        warn_flags;     /* actual warning flags */
131 uint32_t        warn_cmd;       /* command line warning flags */
132 uint32_t        warn_nocmd;     /* command line no-warning flags */
133
134 time_t          now;            /* Time at start of make */
135 struct GNode    *DEFAULT;       /* .DEFAULT node */
136
137 /**
138  * Exit with usage message.
139  */
140 static void
141 usage(void)
142 {
143         fprintf(stderr,
144             "usage: make [-BPSXeiknqrstv] [-C directory] [-D variable]\n"
145             "\t[-d flags] [-E variable] [-f makefile] [-I directory]\n"
146             "\t[-j max_jobs] [-m directory] [-V variable]\n"
147             "\t[variable=value] [target ...]\n");
148         exit(2);
149 }
150
151 /**
152  * MFLAGS_append
153  *      Append a flag with an optional argument to MAKEFLAGS and MFLAGS
154  */
155 static void
156 MFLAGS_append(const char *flag, char *arg)
157 {
158         char *str;
159
160         Var_Append(".MAKEFLAGS", flag, VAR_GLOBAL);
161         if (arg != NULL) {
162                 str = MAKEFLAGS_quote(arg);
163                 Var_Append(".MAKEFLAGS", str, VAR_GLOBAL);
164                 free(str);
165         }
166
167         Var_Append("MFLAGS", flag, VAR_GLOBAL);
168         if (arg != NULL) {
169                 str = MAKEFLAGS_quote(arg);
170                 Var_Append("MFLAGS", str, VAR_GLOBAL);
171                 free(str);
172         }
173 }
174
175 /**
176  * Open and parse the given makefile.
177  *
178  * Results:
179  *      TRUE if ok. FALSE if couldn't open file.
180  */
181 static Boolean
182 ReadMakefile(const char p[])
183 {
184         char *fname;                    /* makefile to read */
185         FILE *stream;
186         char *name, path[MAXPATHLEN];
187         char *MAKEFILE;
188         int setMAKEFILE;
189
190         /* XXX - remove this once constification is done */
191         fname = estrdup(p);
192
193         if (!strcmp(fname, "-")) {
194                 Parse_File("(stdin)", stdin);
195                 Var_SetGlobal("MAKEFILE", "");
196         } else {
197                 setMAKEFILE = strcmp(fname, ".depend");
198
199                 /* if we've chdir'd, rebuild the path name */
200                 if (curdir != objdir && *fname != '/') {
201                         snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname);
202                         /*
203                          * XXX The realpath stuff breaks relative includes
204                          * XXX in some cases.   The problem likely is in
205                          * XXX parse.c where it does special things in
206                          * XXX ParseDoInclude if the file is relateive
207                          * XXX or absolute and not a system file.  There
208                          * XXX it assumes that if the current file that's
209                          * XXX being included is absolute, that any files
210                          * XXX that it includes shouldn't do the -I path
211                          * XXX stuff, which is inconsistant with historical
212                          * XXX behavior.  However, I can't pentrate the mists
213                          * XXX further, so I'm putting this workaround in
214                          * XXX here until such time as the underlying bug
215                          * XXX can be fixed.
216                          */
217 #if THIS_BREAKS_THINGS
218                         if (realpath(path, path) != NULL &&
219                             (stream = fopen(path, "r")) != NULL) {
220                                 MAKEFILE = fname;
221                                 fname = path;
222                                 goto found;
223                         }
224                 } else if (realpath(fname, path) != NULL) {
225                         MAKEFILE = fname;
226                         fname = path;
227                         if ((stream = fopen(fname, "r")) != NULL)
228                                 goto found;
229                 }
230 #else
231                         if ((stream = fopen(path, "r")) != NULL) {
232                                 MAKEFILE = fname;
233                                 fname = path;
234                                 goto found;
235                         }
236                 } else {
237                         MAKEFILE = fname;
238                         if ((stream = fopen(fname, "r")) != NULL)
239                                 goto found;
240                 }
241 #endif
242                 /* look in -I and system include directories. */
243                 name = Path_FindFile(fname, &parseIncPath);
244                 if (!name)
245                         name = Path_FindFile(fname, &sysIncPath);
246                 if (!name || !(stream = fopen(name, "r")))
247                         return (FALSE);
248                 MAKEFILE = fname = name;
249                 /*
250                  * set the MAKEFILE variable desired by System V fans -- the
251                  * placement of the setting here means it gets set to the last
252                  * makefile specified, as it is set by SysV make.
253                  */
254 found:
255                 if (setMAKEFILE)
256                         Var_SetGlobal("MAKEFILE", MAKEFILE);
257                 Parse_File(fname, stream);
258                 fclose(stream);
259         }
260         return (TRUE);
261 }
262
263 /**
264  * Main_ParseWarn
265  *
266  *      Handle argument to warning option.
267  */
268 int
269 Main_ParseWarn(const char *arg, int iscmd)
270 {
271         int i, neg;
272
273         static const struct {
274                 const char      *option;
275                 uint32_t        flag;
276         } options[] = {
277                 { "dirsyntax",  WARN_DIRSYNTAX },
278                 { NULL,         0 }
279         };
280
281         neg = 0;
282         if (arg[0] == 'n' && arg[1] == 'o') {
283                 neg = 1;
284                 arg += 2;
285         }
286
287         for (i = 0; options[i].option != NULL; i++)
288                 if (strcmp(arg, options[i].option) == 0)
289                         break;
290
291         if (options[i].option == NULL)
292                 /* unknown option */
293                 return (-1);
294
295         if (iscmd) {
296                 if (!neg) {
297                         warn_cmd |= options[i].flag;
298                         warn_nocmd &= ~options[i].flag;
299                         warn_flags |= options[i].flag;
300                 } else {
301                         warn_nocmd |= options[i].flag;
302                         warn_cmd &= ~options[i].flag;
303                         warn_flags &= ~options[i].flag;
304                 }
305         } else {
306                 if (!neg) {
307                         warn_flags |= (options[i].flag & ~warn_nocmd);
308                 } else {
309                         warn_flags &= ~(options[i].flag | warn_cmd);
310                 }
311         }
312         return (0);
313 }
314
315 /**
316  * MainParseArgs
317  *      Parse a given argument vector. Called from main() and from
318  *      Main_ParseArgLine() when the .MAKEFLAGS target is used.
319  *
320  *      XXX: Deal with command line overriding .MAKEFLAGS in makefile
321  *
322  * Side Effects:
323  *      Various global and local flags will be set depending on the flags
324  *      given
325  */
326 static void
327 MainParseArgs(int argc, char **argv)
328 {
329         int c;
330         Boolean found_dd = FALSE;
331
332 rearg:
333         optind = 1;     /* since we're called more than once */
334         optreset = 1;
335 #define OPTFLAGS "ABC:D:E:I:PSV:Xd:ef:ij:km:nqrstvx:"
336         for (;;) {
337                 if ((optind < argc) && strcmp(argv[optind], "--") == 0) {
338                         found_dd = TRUE;
339                 }
340                 if ((c = getopt(argc, argv, OPTFLAGS)) == -1) {
341                         break;
342                 }
343                 switch(c) {
344
345                 case 'A':
346                         arch_fatal = FALSE;
347                         MFLAGS_append("-A", NULL);
348                         break;
349                 case 'C':
350                         if (chdir(optarg) == -1)
351                                 err(1, "chdir %s", optarg);
352                         break;
353                 case 'D':
354                         Var_SetGlobal(optarg, "1");
355                         MFLAGS_append("-D", optarg);
356                         break;
357                 case 'I':
358                         Parse_AddIncludeDir(optarg);
359                         MFLAGS_append("-I", optarg);
360                         break;
361                 case 'V':
362                         Lst_AtEnd(&variables, estrdup(optarg));
363                         MFLAGS_append("-V", optarg);
364                         break;
365                 case 'X':
366                         expandVars = FALSE;
367                         break;
368                 case 'B':
369                         compatMake = TRUE;
370                         MFLAGS_append("-B", NULL);
371                         unsetenv("MAKE_JOBS_FIFO");
372                         break;
373                 case 'P':
374                         usePipes = FALSE;
375                         MFLAGS_append("-P", NULL);
376                         break;
377                 case 'S':
378                         keepgoing = FALSE;
379                         MFLAGS_append("-S", NULL);
380                         break;
381                 case 'd': {
382                         char *modules = optarg;
383
384                         for (; *modules; ++modules)
385                                 switch (*modules) {
386                                 case 'A':
387                                         debug = ~0;
388                                         break;
389                                 case 'a':
390                                         debug |= DEBUG_ARCH;
391                                         break;
392                                 case 'c':
393                                         debug |= DEBUG_COND;
394                                         break;
395                                 case 'd':
396                                         debug |= DEBUG_DIR;
397                                         break;
398                                 case 'f':
399                                         debug |= DEBUG_FOR;
400                                         break;
401                                 case 'g':
402                                         if (modules[1] == '1') {
403                                                 debug |= DEBUG_GRAPH1;
404                                                 ++modules;
405                                         }
406                                         else if (modules[1] == '2') {
407                                                 debug |= DEBUG_GRAPH2;
408                                                 ++modules;
409                                         }
410                                         break;
411                                 case 'j':
412                                         debug |= DEBUG_JOB;
413                                         break;
414                                 case 'l':
415                                         debug |= DEBUG_LOUD;
416                                         break;
417                                 case 'm':
418                                         debug |= DEBUG_MAKE;
419                                         break;
420                                 case 's':
421                                         debug |= DEBUG_SUFF;
422                                         break;
423                                 case 't':
424                                         debug |= DEBUG_TARG;
425                                         break;
426                                 case 'v':
427                                         debug |= DEBUG_VAR;
428                                         break;
429                                 default:
430                                         warnx("illegal argument to d option "
431                                             "-- %c", *modules);
432                                         usage();
433                                 }
434                         MFLAGS_append("-d", optarg);
435                         break;
436                 }
437                 case 'E':
438                         Lst_AtEnd(&envFirstVars, estrdup(optarg));
439                         MFLAGS_append("-E", optarg);
440                         break;
441                 case 'e':
442                         checkEnvFirst = TRUE;
443                         MFLAGS_append("-e", NULL);
444                         break;
445                 case 'f':
446                         Lst_AtEnd(&makefiles, estrdup(optarg));
447                         break;
448                 case 'i':
449                         ignoreErrors = TRUE;
450                         MFLAGS_append("-i", NULL);
451                         break;
452                 case 'j': {
453                         char *endptr;
454
455                         forceJobs = TRUE;
456                         maxJobs = strtol(optarg, &endptr, 10);
457                         if (maxJobs <= 0 || *endptr != '\0') {
458                                 warnx("illegal number, -j argument -- %s",
459                                     optarg);
460                                 usage();
461                         }
462                         MFLAGS_append("-j", optarg);
463                         break;
464                 }
465                 case 'k':
466                         keepgoing = TRUE;
467                         MFLAGS_append("-k", NULL);
468                         break;
469                 case 'm':
470                         Path_AddDir(&sysIncPath, optarg);
471                         MFLAGS_append("-m", optarg);
472                         break;
473                 case 'n':
474                         noExecute = TRUE;
475                         MFLAGS_append("-n", NULL);
476                         break;
477                 case 'q':
478                         queryFlag = TRUE;
479                         /* Kind of nonsensical, wot? */
480                         MFLAGS_append("-q", NULL);
481                         break;
482                 case 'r':
483                         noBuiltins = TRUE;
484                         MFLAGS_append("-r", NULL);
485                         break;
486                 case 's':
487                         beSilent = TRUE;
488                         MFLAGS_append("-s", NULL);
489                         break;
490                 case 't':
491                         touchFlag = TRUE;
492                         MFLAGS_append("-t", NULL);
493                         break;
494                 case 'v':
495                         beVerbose = TRUE;
496                         MFLAGS_append("-v", NULL);
497                         break;
498                 case 'x':
499                         if (Main_ParseWarn(optarg, 1) != -1)
500                                 MFLAGS_append("-x", optarg);
501                         break;
502                                 
503                 default:
504                 case '?':
505                         usage();
506                 }
507         }
508         argv += optind;
509         argc -= optind;
510
511         oldVars = TRUE;
512
513         /*
514          * Parse the rest of the arguments.
515          *      o Check for variable assignments and perform them if so.
516          *      o Check for more flags and restart getopt if so.
517          *      o Anything else is taken to be a target and added
518          *        to the end of the "create" list.
519          */
520         for (; *argv != NULL; ++argv, --argc) {
521                 if (Parse_IsVar(*argv)) {
522                         char *ptr = MAKEFLAGS_quote(*argv);
523
524                         Var_Append(".MAKEFLAGS", ptr, VAR_GLOBAL);
525                         Parse_DoVar(*argv, VAR_CMD);
526                         free(ptr);
527
528                 } else if ((*argv)[0] == '-') {
529                         if ((*argv)[1] == '\0') {
530                                 /*
531                                  * (*argv) is a single dash, so we
532                                  * just ignore it.
533                                  */
534                         } else if (found_dd) {
535                                 /*
536                                  * Double dash has been found, ignore
537                                  * any more options.  But what do we do
538                                  * with it?  For now treat it like a target.
539                                  */
540                                 Lst_AtEnd(&create, estrdup(*argv));
541                         } else {
542                                 /*
543                                  * (*argv) is a -flag, so backup argv and
544                                  * argc.  getopt() expects options to start
545                                  * in the 2nd position.
546                                  */
547                                 argc++;
548                                 argv--;
549                                 goto rearg;
550                         }
551
552                 } else if ((*argv)[0] == '\0') {
553                         Punt("illegal (null) argument.");
554
555                 } else {
556                         Lst_AtEnd(&create, estrdup(*argv));
557                 }
558         }
559 }
560
561 /**
562  * Main_ParseArgLine
563  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
564  *      is encountered and by main() when reading the .MAKEFLAGS envariable.
565  *      Takes a line of arguments and breaks it into its
566  *      component words and passes those words and the number of them to the
567  *      MainParseArgs function.
568  *      The line should have all its leading whitespace removed.
569  *
570  * Side Effects:
571  *      Only those that come from the various arguments.
572  */
573 void
574 Main_ParseArgLine(char *line, int mflags)
575 {
576         ArgArray        aa;
577
578         if (line == NULL)
579                 return;
580         for (; *line == ' '; ++line)
581                 continue;
582         if (!*line)
583                 return;
584
585         if (mflags) {
586                 MAKEFLAGS_break(&aa, line);
587         } else {
588                 brk_string(&aa, line, TRUE);
589         }
590         MainParseArgs(aa.argc, aa.argv);
591         ArgArray_Done(&aa);
592 }
593
594 static char *
595 chdir_verify_path(const char *path, char *obpath)
596 {
597         struct stat sb;
598
599         if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
600                 if (chdir(path) == -1 || getcwd(obpath, MAXPATHLEN) == NULL) {
601                         warn("warning: %s", path);
602                         return (NULL);
603                 }
604                 return (obpath);
605         }
606
607         return (NULL);
608 }
609
610 /**
611  * In lieu of a good way to prevent every possible looping in make(1), stop
612  * there from being more than MKLVL_MAXVAL processes forked by make(1), to
613  * prevent a forkbomb from happening, in a dumb and mechanical way.
614  *
615  * Side Effects:
616  *      Creates or modifies enviornment variable MKLVL_ENVVAR via setenv().
617  */
618 static void
619 check_make_level(void)
620 {
621 #ifdef WANT_ENV_MKLVL
622         char    *value = getenv(MKLVL_ENVVAR);
623         int     level = (value == NULL) ? 0 : atoi(value);
624
625         if (level < 0) {
626                 errc(2, EAGAIN, "Invalid value for recursion level (%d).",
627                     level);
628         } else if (level > MKLVL_MAXVAL) {
629                 errc(2, EAGAIN, "Max recursion level (%d) exceeded.",
630                     MKLVL_MAXVAL);
631         } else {
632                 char new_value[32];
633                 sprintf(new_value, "%d", level + 1);
634                 setenv(MKLVL_ENVVAR, new_value, 1);
635         }
636 #endif /* WANT_ENV_MKLVL */
637 }
638
639 /**
640  * main
641  *      The main function, for obvious reasons. Initializes variables
642  *      and a few modules, then parses the arguments give it in the
643  *      environment and on the command line. Reads the system makefile
644  *      followed by either Makefile, makefile or the file given by the
645  *      -f argument. Sets the .MAKEFLAGS PMake variable based on all the
646  *      flags it has received by then uses either the Make or the Compat
647  *      module to create the initial list of targets.
648  *
649  * Results:
650  *      If -q was given, exits -1 if anything was out-of-date. Else it exits
651  *      0.
652  *
653  * Side Effects:
654  *      The program exits when done. Targets are created. etc. etc. etc.
655  */
656 int
657 main(int argc, char **argv)
658 {
659         const char *machine;
660         const char *machine_arch;
661         const char *machine_cpu;
662         Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
663         char *p, *p1;
664         const char *pathp;
665         const char *path;
666         char mdpath[MAXPATHLEN];
667         char obpath[MAXPATHLEN];
668         char cdpath[MAXPATHLEN];
669         char *cp = NULL, *start;
670
671         /*
672          * Initialize file global variables.
673          */
674         expandVars = TRUE;
675         noBuiltins = FALSE;             /* Read the built-in rules */
676         forceJobs = FALSE;              /* No -j flag */
677         curdir = cdpath;
678
679         /*
680          * Initialize program global variables.
681          */
682         beSilent = FALSE;               /* Print commands as executed */
683         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */
684         noExecute = FALSE;              /* Execute all commands */
685         keepgoing = FALSE;              /* Stop on error */
686         allPrecious = FALSE;            /* Remove targets when interrupted */
687         queryFlag = FALSE;              /* This is not just a check-run */
688         touchFlag = FALSE;              /* Actually update targets */
689         usePipes = TRUE;                /* Catch child output in pipes */
690         debug = 0;                      /* No debug verbosity, please. */
691         jobsRunning = FALSE;
692
693         maxJobs = DEFMAXJOBS;
694         compatMake = FALSE;             /* No compat mode */
695
696         check_make_level();
697
698 #ifdef RLIMIT_NOFILE
699         /*
700          * get rid of resource limit on file descriptors
701          */
702         {
703                 struct rlimit rl;
704                 if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
705                         err(2, "getrlimit");
706                 }
707                 rl.rlim_cur = rl.rlim_max;
708                 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
709                         err(2, "setrlimit");
710                 }
711         }
712 #endif
713         /*
714          * Get the name of this type of MACHINE from utsname
715          * so we can share an executable for similar machines.
716          * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
717          *
718          * Note that while MACHINE is decided at run-time,
719          * MACHINE_ARCH is always known at compile time.
720          */
721         if ((machine = getenv("MACHINE")) == NULL) {
722 #ifdef MACHINE
723                 machine = MACHINE;
724 #else
725                 static struct utsname utsname;
726
727                 if (uname(&utsname) == -1)
728                         err(2, "uname");
729                 machine = utsname.machine;
730 #endif
731         }
732
733         if ((machine_arch = getenv("MACHINE_ARCH")) == NULL) {
734 #ifdef MACHINE_ARCH
735                 machine_arch = MACHINE_ARCH;
736 #else
737                 machine_arch = "unknown";
738 #endif
739         }
740
741         /*
742          * Set machine_cpu to the minumum supported CPU revision based
743          * on the target architecture, if not already set.
744          */
745         if ((machine_cpu = getenv("MACHINE_CPU")) == NULL) {
746                 if (!strcmp(machine_arch, "i386"))
747                         machine_cpu = "i386";
748                 else if (!strcmp(machine_arch, "alpha"))
749                         machine_cpu = "ev4";
750                 else
751                         machine_cpu = "unknown";
752         }
753
754         /*
755          * Initialize the parsing, directory and variable modules to prepare
756          * for the reading of inclusion paths and variable settings on the
757          * command line
758          */
759         Proc_Init();
760
761         Dir_Init();             /* Initialize directory structures so -I flags
762                                  * can be processed correctly */
763         Var_Init(environ);      /* As well as the lists of variables for
764                                  * parsing arguments */
765
766         /*
767          * Initialize various variables.
768          *      MAKE also gets this name, for compatibility
769          *      .MAKEFLAGS gets set to the empty string just in case.
770          *      MFLAGS also gets initialized empty, for compatibility.
771          */
772         Var_SetGlobal("MAKE", argv[0]);
773         Var_SetGlobal(".MAKEFLAGS", "");
774         Var_SetGlobal("MFLAGS", "");
775         Var_SetGlobal("MACHINE", machine);
776         Var_SetGlobal("MACHINE_ARCH", machine_arch);
777         Var_SetGlobal("MACHINE_CPU", machine_cpu);
778 #ifdef MAKE_VERSION
779         Var_SetGlobal("MAKE_VERSION", MAKE_VERSION);
780 #endif
781
782         /*
783          * First snag things out of the MAKEFLAGS environment
784          * variable.  Then parse the command line arguments.
785          */
786         Main_ParseArgLine(getenv("MAKEFLAGS"), 1);
787
788         MainParseArgs(argc, argv);
789
790         /*
791          * Find where we are...
792          */
793         if (getcwd(curdir, MAXPATHLEN) == NULL)
794                 err(2, NULL);
795
796         {
797         struct stat sa;
798
799         if (stat(curdir, &sa) == -1)
800             err(2, "%s", curdir);
801         }
802
803         /*
804          * The object directory location is determined using the
805          * following order of preference:
806          *
807          *      1. MAKEOBJDIRPREFIX`cwd`
808          *      2. MAKEOBJDIR
809          *      3. PATH_OBJDIR.${MACHINE}
810          *      4. PATH_OBJDIR
811          *      5. PATH_OBJDIRPREFIX`cwd`
812          *
813          * If one of the first two fails, use the current directory.
814          * If the remaining three all fail, use the current directory.
815          *
816          * Once things are initted,
817          * have to add the original directory to the search path,
818          * and modify the paths for the Makefiles apropriately.  The
819          * current directory is also placed as a variable for make scripts.
820          */
821         if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
822                 if (!(path = getenv("MAKEOBJDIR"))) {
823                         path = PATH_OBJDIR;
824                         pathp = PATH_OBJDIRPREFIX;
825                         snprintf(mdpath, MAXPATHLEN, "%s.%s", path, machine);
826                         if (!(objdir = chdir_verify_path(mdpath, obpath)))
827                                 if (!(objdir=chdir_verify_path(path, obpath))) {
828                                         snprintf(mdpath, MAXPATHLEN,
829                                                         "%s%s", pathp, curdir);
830                                         if (!(objdir=chdir_verify_path(mdpath,
831                                                                        obpath)))
832                                                 objdir = curdir;
833                                 }
834                 }
835                 else if (!(objdir = chdir_verify_path(path, obpath)))
836                         objdir = curdir;
837         }
838         else {
839                 snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
840                 if (!(objdir = chdir_verify_path(mdpath, obpath)))
841                         objdir = curdir;
842         }
843         Dir_InitDot();          /* Initialize the "." directory */
844         if (objdir != curdir)
845                 Path_AddDir(&dirSearchPath, curdir);
846         Var_SetGlobal(".DIRECTIVE_MAKEENV", "YES");
847         Var_SetGlobal(".ST_EXPORTVAR", "YES");
848         Var_SetGlobal(".CURDIR", curdir);
849         Var_SetGlobal(".OBJDIR", objdir);
850
851         if (getenv("MAKE_JOBS_FIFO") != NULL)
852                 forceJobs = TRUE;
853         /*
854          * Be compatible if user did not specify -j and did not explicitly
855          * turned compatibility on
856          */
857         if (!compatMake && !forceJobs)
858                 compatMake = TRUE;
859
860         /*
861          * Initialize target and suffix modules in preparation for
862          * parsing the makefile(s)
863          */
864         Targ_Init();
865         Suff_Init();
866
867         DEFAULT = NULL;
868         time(&now);
869
870         /*
871          * Set up the .TARGETS variable to contain the list of targets to be
872          * created. If none specified, make the variable empty -- the parser
873          * will fill the thing in with the default or .MAIN target.
874          */
875         if (Lst_IsEmpty(&create)) {
876                 Var_SetGlobal(".TARGETS", "");
877         } else {
878                 LstNode *ln;
879
880                 for (ln = Lst_First(&create); ln != NULL; ln = Lst_Succ(ln)) {
881                         char *name = Lst_Datum(ln);
882
883                         Var_Append(".TARGETS", name, VAR_GLOBAL);
884                 }
885         }
886
887
888         /*
889          * If no user-supplied system path was given (through the -m option)
890          * add the directories from the DEFSYSPATH (more than one may be given
891          * as dir1:...:dirn) to the system include path.
892          */
893         if (TAILQ_EMPTY(&sysIncPath)) {
894                 char syspath[] = PATH_DEFSYSPATH;
895
896                 for (start = syspath; *start != '\0'; start = cp) {
897                         for (cp = start; *cp != '\0' && *cp != ':'; cp++)
898                                 continue;
899                         if (*cp == '\0') {
900                                 Path_AddDir(&sysIncPath, start);
901                         } else {
902                                 *cp++ = '\0';
903                                 Path_AddDir(&sysIncPath, start);
904                         }
905                 }
906         }
907
908         /*
909          * Read in the built-in rules first, followed by the specified
910          * makefile, if it was (makefile != (char *) NULL), or the default
911          * Makefile and makefile, in that order, if it wasn't.
912          */
913         if (!noBuiltins) {
914                 /* Path of sys.mk */
915                 Lst sysMkPath = Lst_Initializer(sysMkPath);
916                 LstNode *ln;
917                 char    defsysmk[] = PATH_DEFSYSMK;
918
919                 Path_Expand(defsysmk, &sysIncPath, &sysMkPath);
920                 if (Lst_IsEmpty(&sysMkPath))
921                         Fatal("make: no system rules (%s).", PATH_DEFSYSMK);
922                 LST_FOREACH(ln, &sysMkPath) {
923                         if (!ReadMakefile(Lst_Datum(ln)))
924                                 break;
925                 }
926                 if (ln != NULL)
927                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
928                 Lst_Destroy(&sysMkPath, free);
929         }
930
931         if (!Lst_IsEmpty(&makefiles)) {
932                 LstNode *ln;
933
934                 LST_FOREACH(ln, &makefiles) {
935                         if (!ReadMakefile(Lst_Datum(ln)))
936                                 break;
937                 }
938                 if (ln != NULL)
939                         Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
940         } else if (!ReadMakefile("BSDmakefile"))
941             if (!ReadMakefile("makefile"))
942                 ReadMakefile("Makefile");
943
944         ReadMakefile(".depend");
945
946         /* Install all the flags into the MAKE envariable. */
947         if (((p = Var_Value(".MAKEFLAGS", VAR_GLOBAL, &p1)) != NULL) && *p)
948                 setenv("MAKEFLAGS", p, 1);
949         free(p1);
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(maxJobs);
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