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