BSD 4_4_Lite1 release
[unix-history] / usr / src / usr.bin / make / main.c
index 4b04c9e..7b3f5a5 100644 (file)
@@ -1,33 +1,49 @@
 /*
 /*
- * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
- * Copyright (c) 1988, 1989 by Adam de Boor
+ * Copyright (c) 1988, 1989, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  * Copyright (c) 1989 by Berkeley Softworks
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Adam de Boor.
  *
  * Copyright (c) 1989 by Berkeley Softworks
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Adam de Boor.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley.  The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.12 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     8.3 (Berkeley) 3/19/94";
 #endif /* not lint */
 
 /*-
 #endif /* not lint */
 
 /*-
@@ -57,14 +73,25 @@ static char sccsid[] = "@(#)main.c  5.12 (Berkeley) %G%";
  *                             exiting.
  */
 
  *                             exiting.
  */
 
+#include <sys/types.h>
+#include <sys/time.h>
 #include <sys/param.h>
 #include <sys/param.h>
+#include <sys/resource.h>
 #include <sys/signal.h>
 #include <sys/stat.h>
 #include <sys/signal.h>
 #include <sys/stat.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <fcntl.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <stdio.h>
+#if __STDC__
+#include <stdarg.h>
+#else
 #include <varargs.h>
 #include <varargs.h>
+#endif
 #include "make.h"
 #include "make.h"
+#include "hash.h"
+#include "dir.h"
+#include "job.h"
+#include "pathnames.h"
 
 #ifndef        DEFMAXLOCAL
 #define        DEFMAXLOCAL DEFMAXJOBS
 
 #ifndef        DEFMAXLOCAL
 #define        DEFMAXLOCAL DEFMAXJOBS
@@ -77,13 +104,12 @@ time_t                     now;            /* Time at start of make */
 GNode                  *DEFAULT;       /* .DEFAULT node */
 Boolean                        allPrecious;    /* .PRECIOUS given on line by itself */
 
 GNode                  *DEFAULT;       /* .DEFAULT node */
 Boolean                        allPrecious;    /* .PRECIOUS given on line by itself */
 
-static int             printGraph;     /* -p flag */
 static Boolean         noBuiltins;     /* -r flag */
 static Lst             makefiles;      /* ordered list of makefiles to read */
 int                    maxJobs;        /* -J argument */
 static int             maxLocal;       /* -L argument */
 static Boolean         noBuiltins;     /* -r flag */
 static Lst             makefiles;      /* ordered list of makefiles to read */
 int                    maxJobs;        /* -J argument */
 static int             maxLocal;       /* -L argument */
+Boolean                        compatMake;     /* -B argument */
 Boolean                        debug;          /* -d flag */
 Boolean                        debug;          /* -d flag */
-Boolean                        noWarnings;     /* -W flag */
 Boolean                        noExecute;      /* -n flag */
 Boolean                        keepgoing;      /* -k flag */
 Boolean                        queryFlag;      /* -q flag */
 Boolean                        noExecute;      /* -n flag */
 Boolean                        keepgoing;      /* -k flag */
 Boolean                        queryFlag;      /* -q flag */
@@ -96,6 +122,10 @@ Boolean                     checkEnvFirst;  /* -e flag */
 static Boolean         jobsRunning;    /* TRUE if the jobs might be running */
 
 static Boolean         ReadMakefile();
 static Boolean         jobsRunning;    /* TRUE if the jobs might be running */
 
 static Boolean         ReadMakefile();
+static void            usage();
+
+static char *curdir;                   /* startup directory */
+static char *objdir;                   /* where we chdir'ed to */
 
 /*-
  * MainParseArgs --
 
 /*-
  * MainParseArgs --
@@ -118,11 +148,15 @@ MainParseArgs(argc, argv)
 {
        extern int optind;
        extern char *optarg;
 {
        extern int optind;
        extern char *optarg;
-       register int i;
-       register char *cp;
        char c;
 
        char c;
 
-       while((c = getopt(argc, argv, "D:I:J:L:PSWd:ef:iknp:qrstv")) != -1) {
+       optind = 1;     /* since we're called more than once */
+#ifdef notyet
+# define OPTFLAGS "BD:I:L:PSd:ef:ij:knqrst"
+#else
+# define OPTFLAGS "D:I:d:ef:ij:knqrst"
+#endif
+rearg: while ((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
                switch(c) {
                case 'D':
                        Var_Set(optarg, "1", VAR_GLOBAL);
                switch(c) {
                case 'D':
                        Var_Set(optarg, "1", VAR_GLOBAL);
@@ -134,10 +168,9 @@ MainParseArgs(argc, argv)
                        Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                        break;
                        Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                        break;
-               case 'J':
-                       maxJobs = atoi(optarg);
-                       Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
-                       Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
+#ifdef notyet
+               case 'B':
+                       compatMake = TRUE;
                        break;
                case 'L':
                        maxLocal = atoi(optarg);
                        break;
                case 'L':
                        maxLocal = atoi(optarg);
@@ -152,16 +185,13 @@ MainParseArgs(argc, argv)
                        keepgoing = FALSE;
                        Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
                        break;
                        keepgoing = FALSE;
                        Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
                        break;
-               case 'W':
-                       noWarnings = TRUE;
-                       Var_Append(MAKEFLAGS, "-W", VAR_GLOBAL);
-                       break;
+#endif
                case 'd': {
                        char *modules = optarg;
 
                case 'd': {
                        char *modules = optarg;
 
-                       while (*modules) {
+                       for (; *modules; ++modules)
                                switch (*modules) {
                                switch (*modules) {
-                               case '*':
+                               case 'A':
                                        debug = ~0;
                                        break;
                                case 'a':
                                        debug = ~0;
                                        break;
                                case 'a':
@@ -173,18 +203,25 @@ MainParseArgs(argc, argv)
                                case 'd':
                                        debug |= DEBUG_DIR;
                                        break;
                                case 'd':
                                        debug |= DEBUG_DIR;
                                        break;
+                               case 'f':
+                                       debug |= DEBUG_FOR;
+                                       break;
+                               case 'g':
+                                       if (modules[1] == '1') {
+                                               debug |= DEBUG_GRAPH1;
+                                               ++modules;
+                                       }
+                                       else if (modules[1] == '2') {
+                                               debug |= DEBUG_GRAPH2;
+                                               ++modules;
+                                       }
+                                       break;
                                case 'j':
                                        debug |= DEBUG_JOB;
                                        break;
                                case 'm':
                                        debug |= DEBUG_MAKE;
                                        break;
                                case 'j':
                                        debug |= DEBUG_JOB;
                                        break;
                                case 'm':
                                        debug |= DEBUG_MAKE;
                                        break;
-                               case 'p':
-                                       debug |= DEBUG_PARSE;
-                                       break;
-                               case 'r':
-                                       debug |= DEBUG_RMT;
-                                       break;
                                case 's':
                                        debug |= DEBUG_SUFF;
                                        break;
                                case 's':
                                        debug |= DEBUG_SUFF;
                                        break;
@@ -194,9 +231,12 @@ MainParseArgs(argc, argv)
                                case 'v':
                                        debug |= DEBUG_VAR;
                                        break;
                                case 'v':
                                        debug |= DEBUG_VAR;
                                        break;
+                               default:
+                                       (void)fprintf(stderr,
+                               "make: illegal argument to d option -- %c\n",
+                                           *modules);
+                                       usage();
                                }
                                }
-                               ++modules;
-                       }
                        Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                        break;
                        Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
                        Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
                        break;
@@ -212,6 +252,11 @@ MainParseArgs(argc, argv)
                        ignoreErrors = TRUE;
                        Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
                        break;
                        ignoreErrors = TRUE;
                        Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
                        break;
+               case 'j':
+                       maxJobs = atoi(optarg);
+                       Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
+                       Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
+                       break;
                case 'k':
                        keepgoing = TRUE;
                        Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
                case 'k':
                        keepgoing = TRUE;
                        Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
@@ -220,9 +265,6 @@ MainParseArgs(argc, argv)
                        noExecute = TRUE;
                        Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
                        break;
                        noExecute = TRUE;
                        Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
                        break;
-               case 'p':
-                       printGraph = atoi(optarg);
-                       break;
                case 'q':
                        queryFlag = TRUE;
                        /* Kind of nonsensical, wot? */
                case 'q':
                        queryFlag = TRUE;
                        /* Kind of nonsensical, wot? */
@@ -253,12 +295,19 @@ MainParseArgs(argc, argv)
         * perform them if so. Else take them to be targets and stuff them
         * on the end of the "create" list.
         */
         * perform them if so. Else take them to be targets and stuff them
         * on the end of the "create" list.
         */
-       for (argv += optind; *argv; ++argv)
+       for (argv += optind, argc -= optind; *argv; ++argv, --argc)
                if (Parse_IsVar(*argv))
                        Parse_DoVar(*argv, VAR_CMD);
                else {
                        if (!**argv)
                if (Parse_IsVar(*argv))
                        Parse_DoVar(*argv, VAR_CMD);
                else {
                        if (!**argv)
-                               Punt("Bogus argument in MainParseArgs");
+                               Punt("illegal (null) argument.");
+                       if (**argv == '-') {
+                               if ((*argv)[1])
+                                       optind = 0;     /* -flag... */
+                               else
+                                       optind = 1;     /* - */
+                               goto rearg;
+                       }
                        (void)Lst_AtEnd(create, (ClientData)*argv);
                }
 }
                        (void)Lst_AtEnd(create, (ClientData)*argv);
                }
 }
@@ -287,11 +336,13 @@ Main_ParseArgLine(line)
 
        if (line == NULL)
                return;
 
        if (line == NULL)
                return;
-       for (; *line == ' '; ++line);
+       for (; *line == ' '; ++line)
+               continue;
+       if (!*line)
+               return;
 
 
-       argv = Str_BreakString(line, " \t", "\n", &argc);
+       argv = brk_string(line, &argc);
        MainParseArgs(argc, argv);
        MainParseArgs(argc, argv);
-       Str_FreeVec(argc, argv);
 }
 
 /*-
 }
 
 /*-
@@ -311,12 +362,96 @@ Main_ParseArgLine(line)
  * Side Effects:
  *     The program exits when done. Targets are created. etc. etc. etc.
  */
  * Side Effects:
  *     The program exits when done. Targets are created. etc. etc. etc.
  */
+int
 main(argc, argv)
        int argc;
        char **argv;
 {
        Lst targs;      /* target nodes to create -- passed to Make_Init */
 main(argc, argv)
        int argc;
        char **argv;
 {
        Lst targs;      /* target nodes to create -- passed to Make_Init */
-       Boolean outOfDate;      /* FALSE if all targets up to date */
+       Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */
+       struct stat sb, sa;
+       char *p, *path, *pwd, *getenv(), *getwd();
+       char mdpath[MAXPATHLEN + 1];
+       char obpath[MAXPATHLEN + 1];
+       char cdpath[MAXPATHLEN + 1];
+
+       /*
+        * Find where we are and take care of PWD for the automounter...
+        * All this code is so that we know where we are when we start up
+        * on a different machine with pmake.
+        */
+       curdir = cdpath;
+       if (getwd(curdir) == NULL) {
+               (void)fprintf(stderr, "make: %s.\n", curdir);
+               exit(2);
+       }
+
+       if (stat(curdir, &sa) == -1) {
+           (void)fprintf(stderr, "make: %s: %s.\n",
+                         curdir, strerror(errno));
+           exit(2);
+       }
+
+       if ((pwd = getenv("PWD")) != NULL) {
+           if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
+               sa.st_dev == sb.st_dev) 
+               (void) strcpy(curdir, pwd);
+       }
+
+
+       /*
+        * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
+        * exists, change into it and build there.  Once things are
+        * initted, have to add the original directory to the search path,
+        * and modify the paths for the Makefiles apropriately.  The
+        * current directory is also placed as a variable for make scripts.
+        */
+       if (!(path = getenv("MAKEOBJDIR"))) {
+               path = _PATH_OBJDIR;
+               (void) sprintf(mdpath, "%s.%s", path, MACHINE);
+       }
+       else
+               (void) strncpy(mdpath, path, MAXPATHLEN + 1);
+       
+       if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+
+               if (chdir(mdpath)) {
+                       (void)fprintf(stderr, "make warning: %s: %s.\n",
+                                     mdpath, strerror(errno));
+                       objdir = curdir;
+               }
+               else {
+                       if (mdpath[0] != '/') {
+                               (void) sprintf(obpath, "%s/%s", curdir, mdpath);
+                               objdir = obpath;
+                       }
+                       else
+                               objdir = mdpath;
+               }
+       }
+       else {
+               if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+
+                       if (chdir(path)) {
+                               (void)fprintf(stderr, "make warning: %s: %s.\n",
+                                             path, strerror(errno));
+                               objdir = curdir;
+                       }
+                       else {
+                               if (path[0] != '/') {
+                                       (void) sprintf(obpath, "%s/%s", curdir,
+                                                      path);
+                                       objdir = obpath;
+                               }
+                               else
+                                       objdir = obpath;
+                       }
+               }
+               else
+                       objdir = curdir;
+       }
+
+       setenv("PWD", objdir, 1);
 
        create = Lst_Init(FALSE);
        makefiles = Lst_Init(FALSE);
 
        create = Lst_Init(FALSE);
        makefiles = Lst_Init(FALSE);
@@ -330,12 +465,17 @@ main(argc, argv)
        touchFlag = FALSE;              /* Actually update targets */
        usePipes = TRUE;                /* Catch child output in pipes */
        debug = 0;                      /* No debug verbosity, please. */
        touchFlag = FALSE;              /* Actually update targets */
        usePipes = TRUE;                /* Catch child output in pipes */
        debug = 0;                      /* No debug verbosity, please. */
-       noWarnings = FALSE;             /* Print warning messages */
        jobsRunning = FALSE;
 
        maxJobs = DEFMAXJOBS;           /* Set default max concurrency */
        maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
        jobsRunning = FALSE;
 
        maxJobs = DEFMAXJOBS;           /* Set default max concurrency */
        maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
+#ifdef notyet
+       compatMake = FALSE;             /* No compat mode */
+#else
+       compatMake = TRUE;              /* No compat mode */
+#endif
     
     
+
        /*
         * Initialize the parsing, directory and variable modules to prepare
         * for the reading of inclusion paths and variable settings on the
        /*
         * Initialize the parsing, directory and variable modules to prepare
         * for the reading of inclusion paths and variable settings on the
@@ -347,29 +487,36 @@ main(argc, argv)
                                 * directories */
        Var_Init();             /* As well as the lists of variables for
                                 * parsing arguments */
                                 * directories */
        Var_Init();             /* As well as the lists of variables for
                                 * parsing arguments */
+       if (objdir != curdir)
+               Dir_AddDir(dirSearchPath, curdir);
+       Var_Set(".CURDIR", curdir, VAR_GLOBAL);
+       Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
 
        /*
         * Initialize various variables.
 
        /*
         * Initialize various variables.
-        *      .PMAKE gets how we were executed.
         *      MAKE also gets this name, for compatibility
         *      .MAKEFLAGS gets set to the empty string just in case.
         *      MFLAGS also gets initialized empty, for compatibility.
         */
         *      MAKE also gets this name, for compatibility
         *      .MAKEFLAGS gets set to the empty string just in case.
         *      MFLAGS also gets initialized empty, for compatibility.
         */
-       Var_Set(".PMAKE", argv[0], VAR_GLOBAL);
        Var_Set("MAKE", argv[0], VAR_GLOBAL);
        Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
        Var_Set("MFLAGS", "", VAR_GLOBAL);
        Var_Set("MAKE", argv[0], VAR_GLOBAL);
        Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
        Var_Set("MFLAGS", "", VAR_GLOBAL);
-       Var_Set ("MACHINE", MACHINE, VAR_GLOBAL);
+#ifdef MACHINE
+       Var_Set("MACHINE", MACHINE, VAR_GLOBAL);
+#endif
+#ifdef MACHINE_ARCH
+       Var_Set("MACHINE_ARCH", MACHINE_ARCH, VAR_GLOBAL);
+#endif
 
        /*
 
        /*
-        * First snag any flags out of the PMAKE environment variable.
+        * First snag any flags out of the MAKE environment variable.
         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
         * in a different format).
         */
 #ifdef POSIX
        Main_ParseArgLine(getenv("MAKEFLAGS"));
 #else
         * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
         * in a different format).
         */
 #ifdef POSIX
        Main_ParseArgLine(getenv("MAKEFLAGS"));
 #else
-       Main_ParseArgLine(getenv("PMAKE"));
+       Main_ParseArgLine(getenv("MAKE"));
 #endif
     
        MainParseArgs(argc, argv);
 #endif
     
        MainParseArgs(argc, argv);
@@ -407,8 +554,8 @@ main(argc, argv)
         * if it was (makefile != (char *) NULL), or the default Makefile and
         * makefile, in that order, if it wasn't.
         */
         * if it was (makefile != (char *) NULL), or the default Makefile and
         * makefile, in that order, if it wasn't.
         */
-        if (!noBuiltins && !ReadMakefile(DEFSYSMK))
-               Fatal("make: no system rules (%s).", DEFSYSMK);
+        if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
+               Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
 
        if (!Lst_IsEmpty(makefiles)) {
                LstNode ln;
 
        if (!Lst_IsEmpty(makefiles)) {
                LstNode ln;
@@ -419,13 +566,16 @@ main(argc, argv)
        } else if (!ReadMakefile("makefile"))
                (void)ReadMakefile("Makefile");
 
        } else if (!ReadMakefile("makefile"))
                (void)ReadMakefile("Makefile");
 
+       (void)ReadMakefile(".depend");
+
        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL);
 
        Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL);
 
-       /* Install all the flags into the PMAKE envariable. */
+       /* Install all the flags into the MAKE envariable. */
+       if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL)) != NULL) && *p)
 #ifdef POSIX
 #ifdef POSIX
-       setenv("MAKEFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL));
+               setenv("MAKEFLAGS", p, 1);
 #else
 #else
-       setenv("PMAKE", Var_Value(MAKEFLAGS, VAR_GLOBAL));
+               setenv("MAKE", p, 1);
 #endif
 
        /*
 #endif
 
        /*
@@ -443,11 +593,12 @@ main(argc, argv)
                 */
                static char VPATH[] = "${VPATH}";
 
                 */
                static char VPATH[] = "${VPATH}";
 
-               vpath = Var_Subst(VPATH, VAR_CMD, FALSE);
+               vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
                path = vpath;
                do {
                        /* skip to end of directory */
                path = vpath;
                do {
                        /* skip to end of directory */
-                       for (cp = path; *cp != ':' && *cp != '\0'; cp++);
+                       for (cp = path; *cp != ':' && *cp != '\0'; cp++)
+                               continue;
                        /* Save terminator character so know when to stop */
                        savec = *cp;
                        *cp = '\0';
                        /* Save terminator character so know when to stop */
                        savec = *cp;
                        *cp = '\0';
@@ -465,8 +616,8 @@ main(argc, argv)
         */
        Suff_DoPaths();
 
         */
        Suff_DoPaths();
 
-       /* Print the initial graph, if the user requested it */
-       if (printGraph & 1)
+       /* print the initial graph, if the user requested it */
+       if (DEBUG(GRAPH1))
                Targ_PrintGraph(1);
 
        /*
                Targ_PrintGraph(1);
 
        /*
@@ -483,7 +634,7 @@ main(argc, argv)
  * this was original amMake -- want to allow parallelism, so put this
  * back in, eventually.
  */
  * this was original amMake -- want to allow parallelism, so put this
  * back in, eventually.
  */
-       if (0) {
+       if (!compatMake) {
                /*
                 * Initialize job module before traversing the graph, now that
                 * any .BEGIN and .END targets have been read.  This is done
                /*
                 * Initialize job module before traversing the graph, now that
                 * any .BEGIN and .END targets have been read.  This is done
@@ -506,14 +657,14 @@ main(argc, argv)
                 */
                Compat_Run(targs);
     
                 */
                Compat_Run(targs);
     
-       /* Print the graph now it's been processed if the user requested it */
-       if (printGraph & 2)
+       /* print the graph now it's been processed if the user requested it */
+       if (DEBUG(GRAPH2))
                Targ_PrintGraph(2);
 
        if (queryFlag && outOfDate)
                Targ_PrintGraph(2);
 
        if (queryFlag && outOfDate)
-               exit(1);
+               return(1);
        else
        else
-               exit(0);
+               return(0);
 }
 
 /*-
 }
 
 /*-
@@ -530,40 +681,37 @@ static Boolean
 ReadMakefile(fname)
        char *fname;            /* makefile to read */
 {
 ReadMakefile(fname)
        char *fname;            /* makefile to read */
 {
+       extern Lst parseIncPath, sysIncPath;
+       FILE *stream;
+       char *name, path[MAXPATHLEN + 1];
+
        if (!strcmp(fname, "-")) {
                Parse_File("(stdin)", stdin);
                Var_Set("MAKEFILE", "", VAR_GLOBAL);
        } else {
        if (!strcmp(fname, "-")) {
                Parse_File("(stdin)", stdin);
                Var_Set("MAKEFILE", "", VAR_GLOBAL);
        } else {
-               extern Lst parseIncPath, sysIncPath;
-               FILE *stream;
-
-               stream = fopen(fname, "r");
-               if (stream == (FILE *) NULL) {
-                       /* Look in -I directories... */
-                       char *name;
-
-                       name = Dir_FindFile(fname, parseIncPath);
-                       if (name == NULL) {
-                               /*
-                                * Last-ditch: look in system include
-                                * directories.
-                                */
-                               name = Dir_FindFile(fname, sysIncPath);
-                               if (name == NULL)
-                                       return(FALSE);
+               if ((stream = fopen(fname, "r")) != NULL)
+                       goto found;
+               /* if we've chdir'd, rebuild the path name */
+               if (curdir != objdir && *fname != '/') {
+                       (void)sprintf(path, "%s/%s", curdir, fname);
+                       if ((stream = fopen(path, "r")) != NULL) {
+                               fname = path;
+                               goto found;
                        }
                        }
-                       stream = fopen(name, "r");
-                       if (stream == (FILE *)NULL)
-                               /* Better safe than sorry... */
-                               return(FALSE);
-                       fname = name;
                }
                }
+               /* look in -I and system include directories. */
+               name = Dir_FindFile(fname, parseIncPath);
+               if (!name)
+                       name = Dir_FindFile(fname, sysIncPath);
+               if (!name || !(stream = fopen(name, "r")))
+                       return(FALSE);
+               fname = name;
                /*
                /*
-                * Set the MAKEFILE variable desired by System V fans -- the
-                * placement of the setting here means it gets set to the
-                * last makefile specified, as it is set by SysV make...
+                * set the MAKEFILE variable desired by System V fans -- the
+                * placement of the setting here means it gets set to the last
+                * makefile specified, as it is set by SysV make.
                 */
                 */
-               Var_Set("MAKEFILE", fname, VAR_GLOBAL);
+found:         Var_Set("MAKEFILE", fname, VAR_GLOBAL);
                Parse_File(fname, stream);
                (void)fclose(stream);
        }
                Parse_File(fname, stream);
                (void)fclose(stream);
        }
@@ -582,14 +730,22 @@ ReadMakefile(fname)
  */
 /* VARARGS */
 void
  */
 /* VARARGS */
 void
+#if __STDC__
+Error(const char *fmt, ...)
+#else
 Error(va_alist)
        va_dcl
 Error(va_alist)
        va_dcl
+#endif
 {
        va_list ap;
 {
        va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
        char *fmt;
 
        va_start(ap);
        fmt = va_arg(ap, char *);
        char *fmt;
 
        va_start(ap);
        fmt = va_arg(ap, char *);
+#endif
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
@@ -609,23 +765,31 @@ Error(va_alist)
  */
 /* VARARGS */
 void
  */
 /* VARARGS */
 void
+#if __STDC__
+Fatal(const char *fmt, ...)
+#else
 Fatal(va_alist)
        va_dcl
 Fatal(va_alist)
        va_dcl
+#endif
 {
        va_list ap;
 {
        va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
        char *fmt;
 
        char *fmt;
 
+       va_start(ap);
+       fmt = va_arg(ap, char *);
+#endif
        if (jobsRunning)
                Job_Wait();
 
        if (jobsRunning)
                Job_Wait();
 
-       va_start(ap);
-       fmt = va_arg(ap, char *);
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
        (void)fflush(stderr);
 
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
        (void)fflush(stderr);
 
-       if (printGraph & 2)
+       if (DEBUG(GRAPH2))
                Targ_PrintGraph(2);
        exit(2);                /* Not 1 so -q can distinguish error */
 }
                Targ_PrintGraph(2);
        exit(2);                /* Not 1 so -q can distinguish error */
 }
@@ -643,14 +807,24 @@ Fatal(va_alist)
  */
 /* VARARGS */
 void
  */
 /* VARARGS */
 void
+#if __STDC__
+Punt(const char *fmt, ...)
+#else
 Punt(va_alist)
        va_dcl
 Punt(va_alist)
        va_dcl
+#endif
 {
        va_list ap;
 {
        va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
        char *fmt;
 
        va_start(ap);
        fmt = va_arg(ap, char *);
        char *fmt;
 
        va_start(ap);
        fmt = va_arg(ap, char *);
+#endif
+
+       (void)fprintf(stderr, "make: ");
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
        (void)vfprintf(stderr, fmt, ap);
        va_end(ap);
        (void)fprintf(stderr, "\n");
@@ -674,7 +848,7 @@ DieHorribly()
 {
        if (jobsRunning)
                Job_AbortAll();
 {
        if (jobsRunning)
                Job_AbortAll();
-       if (printGraph & 2)
+       if (DEBUG(GRAPH2))
                Targ_PrintGraph(2);
        exit(2);                /* Not 1, so -q can distinguish error */
 }
                Targ_PrintGraph(2);
        exit(2);                /* Not 1, so -q can distinguish error */
 }
@@ -697,10 +871,41 @@ Finish(errors)
        Fatal("%d error%s", errors, errors == 1 ? "" : "s");
 }
 
        Fatal("%d error%s", errors, errors == 1 ? "" : "s");
 }
 
+/*
+ * emalloc --
+ *     malloc, but die on error.
+ */
+char *
+emalloc(len)
+       u_int len;
+{
+       char *p;
+
+       if (!(p = malloc(len)))
+               enomem();
+       return(p);
+}
+
+/*
+ * enomem --
+ *     die when out of memory.
+ */
+void
+enomem()
+{
+       (void)fprintf(stderr, "make: %s.\n", strerror(errno));
+       exit(2);
+}
+
+/*
+ * usage --
+ *     exit with usage message
+ */
+static void
 usage()
 {
        (void)fprintf(stderr,
 usage()
 {
        (void)fprintf(stderr,
-"usage: make [-PSWeiknqrstvh] [-D define] [-I include] [-J max_target] \n\t\
-[-L max_local] [-d debug] [-f file] [-p #]\n");
+"usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
+            [-I directory] [-j max_jobs] [variable=value]\n");
        exit(2);
 }
        exit(2);
 }