home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / win3 / nt / source.exe / POSIX / MAKE / MAIN.C < prev    next >
C/C++ Source or Header  |  1993-07-01  |  22KB  |  843 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
  3.  * Copyright (c) 1988, 1989 by Adam de Boor
  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.  
  39. #ifdef DF_POSIX
  40. #include <misc.h>
  41. #include <bsdlib.h>
  42. #endif
  43.  
  44. #ifndef lint
  45. char copyright[] =
  46. "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
  47.  All rights reserved.\n";
  48. #endif /* not lint */
  49.  
  50. #ifndef lint
  51. static char sccsid[] = "@(#)main.c    5.25 (Berkeley) 4/1/91";
  52. #endif /* not lint */
  53.  
  54. /*-
  55.  * main.c --
  56.  *    The main file for this entire program. Exit routines etc
  57.  *    reside here.
  58.  *
  59.  * Utility functions defined in this file:
  60.  *    Main_ParseArgLine    Takes a line of arguments, breaks them and
  61.  *                treats them as if they were given when first
  62.  *                invoked. Used by the parse module to implement
  63.  *                the .MFLAGS target.
  64.  *
  65.  *    Error            Print a tagged error message. The global
  66.  *                MAKE variable must have been defined. This
  67.  *                takes a format string and two optional
  68.  *                arguments for it.
  69.  *
  70.  *    Fatal            Print an error message and exit. Also takes
  71.  *                a format string and two arguments.
  72.  *
  73.  *    Punt            Aborts all jobs and exits with a message. Also
  74.  *                takes a format string and two arguments.
  75.  *
  76.  *    Finish            Finish things up by printing the number of
  77.  *                errors which occured, as passed to it, and
  78.  *                exiting.
  79.  */
  80.  
  81. #ifdef _POSIX_SOURCE
  82. #include <signal.h>
  83. #else
  84. #include <sys/param.h>
  85. #include <sys/signal.h>
  86. #endif
  87. #include <sys/stat.h>
  88. #include <errno.h>
  89. #include <fcntl.h>
  90. #include <stdio.h>
  91. #include <varargs.h>
  92. #include "make.h"
  93. #include "pathnames.h"
  94.  
  95. #ifndef    DEFMAXLOCAL
  96. #define    DEFMAXLOCAL DEFMAXJOBS
  97. #endif    DEFMAXLOCAL
  98.  
  99. #define    MAKEFLAGS    ".MAKEFLAGS"
  100. /* Added by CSP 29 June 93 */
  101. char *mk_ptr, *fn_ptr;
  102.  
  103. Lst            create;        /* Targets to be made */
  104. time_t            now;        /* Time at start of make */
  105. GNode            *DEFAULT;    /* .DEFAULT node */
  106. Boolean            allPrecious;    /* .PRECIOUS given on line by itself */
  107.  
  108. static Boolean        noBuiltins;    /* -r flag */
  109. static Lst        makefiles;    /* ordered list of makefiles to read */
  110. int            maxJobs;    /* -J argument */
  111. static int        maxLocal;    /* -L argument */
  112. Boolean            debug;        /* -d flag */
  113. Boolean            noExecute;    /* -n flag */
  114. Boolean            keepgoing;    /* -k flag */
  115. Boolean            queryFlag;    /* -q flag */
  116. Boolean            touchFlag;    /* -t flag */
  117. Boolean            usePipes;    /* !-P flag */
  118. Boolean            ignoreErrors;    /* -i flag */
  119. Boolean            beSilent;    /* -s flag */
  120. Boolean            oldVars;    /* variable substitution style */
  121. Boolean            checkEnvFirst;    /* -e flag */
  122. static Boolean        jobsRunning;    /* TRUE if the jobs might be running */
  123.  
  124. static Boolean        ReadMakefile();
  125.  
  126. static char *curdir;            /* if chdir'd for an architecture */
  127.  
  128. /*-
  129.  * MainParseArgs --
  130.  *    Parse a given argument vector. Called from main() and from
  131.  *    Main_ParseArgLine() when the .MAKEFLAGS target is used.
  132.  *
  133.  *    XXX: Deal with command line overriding .MAKEFLAGS in makefile
  134.  *
  135.  * Results:
  136.  *    None
  137.  *
  138.  * Side Effects:
  139.  *    Various global and local flags will be set depending on the flags
  140.  *    given
  141.  */
  142. static void
  143. MainParseArgs(argc, argv)
  144.     int argc;
  145.     char **argv;
  146. {
  147.     extern int optind;
  148.     extern char *optarg;
  149.     register int i;
  150.     register char *cp;
  151.     char c;
  152.  
  153.     optind = 1;    /* since we're called more than once */
  154. rearg:    while((c = getopt(argc, argv, "D:I:d:ef:ij:knqrst")) != EOF) {
  155.         switch(c) {
  156.         case 'D':
  157.             Var_Set(optarg, "1", VAR_GLOBAL);
  158.             Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
  159.             Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
  160.             break;
  161.         case 'I':
  162.             Parse_AddIncludeDir(optarg);
  163.             Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
  164.             Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
  165.             break;
  166. #ifdef notdef
  167.         case 'L':
  168.             maxLocal = atoi(optarg);
  169.             Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
  170.             Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
  171.             break;
  172.         case 'P':
  173.             usePipes = FALSE;
  174.             Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
  175.             break;
  176.         case 'S':
  177.             keepgoing = FALSE;
  178.             Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
  179.             break;
  180. #endif
  181.         case 'd': {
  182.             char *modules = optarg;
  183.  
  184.             for (; *modules; ++modules)
  185.                 switch (*modules) {
  186.                 case 'A':
  187.                     debug = ~0;
  188.                     break;
  189.                 case 'a':
  190.                     debug |= DEBUG_ARCH;
  191.                     break;
  192.                 case 'c':
  193.                     debug |= DEBUG_COND;
  194.                     break;
  195.                 case 'd':
  196.                     debug |= DEBUG_DIR;
  197.                     break;
  198.                 case 'g':
  199.                     if (modules[1] == '1') {
  200.                         debug |= DEBUG_GRAPH1;
  201.                         ++modules;
  202.                     }
  203.                     else if (modules[1] == '2') {
  204.                         debug |= DEBUG_GRAPH2;
  205.                         ++modules;
  206.                     }
  207.                     break;
  208.                 case 'j':
  209.                     debug |= DEBUG_JOB;
  210.                     break;
  211.                 case 'm':
  212.                     debug |= DEBUG_MAKE;
  213.                     break;
  214.                 case 's':
  215.                     debug |= DEBUG_SUFF;
  216.                     break;
  217.                 case 't':
  218.                     debug |= DEBUG_TARG;
  219.                     break;
  220.                 case 'v':
  221.                     debug |= DEBUG_VAR;
  222.                     break;
  223.                 default:
  224.                     (void)fprintf(stderr,
  225.                 "make: illegal argument to d option -- %c\n",
  226.                         *modules);
  227.                     usage();
  228.                 }
  229.             Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
  230.             Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
  231.             break;
  232.         }
  233.         case 'e':
  234.             checkEnvFirst = TRUE;
  235.             Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
  236.             break;
  237.         case 'f':
  238.             (void)Lst_AtEnd(makefiles, (ClientData)optarg);
  239.             break;
  240.         case 'i':
  241.             ignoreErrors = TRUE;
  242.             Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
  243.             break;
  244.         case 'j':
  245.             maxJobs = atoi(optarg);
  246.             Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
  247.             Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
  248.             break;
  249.         case 'k':
  250.             keepgoing = TRUE;
  251.             Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
  252.             break;
  253.         case 'n':
  254.             noExecute = TRUE;
  255.             Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
  256.             break;
  257.         case 'q':
  258.             queryFlag = TRUE;
  259.             /* Kind of nonsensical, wot? */
  260.             Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
  261.             break;
  262.         case 'r':
  263.             noBuiltins = TRUE;
  264.             Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
  265.             break;
  266.         case 's':
  267.             beSilent = TRUE;
  268.             Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
  269.             break;
  270.         case 't':
  271.             touchFlag = TRUE;
  272.             Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
  273.             break;
  274.         default:
  275.         case '?':
  276.             usage();
  277.         }
  278.     }
  279.  
  280.     oldVars = TRUE;
  281.  
  282.     /*
  283.      * See if the rest of the arguments are variable assignments and
  284.      * perform them if so. Else take them to be targets and stuff them
  285.      * on the end of the "create" list.
  286.      */
  287.     for (argv += optind, argc -= optind; *argv; ++argv, --argc)
  288.         if (Parse_IsVar(*argv))
  289.             Parse_DoVar(*argv, VAR_CMD);
  290.         else {
  291.             if (!**argv)
  292.                 Punt("illegal (null) argument.");
  293.             if (**argv == '-') {
  294.                 optind = 0;
  295.                 goto rearg;
  296.             }
  297.             (void)Lst_AtEnd(create, (ClientData)*argv);
  298.         }
  299. }
  300.  
  301. /*-
  302.  * Main_ParseArgLine --
  303.  *      Used by the parse module when a .MFLAGS or .MAKEFLAGS target
  304.  *    is encountered and by main() when reading the .MAKEFLAGS envariable.
  305.  *    Takes a line of arguments and breaks it into its
  306.  *     component words and passes those words and the number of them to the
  307.  *    MainParseArgs function.
  308.  *    The line should have all its leading whitespace removed.
  309.  *
  310.  * Results:
  311.  *    None
  312.  *
  313.  * Side Effects:
  314.  *    Only those that come from the various arguments.
  315.  */
  316. void
  317. Main_ParseArgLine(line)
  318.     char *line;            /* Line to fracture */
  319. {
  320.     char **argv;            /* Manufactured argument vector */
  321.     int argc;            /* Number of arguments in argv */
  322.  
  323.     if (line == NULL)
  324.         return;
  325.     for (; *line == ' '; ++line);
  326.     if (!*line)
  327.         return;
  328.  
  329.     argv = brk_string(line, &argc);
  330.     MainParseArgs(argc, argv);
  331. }
  332.  
  333. /*-
  334.  * main --
  335.  *    The main function, for obvious reasons. Initializes variables
  336.  *    and a few modules, then parses the arguments give it in the
  337.  *    environment and on the command line. Reads the system makefile
  338.  *    followed by either Makefile, makefile or the file given by the
  339.  *    -f argument. Sets the .MAKEFLAGS PMake variable based on all the
  340.  *    flags it has received by then uses either the Make or the Compat
  341.  *    module to create the initial list of targets.
  342.  *
  343.  * Results:
  344.  *    If -q was given, exits -1 if anything was out-of-date. Else it exits
  345.  *    0.
  346.  *
  347.  * Side Effects:
  348.  *    The program exits when done. Targets are created. etc. etc. etc.
  349.  */
  350. main(argc, argv)
  351.     int argc;
  352.     char **argv;
  353. {
  354.     Lst targs;    /* target nodes to create -- passed to Make_Init */
  355.     Boolean outOfDate;     /* FALSE if all targets up to date */
  356.     struct stat sb;
  357.     char *p, *path, *getenv();
  358.  
  359.     /*
  360.      * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
  361.      * exists, change into it and build there.  Once things are
  362.      * initted, have to add the original directory to the search path,
  363.      * and modify the paths for the Makefiles apropriately.  The
  364.      * current directory is also placed as a variable for make scripts.
  365.      */
  366.  
  367.     if (!(path = getenv("MAKEOBJDIR")))
  368.         path = _PATH_OBJDIR;
  369.     if (!lstat(path, &sb)) {
  370.         if (S_ISDIR(sb.st_mode))
  371. #ifdef DF_POSIX
  372.                         curdir = ".";
  373. #else
  374.             curdir = "..";
  375. #endif
  376.         else {
  377.             curdir = emalloc((u_int)MAXPATHLEN + 1);
  378.             if (!getwd(curdir)) {
  379.                 (void)fprintf(stderr, "make: %s.\n", curdir);
  380.                 exit(2);
  381.             }
  382.         }
  383.         if (chdir(path)) {
  384.            (void)fprintf(stderr, "make: %s: %s.\n",
  385.                               path, strerror(errno));
  386.            exit(2);
  387.         }
  388.     }
  389.  
  390.     create = Lst_Init(FALSE);
  391.     makefiles = Lst_Init(FALSE);
  392.     beSilent = FALSE;        /* Print commands as executed */
  393.     ignoreErrors = FALSE;        /* Pay attention to non-zero returns */
  394.     noExecute = FALSE;        /* Execute all commands */
  395.     keepgoing = FALSE;        /* Stop on error */
  396.     allPrecious = FALSE;        /* Remove targets when interrupted */
  397.     queryFlag = FALSE;        /* This is not just a check-run */
  398.     noBuiltins = FALSE;        /* Read the built-in rules */
  399.     touchFlag = FALSE;        /* Actually update targets */
  400.     usePipes = TRUE;        /* Catch child output in pipes */
  401.     debug = 0;            /* No debug verbosity, please. */
  402.     jobsRunning = FALSE;
  403.  
  404.     maxJobs = DEFMAXJOBS;        /* Set default max concurrency */
  405.     maxLocal = DEFMAXLOCAL;        /* Set default local max concurrency */
  406.     
  407.     /*
  408.      * Initialize the parsing, directory and variable modules to prepare
  409.      * for the reading of inclusion paths and variable settings on the
  410.      * command line
  411.      */
  412.     Dir_Init();        /* Initialize directory structures so -I flags
  413.                  * can be processed correctly */
  414.     Parse_Init();        /* Need to initialize the paths of #include
  415.                  * directories */
  416.     Var_Init();        /* As well as the lists of variables for
  417.                  * parsing arguments */
  418.  
  419.     if (curdir) {
  420.         Dir_AddDir(dirSearchPath, curdir);
  421.         Var_Set(".CURDIR", curdir, VAR_GLOBAL);
  422.     } else
  423.         Var_Set(".CURDIR", ".", VAR_GLOBAL);
  424.  
  425.     /*
  426.      * Initialize various variables.
  427.      *    MAKE also gets this name, for compatibility
  428.      *    .MAKEFLAGS gets set to the empty string just in case.
  429.      *    MFLAGS also gets initialized empty, for compatibility.
  430.      */
  431.     Var_Set("MAKE", argv[0], VAR_GLOBAL);
  432.     Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
  433.     Var_Set("MFLAGS", "", VAR_GLOBAL);
  434.     Var_Set("MACHINE", MACHINE, VAR_GLOBAL);
  435.  
  436.     /*
  437.      * First snag any flags out of the MAKE environment variable.
  438.      * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
  439.      * in a different format).
  440.      */
  441. #ifdef POSIX
  442.     Main_ParseArgLine(getenv("MAKEFLAGS"));
  443. #else
  444.     Main_ParseArgLine(getenv("MAKE"));
  445. #endif
  446.     
  447.     MainParseArgs(argc, argv);
  448.  
  449.     /*
  450.      * Initialize archive, target and suffix modules in preparation for
  451.      * parsing the makefile(s)
  452.      */
  453.     Arch_Init();
  454.     Targ_Init();
  455.     Suff_Init();
  456.  
  457.     DEFAULT = NILGNODE;
  458.     (void)time(&now);
  459.  
  460.     /*
  461.      * Set up the .TARGETS variable to contain the list of targets to be
  462.      * created. If none specified, make the variable empty -- the parser
  463.      * will fill the thing in with the default or .MAIN target.
  464.      */
  465.     if (!Lst_IsEmpty(create)) {
  466.         LstNode ln;
  467.  
  468.         for (ln = Lst_First(create); ln != NILLNODE;
  469.             ln = Lst_Succ(ln)) {
  470.             char *name = (char *)Lst_Datum(ln);
  471.  
  472.             Var_Append(".TARGETS", name, VAR_GLOBAL);
  473.         }
  474.     } else
  475.         Var_Set(".TARGETS", "", VAR_GLOBAL);
  476.  
  477.     /*
  478.      * Read in the built-in rules first, followed by the specified makefile,
  479.      * if it was (makefile != (char *) NULL), or the default Makefile and
  480.      * makefile, in that order, if it wasn't.
  481.      */
  482. #ifndef _POSIX_SOURCE
  483.      if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
  484.         Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
  485. #else  
  486.          if (( mk_ptr = getenv(MAKEPATH)) == (char *) NULL )
  487.          {
  488.                  fprintf(stderr,"SET: MAKEPATH to run make!\n");
  489.                  exit(0);
  490.          }
  491.             
  492.          if (( fn_ptr = (char *)malloc(strlen(mk_ptr) + 1 ))==(char *)NULL)
  493.          {
  494.              fprintf(stderr,"ERROR : Not enough MEM !\n");
  495.              exit(0);
  496.          }
  497.  
  498.          strcat(strcat(strcpy(fn_ptr,mk_ptr),PATH_SEP),RULE_FILE);
  499.             
  500.             
  501.      if (!noBuiltins && !ReadMakefile(fn_ptr))
  502.         Fatal("make: no system rules (%s).", fn_ptr);
  503. #endif
  504.  
  505.     if (!Lst_IsEmpty(makefiles)) {
  506.         LstNode ln;
  507.  
  508.         ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
  509.         if (ln != NILLNODE)
  510.             Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
  511.     } else if (!ReadMakefile("makefile"))
  512.         (void)ReadMakefile("Makefile");
  513.  
  514.     (void)ReadMakefile(".depend");
  515.  
  516.     Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL), VAR_GLOBAL);
  517.  
  518.     /* Install all the flags into the MAKE envariable. */
  519.     if ((p = Var_Value(MAKEFLAGS, VAR_GLOBAL)) && *p)
  520. /*
  521. #ifdef _POSIX_SOURCE
  522.     {
  523.         char
  524.             _sbuf [80];
  525.  
  526.         sprintf (_sbuf, "%s=%s", "MAKEFLAGS", p);
  527.         putenv (_sbuf);
  528.     }
  529. #else
  530. */
  531. #ifdef POSIX
  532.         setenv("MAKEFLAGS", p, 1);
  533. #else
  534.         setenv("MAKE", p, 1);
  535. #endif
  536. //#endif
  537.  
  538.     /*
  539.      * For compatibility, look at the directories in the VPATH variable
  540.      * and add them to the search path, if the variable is defined. The
  541.      * variable's value is in the same format as the PATH envariable, i.e.
  542.      * <directory>:<directory>:<directory>...
  543.      */
  544.     if (Var_Exists("VPATH", VAR_CMD)) {
  545.         char *vpath, *path, *cp, savec;
  546.         /*
  547.          * GCC stores string constants in read-only memory, but
  548.          * Var_Subst will want to write this thing, so store it
  549.          * in an array
  550.          */
  551.         static char VPATH[] = "${VPATH}";
  552.  
  553.         vpath = Var_Subst(VPATH, VAR_CMD, FALSE);
  554.         path = vpath;
  555.         do {
  556.             /* skip to end of directory */
  557.             for (cp = path; *cp != ':' && *cp != '\0'; cp++);
  558.             /* Save terminator character so know when to stop */
  559.             savec = *cp;
  560.             *cp = '\0';
  561.             /* Add directory to search path */
  562.             Dir_AddDir(dirSearchPath, path);
  563.             *cp = savec;
  564.             path = cp + 1;
  565.         } while (savec == ':');
  566.         (void)free((Address)vpath);
  567.     }
  568.  
  569.     /*
  570.      * Now that all search paths have been read for suffixes et al, it's
  571.      * time to add the default search path to their lists...
  572.      */
  573.     Suff_DoPaths();
  574.  
  575.     /* print the initial graph, if the user requested it */
  576.     if (DEBUG(GRAPH1))
  577.         Targ_PrintGraph(1);
  578.  
  579.     /*
  580.      * Have now read the entire graph and need to make a list of targets
  581.      * to create. If none was given on the command line, we consult the
  582.      * parsing module to find the main target(s) to create.
  583.      */
  584.     if (Lst_IsEmpty(create))
  585.         targs = Parse_MainName();
  586.     else
  587.         targs = Targ_FindList(create, TARG_CREATE);
  588.  
  589. /*
  590.  * this was original amMake -- want to allow parallelism, so put this
  591.  * back in, eventually.
  592.  */
  593.     if (0) {
  594.         /*
  595.          * Initialize job module before traversing the graph, now that
  596.          * any .BEGIN and .END targets have been read.  This is done
  597.          * only if the -q flag wasn't given (to prevent the .BEGIN from
  598.          * being executed should it exist).
  599.          */
  600.         if (!queryFlag) {
  601.             if (maxLocal == -1)
  602.                 maxLocal = maxJobs;
  603.             Job_Init(maxJobs, maxLocal);
  604.             jobsRunning = TRUE;
  605.         }
  606.  
  607.         /* Traverse the graph, checking on all the targets */
  608.         outOfDate = Make_Run(targs);
  609.     } else
  610.         /*
  611.          * Compat_Init will take care of creating all the targets as
  612.          * well as initializing the module.
  613.          */
  614.         Compat_Run(targs);
  615.     
  616.     /* print the graph now it's been processed if the user requested it */
  617.     if (DEBUG(GRAPH2))
  618.         Targ_PrintGraph(2);
  619.  
  620.     if (queryFlag && outOfDate)
  621.         exit(1);
  622.     else
  623.         exit(0);
  624. }
  625.  
  626. /*-
  627.  * ReadMakefile  --
  628.  *    Open and parse the given makefile.
  629.  *
  630.  * Results:
  631.  *    TRUE if ok. FALSE if couldn't open file.
  632.  *
  633.  * Side Effects:
  634.  *    lots
  635.  */
  636. static Boolean
  637. ReadMakefile(fname)
  638.     char *fname;        /* makefile to read */
  639. {
  640.     extern Lst parseIncPath, sysIncPath;
  641.     FILE *stream;
  642.     char *name, path[MAXPATHLEN + 1];
  643.  
  644.     if (!strcmp(fname, "-")) {
  645.         Parse_File("(stdin)", stdin);
  646.         Var_Set("MAKEFILE", "", VAR_GLOBAL);
  647.     } else {
  648.         if (stream = fopen(fname, "r"))
  649.             goto found;
  650.         /* if we've chdir'd, rebuild the path name */
  651.         if (curdir && *fname != '/') {
  652.             (void)sprintf(path, "%s/%s", curdir, fname);
  653.             if (stream = fopen(path, "r")) {
  654.                 fname = path;
  655.                 goto found;
  656.             }
  657.         }
  658.         /* look in -I and system include directories. */
  659.         name = Dir_FindFile(fname, parseIncPath);
  660.         if (!name)
  661.             name = Dir_FindFile(fname, sysIncPath);
  662.         if (!name || !(stream = fopen(name, "r")))
  663.             return(FALSE);
  664.         fname = name;
  665.         /*
  666.          * set the MAKEFILE variable desired by System V fans -- the
  667.          * placement of the setting here means it gets set to the last
  668.          * makefile specified, as it is set by SysV make.
  669.          */
  670. found:        Var_Set("MAKEFILE", fname, VAR_GLOBAL);
  671.         Parse_File(fname, stream);
  672.         (void)fclose(stream);
  673.     }
  674.     return(TRUE);
  675. }
  676.  
  677. /*-
  678.  * Error --
  679.  *    Print an error message given its format.
  680.  *
  681.  * Results:
  682.  *    None.
  683.  *
  684.  * Side Effects:
  685.  *    The message is printed.
  686.  */
  687. /* VARARGS */
  688. void
  689. Error(va_alist)
  690.     va_dcl
  691. {
  692.     va_list ap;
  693.     char *fmt;
  694.  
  695.     va_start(ap);
  696.     fmt = va_arg(ap, char *);
  697.     (void)vfprintf(stderr, fmt, ap);
  698.     va_end(ap);
  699.     (void)fprintf(stderr, "\n");
  700.     (void)fflush(stderr);
  701. }
  702.  
  703. /*-
  704.  * Fatal --
  705.  *    Produce a Fatal error message. If jobs are running, waits for them
  706.  *    to finish.
  707.  *
  708.  * Results:
  709.  *    None
  710.  *
  711.  * Side Effects:
  712.  *    The program exits
  713.  */
  714. /* VARARGS */
  715. void
  716. Fatal(va_alist)
  717.     va_dcl
  718. {
  719.     va_list ap;
  720.     char *fmt;
  721.  
  722.     if (jobsRunning)
  723.         Job_Wait();
  724.  
  725.     va_start(ap);
  726.     fmt = va_arg(ap, char *);
  727.     (void)vfprintf(stderr, fmt, ap);
  728.     va_end(ap);
  729.     (void)fprintf(stderr, "\n");
  730.     (void)fflush(stderr);
  731.  
  732.     if (DEBUG(GRAPH2))
  733.         Targ_PrintGraph(2);
  734.     exit(2);        /* Not 1 so -q can distinguish error */
  735. }
  736.  
  737. /*
  738.  * Punt --
  739.  *    Major exception once jobs are being created. Kills all jobs, prints
  740.  *    a message and exits.
  741.  *
  742.  * Results:
  743.  *    None 
  744.  *
  745.  * Side Effects:
  746.  *    All children are killed indiscriminately and the program Lib_Exits
  747.  */
  748. /* VARARGS */
  749. void
  750. Punt(va_alist)
  751.     va_dcl
  752. {
  753.     va_list ap;
  754.     char *fmt;
  755.  
  756.     (void)fprintf(stderr, "make: ");
  757.     va_start(ap);
  758.     fmt = va_arg(ap, char *);
  759.     (void)vfprintf(stderr, fmt, ap);
  760.     va_end(ap);
  761.     (void)fprintf(stderr, "\n");
  762.     (void)fflush(stderr);
  763.  
  764.     DieHorribly();
  765. }
  766.  
  767. /*-
  768.  * DieHorribly --
  769.  *    Exit without giving a message.
  770.  *
  771.  * Results:
  772.  *    None
  773.  *
  774.  * Side Effects:
  775.  *    A big one...
  776.  */
  777. void
  778. DieHorribly()
  779. {
  780.     if (jobsRunning)
  781.         Job_AbortAll();
  782.     if (DEBUG(GRAPH2))
  783.         Targ_PrintGraph(2);
  784.     exit(2);        /* Not 1, so -q can distinguish error */
  785. }
  786.  
  787. /*
  788.  * Finish --
  789.  *    Called when aborting due to errors in child shell to signal
  790.  *    abnormal exit. 
  791.  *
  792.  * Results:
  793.  *    None 
  794.  *
  795.  * Side Effects:
  796.  *    The program exits
  797.  */
  798. void
  799. Finish(errors)
  800.     int errors;    /* number of errors encountered in Make_Make */
  801. {
  802.     Fatal("%d error%s", errors, errors == 1 ? "" : "s");
  803. }
  804.  
  805. /*
  806.  * emalloc --
  807.  *    malloc, but die on error.
  808.  */
  809. #ifndef DF_POSIX
  810. char *
  811. emalloc(len)
  812.     u_int len;
  813. {
  814.     char *p, *malloc();
  815.  
  816.     if (!(p = malloc(len)))
  817.         enomem();
  818.     return(p);
  819. }
  820. #endif
  821.  
  822. /*
  823.  * enomem --
  824.  *    die when out of memory.
  825.  */
  826. enomem()
  827. {
  828.     (void)fprintf(stderr, "make: %s.\n", strerror(errno));
  829.     exit(2);
  830. }
  831.  
  832. /*
  833.  * usage --
  834.  *    exit with usage message
  835.  */
  836. usage()
  837. {
  838.     (void)fprintf(stderr,
  839. "usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
  840.             [-I directory] [-j max_jobs] [variable=value]\n");
  841.     exit(2);
  842. }
  843.