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