[BACK]Return to main.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/main.c between version 1.47 and 1.48

version 1.47, 2001/05/07 22:57:19 version 1.48, 2001/05/23 12:34:46
Line 40 
Line 40 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
 /*-  
  * main.c --  
  *      The main file for this entire program. Exit routines etc  
  *      reside here.  
  *  
  * Utility functions defined in this file:  
  *      Main_ParseArgLine       Takes a line of arguments, breaks them and  
  *                              treats them as if they were given when first  
  *                              invoked. Used by the parse module to implement  
  *                              the .MFLAGS target.  
  *  
  *      Error                   Print a tagged error message. The global  
  *                              MAKE variable must have been defined. This  
  *                              takes a format string and two optional  
  *                              arguments for it.  
  *  
  *      Fatal                   Print an error message and exit. Also takes  
  *                              a format string and two arguments.  
  *  
  *      Punt                    Aborts all jobs and exits with a message. Also  
  *                              takes a format string and two arguments.  
  *  
  *      Finish                  Finish things up by printing the number of  
  *                              errors which occured, as passed to it, and  
  *                              exiting.  
  */  
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/time.h>  
 #include <sys/param.h>  
 #include <sys/resource.h>  
 #include <sys/signal.h>  
 #include <sys/stat.h>  #include <sys/stat.h>
 #ifndef MAKE_BOOTSTRAP  #ifndef MAKE_BOOTSTRAP
 #include <sys/utsname.h>  #include <sys/utsname.h>
 #endif  #endif
 #include <sys/wait.h>  
 #include <errno.h>  #include <errno.h>
 #include <fcntl.h>  
 #include <stddef.h>  
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <string.h>
 #include <time.h>  #include <unistd.h>
 #ifdef __STDC__  #include "config.h"
 #include <stdarg.h>  #include "defines.h"
 #else  #include "var.h"
 #include <varargs.h>  #include "parse.h"
 #endif  #include "parsevar.h"
 #include "make.h"  
 #include "ohash.h"  
 #include "dir.h"  #include "dir.h"
 #include "job.h"  #include "error.h"
 #include "pathnames.h"  #include "pathnames.h"
 #include "stats.h"  #include "init.h"
   #include "job.h"
   #include "compat.h"
   #include "targ.h"
   #include "suff.h"
   #include "str.h"
   #include "main.h"
   #include "lst.h"
   #include "memory.h"
   #include "make.h"
   
 #ifndef lint  
 UNUSED  
 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  
 #if 0  
 static char sccsid[] = "@(#)main.c      8.3 (Berkeley) 3/19/94";  
 #else  
 UNUSED  
 static char rcsid[] = "$OpenBSD$";  
 #endif  
 #endif /* not lint */  
   
   
 #ifndef DEFMAXLOCAL  #ifndef DEFMAXLOCAL
 #define DEFMAXLOCAL DEFMAXJOBS  #define DEFMAXLOCAL DEFMAXJOBS
 #endif  /* DEFMAXLOCAL */  #endif  /* DEFMAXLOCAL */
   
 #define MAKEFLAGS       ".MAKEFLAGS"  #define MAKEFLAGS       ".MAKEFLAGS"
   
 LIST                    create;         /* Targets to be made */  static LIST             to_create;      /* Targets to be made */
 TIMESTAMP               now;            /* Time at start of make */  Lst create = &to_create;
 GNode                   *DEFAULT;       /* .DEFAULT node */  GNode                   *DEFAULT;       /* .DEFAULT node */
 Boolean                 allPrecious;    /* .PRECIOUS given on line by itself */  bool            allPrecious;    /* .PRECIOUS given on line by itself */
   
 static Boolean          noBuiltins;     /* -r flag */  static bool             noBuiltins;     /* -r flag */
 static LIST             makefiles;      /* ordered list of makefiles to read */  static LIST             makefiles;      /* ordered list of makefiles to read */
 static Boolean          printVars;      /* print value of one or more vars */  static LIST             varstoprint;    /* list of variables to print */
 static LIST             variables;      /* list of variables to print */  
 int                     maxJobs;        /* -j argument */  int                     maxJobs;        /* -j argument */
 static int              maxLocal;       /* -L argument */  static int              maxLocal;       /* -L argument */
 Boolean                 compatMake;     /* -B argument */  bool            compatMake;     /* -B argument */
 Boolean                 debug;          /* -d flag */  bool            debug;          /* -d flag */
 Boolean                 noExecute;      /* -n flag */  bool            noExecute;      /* -n flag */
 Boolean                 keepgoing;      /* -k flag */  bool            keepgoing;      /* -k flag */
 Boolean                 queryFlag;      /* -q flag */  bool            queryFlag;      /* -q flag */
 Boolean                 touchFlag;      /* -t flag */  bool            touchFlag;      /* -t flag */
 Boolean                 usePipes;       /* !-P flag */  bool            usePipes;       /* !-P flag */
 Boolean                 ignoreErrors;   /* -i flag */  bool            ignoreErrors;   /* -i flag */
 Boolean                 beSilent;       /* -s flag */  bool            beSilent;       /* -s flag */
 Boolean                 oldVars;        /* variable substitution style */  bool            oldVars;        /* variable substitution style */
 Boolean                 checkEnvFirst;  /* -e flag */  bool            checkEnvFirst;  /* -e flag */
 static Boolean          jobsRunning;    /* TRUE if the jobs might be running */  
   
 static void             MainParseArgs(int, char **);  static void             MainParseArgs(int, char **);
 static char *           chdir_verify_path(char *, char *);  static char *           chdir_verify_path(char *, char *);
Line 148 
Line 102 
 static void             add_dirpath(Lst, const char *);  static void             add_dirpath(Lst, const char *);
 static void             usage(void);  static void             usage(void);
 static void             posixParseOptLetter(int);  static void             posixParseOptLetter(int);
   static void             record_option(int, const char *);
   
 static char *curdir;                    /* startup directory */  static char *curdir;                    /* startup directory */
 static char *objdir;                    /* where we chdir'ed to */  static char *objdir;                    /* where we chdir'ed to */
   
   
   static void record_option(c, arg)
       int         c;
       const char  *arg;
   {
       char opt[3];
   
       opt[0] = '-';
       opt[1] = c;
       opt[2] = '\0';
       Var_Append(MAKEFLAGS, opt, VAR_GLOBAL);
       if (arg != NULL)
           Var_Append(MAKEFLAGS, arg, VAR_GLOBAL);
   }
   
 static void  static void
 posixParseOptLetter(c)  posixParseOptLetter(c)
     int c;      int c;
 {  {
         switch(c) {          switch(c) {
         case 'B':          case 'B':
                 compatMake = TRUE;                  compatMake = true;
                 break;                  return; /* XXX don't pass to submakes. */
         case 'P':          case 'P':
                 usePipes = FALSE;                  usePipes = false;
                 Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);  
                 break;                  break;
         case 'S':          case 'S':
                 keepgoing = FALSE;                  keepgoing = false;
                 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);  
                 break;                  break;
         case 'e':          case 'e':
                 checkEnvFirst = TRUE;                  checkEnvFirst = true;
                 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);  
                 break;                  break;
         case 'i':          case 'i':
                 ignoreErrors = TRUE;                  ignoreErrors = true;
                 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);  
                 break;                  break;
         case 'k':          case 'k':
                 keepgoing = TRUE;                  keepgoing = true;
                 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);  
                 break;                  break;
         case 'n':          case 'n':
                 noExecute = TRUE;                  noExecute = true;
                 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);  
                 break;                  break;
         case 'q':          case 'q':
                 queryFlag = TRUE;                  queryFlag = true;
                 /* Kind of nonsensical, wot? */                  /* Kind of nonsensical, wot? */
                 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);  
                 break;                  break;
         case 'r':          case 'r':
                 noBuiltins = TRUE;                  noBuiltins = true;
                 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);  
                 break;                  break;
         case 's':          case 's':
                 beSilent = TRUE;                  beSilent = true;
                 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);  
                 break;                  break;
         case 't':          case 't':
                 touchFlag = TRUE;                  touchFlag = true;
                 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);  
                 break;                  break;
         default:          default:
         case '?':          case '?':
                 usage();                  usage();
         }          }
           record_option(c, NULL);
 }  }
   
 /*-  /*-
Line 240 
Line 200 
                 switch (c) {                  switch (c) {
                 case 'D':                  case 'D':
                         Var_Set(optarg, "1", VAR_GLOBAL);                          Var_Set(optarg, "1", VAR_GLOBAL);
                         Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);                          record_option(c, optarg);
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
                 case 'I':                  case 'I':
                         Parse_AddIncludeDir(optarg);                          Parse_AddIncludeDir(optarg);
                         Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);                          record_option(c, optarg);
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
                 case 'V':                  case 'V':
                         printVars = TRUE;                          Lst_AtEnd(&varstoprint, optarg);
                         Lst_AtEnd(&variables, optarg);                          record_option(c, optarg);
                         Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);  
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
 #ifdef REMOTE  #ifdef REMOTE
                 case 'L': {                  case 'L': {
Line 265 
Line 221 
                                         optarg);                                          optarg);
                                 usage();                                  usage();
                         }                          }
                         Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);                          record_option(c, optend);
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
                 }                  }
 #endif  #endif
Line 324 
Line 279 
                                             *modules);                                              *modules);
                                         usage();                                          usage();
                                 }                                  }
                         Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);                          record_option(c, optarg);
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
                 }                  }
                 case 'f':                  case 'f':
Line 334 
Line 288 
                 case 'j': {                  case 'j': {
                    char *endptr;                     char *endptr;
   
                         forceJobs = TRUE;                          forceJobs = true;
                         maxJobs = strtol(optarg, &endptr, 0);                          maxJobs = strtol(optarg, &endptr, 0);
                         if (endptr == optarg) {                          if (endptr == optarg) {
                                 fprintf(stderr,                                  fprintf(stderr,
Line 346 
Line 300 
 #ifndef REMOTE  #ifndef REMOTE
                         maxLocal = maxJobs;                          maxLocal = maxJobs;
 #endif  #endif
                         Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);                          record_option(c, optarg);
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
                 }                  }
                 case 'm':                  case 'm':
                         Dir_AddDir(&sysIncPath, optarg, NULL);                          Dir_AddDir(sysIncPath, optarg);
                         Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);                          record_option(c, optarg);
                         Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);  
                         break;                          break;
                 default:                  default:
                         posixParseOptLetter(c);                          posixParseOptLetter(c);
Line 362 
Line 314 
   
         /*          /*
          * Be compatible if user did not specify -j and did not explicitly           * Be compatible if user did not specify -j and did not explicitly
          * turned compatibility on           * turn compatibility on
          */           */
         if (!compatMake && !forceJobs)          if (!compatMake && !forceJobs)
                 compatMake = TRUE;                  compatMake = true;
   
         oldVars = TRUE;          oldVars = true;
   
         /*          /*
          * See if the rest of the arguments are variable assignments and           * See if the rest of the arguments are variable assignments and
Line 375 
Line 327 
          * on the end of the "create" list.           * on the end of the "create" list.
          */           */
         for (argv += optind, argc -= optind; *argv; ++argv, --argc)          for (argv += optind, argc -= optind; *argv; ++argv, --argc)
                 if (Parse_IsVar(*argv)) {                  if (!Parse_DoVar(*argv, VAR_CMD)) {
                         char *var = estrdup(*argv);  
   
                         Parse_DoVar(var, VAR_CMD);  
                         free(var);  
                 } else {  
                         if (!**argv)                          if (!**argv)
                                 Punt("illegal (null) argument.");                                  Punt("illegal (null) argument.");
                         if (**argv == '-') {                          if (**argv == '-') {
Line 390 
Line 337 
                                         optind = 1;     /* - */                                          optind = 1;     /* - */
                                 goto rearg;                                  goto rearg;
                         }                          }
                         Lst_AtEnd(&create, estrdup(*argv));                          Lst_AtEnd(create, estrdup(*argv));
                 }                  }
 }  }
   
Line 408 
Line 355 
  */   */
 void  void
 Main_ParseArgLine(line)  Main_ParseArgLine(line)
         char *line;                     /* Line to fracture */          const char *line;                       /* Line to fracture */
 {  {
         char **argv;                    /* Manufactured argument vector */          char **argv;                    /* Manufactured argument vector */
         int argc;                       /* Number of arguments in argv */          int argc;                       /* Number of arguments in argv */
         char *args;                     /* Space used by the args */          char *args;                     /* Space used by the args */
         char *buf;          char *buf;
         char *argv0;          char *argv0;
         char *s;          const char *s;
   
   
         if (line == NULL)          if (line == NULL)
Line 486 
Line 433 
     for (start = n;;) {      for (start = n;;) {
         for (cp = start; *cp != '\0' && *cp != ':';)          for (cp = start; *cp != '\0' && *cp != ':';)
             cp++;              cp++;
         Dir_AddDir(l, start, cp);          Dir_AddDiri(l, start, cp);
         if (*cp == '\0')          if (*cp == '\0')
             break;              break;
         else          else
Line 518 
Line 465 
         char **argv;          char **argv;
 {  {
         LIST targs;                     /* target nodes to create */          LIST targs;                     /* target nodes to create */
         Boolean outOfDate = TRUE;       /* FALSE if all targets up to date */          bool outOfDate = true;  /* false if all targets up to date */
         struct stat sb, sa;          struct stat sb, sa;
         char *p, *path, *pathp, *pwd;          char *p, *path, *pathp, *pwd;
         char mdpath[MAXPATHLEN + 1];          char mdpath[MAXPATHLEN + 1];
Line 526 
Line 473 
         char cdpath[MAXPATHLEN + 1];          char cdpath[MAXPATHLEN + 1];
         char *machine = getenv("MACHINE");          char *machine = getenv("MACHINE");
         char *machine_arch = getenv("MACHINE_ARCH");          char *machine_arch = getenv("MACHINE_ARCH");
                                         /* avoid faults on read-only strings */          const char *syspath = _PATH_DEFSYSPATH;
         static char syspath[] = _PATH_DEFSYSPATH;  
   
         set_out_of_date(now);  
 #ifdef HAS_STATS  
         Init_Stats();  
 #endif  
   
 #ifdef RLIMIT_NOFILE  #ifdef RLIMIT_NOFILE
         /*          /*
          * get rid of resource limit on file descriptors           * get rid of resource limit on file descriptors
Line 640 
Line 581 
         esetenv("PWD", objdir);          esetenv("PWD", objdir);
         unsetenv("CDPATH");          unsetenv("CDPATH");
   
         Lst_Init(&create);          Lst_Init(create);
         Lst_Init(&makefiles);          Lst_Init(&makefiles);
         printVars = FALSE;          Lst_Init(&varstoprint);
         Lst_Init(&variables);          beSilent = false;               /* Print commands as executed */
         beSilent = FALSE;               /* Print commands as executed */          ignoreErrors = false;           /* Pay attention to non-zero returns */
         ignoreErrors = FALSE;           /* Pay attention to non-zero returns */          noExecute = false;              /* Execute all commands */
         noExecute = FALSE;              /* Execute all commands */          keepgoing = false;              /* Stop on error */
         keepgoing = FALSE;              /* Stop on error */          allPrecious = false;            /* Remove targets when interrupted */
         allPrecious = FALSE;            /* Remove targets when interrupted */          queryFlag = false;              /* This is not just a check-run */
         queryFlag = FALSE;              /* This is not just a check-run */          noBuiltins = false;             /* Read the built-in rules */
         noBuiltins = FALSE;             /* Read the built-in rules */          touchFlag = false;              /* Actually update targets */
         touchFlag = FALSE;              /* Actually update targets */          usePipes = true;                /* Catch child output in pipes */
         usePipes = TRUE;                /* Catch child output in pipes */  
         debug = 0;                      /* No debug verbosity, please. */          debug = 0;                      /* No debug verbosity, please. */
         jobsRunning = FALSE;  
   
         maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */          maxLocal = DEFMAXLOCAL;         /* Set default local max concurrency */
 #ifdef REMOTE  #ifdef REMOTE
Line 662 
Line 601 
 #else  #else
         maxJobs = maxLocal;          maxJobs = maxLocal;
 #endif  #endif
         compatMake = FALSE;             /* No compat mode */          compatMake = false;             /* No compat mode */
   
   
         /*          /*
          * Initialize the parsing, directory and variable modules to prepare           * Initialize all external modules.
          * for the reading of inclusion paths and variable settings on the  
          * command line  
          */           */
         Dir_Init();             /* Initialize directory structures so -I flags          Init();
                                  * can be processed correctly */  
         Parse_Init();           /* Need to initialize the paths of #include  
                                  * directories */  
         Var_Init();             /* As well as the lists of variables for  
                                  * parsing arguments */  
         if (objdir != curdir)          if (objdir != curdir)
                 Dir_AddDir(&dirSearchPath, curdir, NULL);                  Dir_AddDir(dirSearchPath, curdir);
         Var_Set(".CURDIR", curdir, VAR_GLOBAL);          Var_Set(".CURDIR", curdir, VAR_GLOBAL);
         Var_Set(".OBJDIR", objdir, VAR_GLOBAL);          Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
   
Line 705 
Line 638 
         Var_AddCmdline(MAKEFLAGS);          Var_AddCmdline(MAKEFLAGS);
   
   
         /*  
          * Initialize archive, target and suffix modules in preparation for  
          * parsing the makefile(s)  
          */  
         Arch_Init();  
         Targ_Init();  
         Suff_Init();  
   
         DEFAULT = NULL;          DEFAULT = NULL;
         grab(now);  
   
         /*          /*
          * Set up the .TARGETS variable to contain the list of targets to be           * Set up the .TARGETS variable to contain the list of targets to be
          * created. If none specified, make the variable empty -- the parser           * created. If none specified, make the variable empty -- the parser
          * will fill the thing in with the default or .MAIN target.           * will fill the thing in with the default or .MAIN target.
          */           */
         if (!Lst_IsEmpty(&create)) {          if (!Lst_IsEmpty(create)) {
                 LstNode ln;                  LstNode ln;
   
                 for (ln = Lst_First(&create); ln != NULL; ln = Lst_Adv(ln)) {                  for (ln = Lst_First(create); ln != NULL; ln = Lst_Adv(ln)) {
                         char *name = (char *)Lst_Datum(ln);                          char *name = (char *)Lst_Datum(ln);
   
                         Var_Append(".TARGETS", name, VAR_GLOBAL);                          Var_Append(".TARGETS", name, VAR_GLOBAL);
Line 738 
Line 662 
          * add the directories from the DEFSYSPATH (more than one may be given           * add the directories from the DEFSYSPATH (more than one may be given
          * as dir1:...:dirn) to the system include path.           * as dir1:...:dirn) to the system include path.
          */           */
         if (Lst_IsEmpty(&sysIncPath))          if (Lst_IsEmpty(sysIncPath))
             add_dirpath(&sysIncPath, syspath);              add_dirpath(sysIncPath, syspath);
   
         /*          /*
          * Read in the built-in rules first, followed by the specified           * Read in the built-in rules first, followed by the specified
          * makefile, if it was (makefile != (char *)NULL), or the default           * makefile(s), or the default BSDmakefile, Makefile or
          * Makefile and makefile, in that order, if it wasn't.           * makefile, in that order.
          */           */
         if (!noBuiltins) {          if (!noBuiltins) {
                 LstNode ln;                  LstNode ln;
                 LIST sysMkPath;                 /* Path of sys.mk */                  LIST sysMkPath;                 /* Path of sys.mk */
   
                 Lst_Init(&sysMkPath);                  Lst_Init(&sysMkPath);
                 Dir_Expand(_PATH_DEFSYSMK, &sysIncPath, &sysMkPath);                  Dir_Expand(_PATH_DEFSYSMK, sysIncPath, &sysMkPath);
                 if (Lst_IsEmpty(&sysMkPath))                  if (Lst_IsEmpty(&sysMkPath))
                         Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);                          Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
                 ln = Lst_Find(&sysMkPath, ReadMakefile, NULL);                  ln = Lst_Find(&sysMkPath, ReadMakefile, NULL);
Line 772 
Line 696 
                 if (!ReadMakefile("makefile", NULL))                  if (!ReadMakefile("makefile", NULL))
                         (void)ReadMakefile("Makefile", NULL);                          (void)ReadMakefile("Makefile", NULL);
   
           /* Always read a .depend file, if it exists. */
         (void)ReadMakefile(".depend", NULL);          (void)ReadMakefile(".depend", NULL);
   
         Var_Append("MFLAGS", Var_Value(MAKEFLAGS),          Var_Append("MFLAGS", Var_Value(MAKEFLAGS),
Line 790 
Line 715 
         if (Var_Value("VPATH") != NULL) {          if (Var_Value("VPATH") != NULL) {
             char *vpath;              char *vpath;
   
             vpath = Var_Subst("${VPATH}", NULL, FALSE);              vpath = Var_Subst("${VPATH}", NULL, false);
             add_dirpath(&dirSearchPath, vpath);              add_dirpath(dirSearchPath, vpath);
             (void)free(vpath);              (void)free(vpath);
         }          }
   
Line 804 
Line 729 
                 Targ_PrintGraph(1);                  Targ_PrintGraph(1);
   
         /* Print the values of any variables requested by the user.  */          /* Print the values of any variables requested by the user.  */
         if (printVars) {          if (!Lst_IsEmpty(&varstoprint)) {
                 LstNode ln;              LstNode ln;
   
                 for (ln = Lst_First(&variables); ln != NULL; ln = Lst_Adv(ln)) {              for (ln = Lst_First(&varstoprint); ln != NULL; ln = Lst_Adv(ln)) {
                         char *value = Var_Value((char *)Lst_Datum(ln));                      char *value = Var_Value((char *)Lst_Datum(ln));
   
                         printf("%s\n", value ? value : "");                      printf("%s\n", value ? value : "");
                 }              }
         }          } else {
               /* Have now read the entire graph and need to make a list of targets
         /* Have now read the entire graph and need to make a list of targets               * to create. If none was given on the command line, we consult the
          * to create. If none was given on the command line, we consult the               * parsing module to find the main target(s) to create.  */
          * parsing module to find the main target(s) to create.  */              Lst_Init(&targs);
         Lst_Init(&targs);              if (Lst_IsEmpty(create))
         if (!Lst_IsEmpty(&create))  
                 Targ_FindList(&targs, &create);  
         else  
                 Parse_MainName(&targs);                  Parse_MainName(&targs);
               else
                   Targ_FindList(&targs, create);
   
         if (!compatMake && !printVars) {              if (compatMake)
                   /* Compat_Init will take care of creating all the targets as
                    * well as initializing the module.  */
                   Compat_Run(&targs);
               else {
                 /* Initialize job module before traversing the graph, now that                  /* Initialize job module before traversing the graph, now that
                  * any .BEGIN and .END targets have been read.  This is done                   * any .BEGIN and .END targets have been read.  This is done
                  * only if the -q flag wasn't given (to prevent the .BEGIN from                   * only if the -q flag wasn't given (to prevent the .BEGIN from
Line 832 
Line 760 
                         if (maxLocal == -1)                          if (maxLocal == -1)
                                 maxLocal = maxJobs;                                  maxLocal = maxJobs;
                         Job_Init(maxJobs, maxLocal);                          Job_Init(maxJobs, maxLocal);
                         jobsRunning = TRUE;  
                 }                  }
   
                 /* Traverse the graph, checking on all the targets.  */                  /* Traverse the graph, checking on all the targets.  */
                 outOfDate = Make_Run(&targs);                  outOfDate = Make_Run(&targs);
         } else if (!printVars) {              }
                 /* Compat_Init will take care of creating all the targets as  
                  * well as initializing the module.  */  
                 Compat_Run(&targs);  
         }          }
   
         Lst_Destroy(&targs, NOFREE);          Lst_Destroy(&targs, NOFREE);
         Lst_Destroy(&variables, NOFREE);          Lst_Destroy(&varstoprint, NOFREE);
         Lst_Destroy(&makefiles, NOFREE);          Lst_Destroy(&makefiles, NOFREE);
         Lst_Destroy(&create, (SimpleProc)free);          Lst_Destroy(create, (SimpleProc)free);
   
         /* print the graph now it's been processed if the user requested it */          /* print the graph now it's been processed if the user requested it */
         if (DEBUG(GRAPH2))          if (DEBUG(GRAPH2))
                 Targ_PrintGraph(2);                  Targ_PrintGraph(2);
   
         Suff_End();  
         Targ_End();  
         Arch_End();  
         Var_End();  
         Parse_End();  
         Dir_End();  
         Job_End();  
   
         if (queryFlag && outOfDate)          if (queryFlag && outOfDate)
                 return 1;                  return 1;
         else          else
Line 871 
Line 787 
  *      Open and parse the given makefile.   *      Open and parse the given makefile.
  *   *
  * Results:   * Results:
  *      TRUE if ok. FALSE if couldn't open file.   *      true if ok. false if couldn't open file.
  *   *
  * Side Effects:   * Side Effects:
  *      lots   *      lots
  */   */
 static Boolean  static bool
 ReadMakefile(p, q)  ReadMakefile(p, q)
         void * p;          void * p;
         void * q                UNUSED;          void * q                UNUSED;
 {  {
         char *fname = p;                /* makefile to read */          char *fname = p;                /* makefile to read */
         extern LIST parseIncPath;  
         FILE *stream;          FILE *stream;
         char *name, path[MAXPATHLEN + 1];          char *name, path[MAXPATHLEN + 1];
   
Line 901 
Line 816 
                         }                          }
                 }                  }
                 /* look in -I and system include directories. */                  /* look in -I and system include directories. */
                 name = Dir_FindFile(fname, &parseIncPath);                  name = Dir_FindFile(fname, parseIncPath);
                 if (!name)                  if (!name)
                         name = Dir_FindFile(fname, &sysIncPath);                          name = Dir_FindFile(fname, sysIncPath);
                 if (!name || !(stream = fopen(name, "r")))                  if (!name || !(stream = fopen(name, "r")))
                         return FALSE;                          return false;
                 fname = name;                  fname = name;
                 /*                  /*
                  * set the MAKEFILE variable desired by System V fans -- the                   * set the MAKEFILE variable desired by System V fans -- the
Line 915 
Line 830 
 found:          Var_Set("MAKEFILE", fname, VAR_GLOBAL);  found:          Var_Set("MAKEFILE", fname, VAR_GLOBAL);
                 Parse_File(fname, stream);                  Parse_File(fname, stream);
         }          }
         return TRUE;          return true;
 }  }
   
 /*-  
  * Cmd_Exec --  
  *      Execute the command in cmd, and return the output of that command  
  *      in a string.  
  *  
  * Results:  
  *      A string containing the output of the command, or the empty string  
  *      If err is not NULL, it contains the reason for the command failure  
  *  
  * Side Effects:  
  *      The string must be freed by the caller.  
  */  
 char *  
 Cmd_Exec(cmd, err)  
     const char *cmd;  
     char **err;  
 {  
     char        *args[4];       /* Args for invoking the shell */  
     int         fds[2];         /* Pipe streams */  
     int         cpid;           /* Child PID */  
     int         pid;            /* PID from wait() */  
     char        *res;           /* result */  
     int         status;         /* command exit status */  
     BUFFER      buf;            /* buffer to store the result */  
     char        *cp;  
     ssize_t     cc;  
     size_t      length;  
   
   
     *err = NULL;  
   
     /*  
      * Set up arguments for shell  
      */  
     args[0] = "sh";  
     args[1] = "-c";  
     args[2] = (char *)cmd;  
     args[3] = NULL;  
   
     /*  
      * Open a pipe for fetching its output  
      */  
     if (pipe(fds) == -1) {  
         *err = "Couldn't create pipe for \"%s\"";  
         goto bad;  
     }  
   
     /*  
      * Fork  
      */  
     switch (cpid = vfork()) {  
     case 0:  
         /*  
          * Close input side of pipe  
          */  
         (void)close(fds[0]);  
   
         /*  
          * Duplicate the output stream to the shell's output, then  
          * shut the extra thing down. Note we don't fetch the error  
          * stream...why not? Why?  
          */  
         (void)dup2(fds[1], 1);  
         if (fds[1] != 1)  
             (void)close(fds[1]);  
   
         (void)execv("/bin/sh", args);  
         _exit(1);  
         /*NOTREACHED*/  
   
     case -1:  
         *err = "Couldn't exec \"%s\"";  
         goto bad;  
   
     default:  
         /*  
          * No need for the writing half  
          */  
         (void)close(fds[1]);  
   
         Buf_Init(&buf, MAKE_BSIZE);  
   
         do {  
             char   result[BUFSIZ];  
             cc = read(fds[0], result, sizeof(result));  
             if (cc > 0)  
                 Buf_AddChars(&buf, cc, result);  
         }  
         while (cc > 0 || (cc == -1 && errno == EINTR));  
   
         /*  
          * Close the input side of the pipe.  
          */  
         (void)close(fds[0]);  
   
         /*  
          * Wait for the process to exit.  
          */  
         while ((pid = wait(&status)) != cpid && pid >= 0)  
             continue;  
   
         if (cc == -1)  
             *err = "Couldn't read shell's output for \"%s\"";  
   
         if (status)  
             *err = "\"%s\" returned non-zero status";  
   
         length = Buf_Size(&buf);  
         res = Buf_Retrieve(&buf);  
   
         /* The result is null terminated, Convert newlines to spaces and  
          * install in the variable.  */  
         cp = res + length - 1;  
   
         if (*cp == '\n')  
             /* A final newline is just stripped.  */  
             *cp-- = '\0';  
   
         while (cp >= res) {  
             if (*cp == '\n')  
                 *cp = ' ';  
             cp--;  
         }  
         break;  
     }  
     return res;  
 bad:  
     return estrdup("");  
 }  
   
 /*-  
  * Error --  
  *      Print an error message given its format.  
  */  
 /* VARARGS */  
 void  
 #ifdef __STDC__  
 Error(char *fmt, ...)  
 #else  
 Error(va_alist)  
         va_dcl  
 #endif  
 {  
         va_list ap;  
 #ifdef __STDC__  
         va_start(ap, fmt);  
 #else  
         char *fmt;  
   
         va_start(ap);  
         fmt = va_arg(ap, char *);  
 #endif  
         (void)vfprintf(stderr, fmt, ap);  
         va_end(ap);  
         (void)fprintf(stderr, "\n");  
 }  
   
 /*-  
  * Fatal --  
  *      Produce a Fatal error message. If jobs are running, waits for them  
  *      to finish.  
  *  
  * Side Effects:  
  *      The program exits  
  */  
 /* VARARGS */  
 void  
 #ifdef __STDC__  
 Fatal(char *fmt, ...)  
 #else  
 Fatal(va_alist)  
         va_dcl  
 #endif  
 {  
         va_list ap;  
 #ifdef __STDC__  
         va_start(ap, fmt);  
 #else  
         char *fmt;  
   
         va_start(ap);  
         fmt = va_arg(ap, char *);  
 #endif  
         if (jobsRunning)  
                 Job_Wait();  
   
         (void)vfprintf(stderr, fmt, ap);  
         va_end(ap);  
         (void)fprintf(stderr, "\n");  
   
         if (DEBUG(GRAPH2))  
                 Targ_PrintGraph(2);  
         exit(2);                /* Not 1 so -q can distinguish error */  
 }  
   
 /*  /*
  * Punt --  
  *      Major exception once jobs are being created. Kills all jobs, prints  
  *      a message and exits.  
  *  
  * Side Effects:  
  *      All children are killed indiscriminately and the program Lib_Exits  
  */  
 /* VARARGS */  
 void  
 #ifdef __STDC__  
 Punt(char *fmt, ...)  
 #else  
 Punt(va_alist)  
         va_dcl  
 #endif  
 {  
         va_list ap;  
 #ifdef __STDC__  
         va_start(ap, fmt);  
 #else  
         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");  
   
         DieHorribly();  
 }  
   
 /*-  
  * DieHorribly --  
  *      Exit without giving a message.  
  *  
  * Side Effects:  
  *      A big one...  
  */  
 void  
 DieHorribly()  
 {  
         if (jobsRunning)  
                 Job_AbortAll();  
         if (DEBUG(GRAPH2))  
                 Targ_PrintGraph(2);  
         exit(2);                /* Not 1, so -q can distinguish error */  
 }  
   
 /*  
  * Finish --  
  *      Called when aborting due to errors in child shell to signal  
  *      abnormal exit.  
  *  
  * Side Effects:  
  *      The program exits  
  */  
 void  
 Finish(errors)  
         int errors;     /* number of errors encountered in Make_Make */  
 {  
         Fatal("%d error%s", errors, errors == 1 ? "" : "s");  
 }  
   
   
 /*  
  * usage --   * usage --
  *      exit with usage message   *      exit with usage message
  */   */
Line 1196 
Line 849 
 }  }
   
   
 void  
 PrintAddr(a)  
     void *a;  
 {  
     printf("%lx ", (unsigned long)a);  
 }  

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.48