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

Diff for /src/usr.bin/make/compat.c between version 1.56 and 1.57

version 1.56, 2007/09/16 12:09:36 version 1.57, 2007/09/16 14:18:40
Line 71 
Line 71 
  * contains any of these characters, it is executed by the shell, not   * contains any of these characters, it is executed by the shell, not
  * directly by us.  */   * directly by us.  */
   
 static char         meta[256];  static char meta[256];
   
 static GNode        *ENDNode;  static GNode *ENDNode;
 static void CompatInterrupt(int);  static void CompatInterrupt(int);
 static int CompatRunCommand(LstNode, void *);  static int CompatRunCommand(LstNode, void *);
 static void CompatMake(void *, void *);  static void CompatMake(void *, void *);
Line 84 
Line 84 
 static void  static void
 CompatInterrupt(int signo)  CompatInterrupt(int signo)
 {  {
     if (interrupted != SIGINT)          if (interrupted != SIGINT)
         interrupted = signo;                  interrupted = signo;
 }  }
   
 /*-  /*-
Line 157 
Line 157 
 CompatRunCommand(LstNode cmdNode,/* Command to execute */  CompatRunCommand(LstNode cmdNode,/* Command to execute */
     void *gnp)                  /* Node from which the command came */      void *gnp)                  /* Node from which the command came */
 {  {
     char          *cmdStart;    /* Start of expanded command */          char *cmdStart;         /* Start of expanded command */
     char *cp, *bp = NULL;          char *cp, *bp = NULL;
     bool          silent,       /* Don't print command */          bool silent;            /* Don't print command */
                   doExecute;    /* Execute the command */          bool doExecute;         /* Execute the command */
     volatile bool errCheck;     /* Check errors */          volatile bool errCheck; /* Check errors */
     int           reason;       /* Reason for child's death */          int reason;             /* Reason for child's death */
     int           status;       /* Description of child's death */          int status;             /* Description of child's death */
     pid_t         cpid;         /* Child actually found */          pid_t cpid;             /* Child actually found */
     pid_t         stat;         /* Status of fork */          pid_t stat;             /* Status of fork */
     char          ** volatile av; /* Argument vector for thing to exec */          char **volatile av;     /* Argument vector for thing to exec */
     int           argc;         /* Number of arguments in av or 0 if not          int argc;               /* Number of arguments in av or 0 if not
                                  * dynamically allocated */                                   * dynamically allocated */
     char          *cmd = (char *)Lst_Datum(cmdNode);          char *cmd = (char *)Lst_Datum(cmdNode);
     GNode         *gn = (GNode *)gnp;          GNode *gn = (GNode *)gnp;
     static char *shargv[4] = { _PATH_BSHELL };          static char *shargv[4] = { _PATH_BSHELL };
   
     silent = gn->type & OP_SILENT;          silent = gn->type & OP_SILENT;
     errCheck = !(gn->type & OP_IGNORE);          errCheck = !(gn->type & OP_IGNORE);
     doExecute = !noExecute;          doExecute = !noExecute;
   
     cmdStart = Var_Subst(cmd, &gn->context, false);          cmdStart = Var_Subst(cmd, &gn->context, false);
   
     /* brk_string will return an argv with a NULL in av[0], thus causing          /* brk_string will return an argv with a NULL in av[0], thus causing
      * execvp to choke and die horribly. Besides, how can we execute a null           * execvp to choke and die horribly. Besides, how can we execute a null
      * command? In any case, we warn the user that the command expanded to           * command? In any case, we warn the user that the command expanded to
      * nothing (is this the right thing to do?).  */           * nothing (is this the right thing to do?).  */
   
     if (*cmdStart == '\0') {          if (*cmdStart == '\0') {
         free(cmdStart);                  free(cmdStart);
         Error("%s expands to empty string", cmd);                  Error("%s expands to empty string", cmd);
         return 1;                  return 1;
     } else          } else
         cmd = cmdStart;                  cmd = cmdStart;
     Lst_Replace(cmdNode, cmdStart);          Lst_Replace(cmdNode, cmdStart);
   
     if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {          if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) {
         Lst_AtEnd(&ENDNode->commands, cmdStart);                  Lst_AtEnd(&ENDNode->commands, cmdStart);
         return 1;                  return 1;
     } else if (strcmp(cmdStart, "...") == 0) {          } else if (strcmp(cmdStart, "...") == 0) {
         gn->type |= OP_SAVE_CMDS;                  gn->type |= OP_SAVE_CMDS;
         return 1;                  return 1;
     }          }
   
     for (;; cmd++) {          for (;; cmd++) {
         if (*cmd == '@')                  if (*cmd == '@')
             silent = DEBUG(LOUD) ? false : true;                          silent = DEBUG(LOUD) ? false : true;
         else if (*cmd == '-')                  else if (*cmd == '-')
             errCheck = false;                          errCheck = false;
         else if (*cmd == '+')                  else if (*cmd == '+')
             doExecute = true;                          doExecute = true;
         else                  else
             break;                          break;
     }          }
   
     while (isspace(*cmd))          while (isspace(*cmd))
         cmd++;                  cmd++;
   
     /* Search for meta characters in the command. If there are no meta          /* Search for meta characters in the command. If there are no meta
      * characters, there's no need to execute a shell to execute the           * characters, there's no need to execute a shell to execute the
      * command.  */           * command.  */
     for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {          for (cp = cmd; !meta[(unsigned char)*cp]; cp++) {
         continue;                  continue;
     }          }
   
     /* Print the command before echoing if we're not supposed to be quiet for          /* Print the command before echoing if we're not supposed to be quiet
      * this one. We also print the command if -n given.  */           * for this one. We also print the command if -n given.  */
     if (!silent || noExecute) {          if (!silent || noExecute) {
         printf("%s\n", cmd);                  printf("%s\n", cmd);
         fflush(stdout);                  fflush(stdout);
     }          }
   
     /* If we're not supposed to execute any commands, this is as far as          /* If we're not supposed to execute any commands, this is as far as
      * we go...  */           * we go...  */
     if (!doExecute)          if (!doExecute)
         return 1;                  return 1;
   
     if (*cp != '\0') {          if (*cp != '\0') {
         /* If *cp isn't the null character, we hit a "meta" character and                  /* If *cp isn't the null character, we hit a "meta" character
          * need to pass the command off to the shell. We give the shell the                   * and need to pass the command off to the shell. We give the
          * -e flag as well as -c if it's supposed to exit when it hits an                   * shell the -e flag as well as -c if it's supposed to exit
          * error.  */                   * when it hits an error.  */
   
         shargv[1] = errCheck ? "-ec" : "-c";  
         shargv[2] = cmd;  
         shargv[3] = NULL;  
         av = shargv;  
         argc = 0;  
     } else {  
         /* No meta-characters, so probably no need to exec a shell.  
          * Break the command into words to form an argument vector  
          * we can execute.  */  
         av = brk_string(cmd, &argc, &bp);  
         switch (shellneed(av)) {  
         case -1: /* handled internally */  
                 free(bp);  
                 free(av);  
                 return 1;  
         case 1:  
                 shargv[1] = errCheck ? "-ec" : "-c";                  shargv[1] = errCheck ? "-ec" : "-c";
                 shargv[2] = cmd;                  shargv[2] = cmd;
                 shargv[3] = NULL;                  shargv[3] = NULL;
                 free(av);  
                 free(bp);  
                 bp = NULL;  
                 av = shargv;                  av = shargv;
                 argc = 0;                  argc = 0;
                 break;          } else {
         default: /* nothing needed */                  /* No meta-characters, so probably no need to exec a shell.
                 break;                   * Break the command into words to form an argument vector
                    * we can execute.  */
                   av = brk_string(cmd, &argc, &bp);
                   switch (shellneed(av)) {
                   case -1: /* handled internally */
                           free(bp);
                           free(av);
                           return 1;
                   case 1:
                           shargv[1] = errCheck ? "-ec" : "-c";
                           shargv[2] = cmd;
                           shargv[3] = NULL;
                           free(av);
                           free(bp);
                           bp = NULL;
                           av = shargv;
                           argc = 0;
                           break;
                   default: /* nothing needed */
                           break;
                   }
         }          }
     }  
   
     /* Fork and execute the single command. If the fork fails, we abort.  */          /* Fork and execute the single command. If the fork fails, we abort.  */
     cpid = fork();          cpid = fork();
     if (cpid == -1)          if (cpid == -1)
         Fatal("Could not fork");                  Fatal("Could not fork");
     if (cpid == 0) {          if (cpid == 0) {
             execvp(av[0], av);                  execvp(av[0], av);
             if (errno == ENOENT)                  if (errno == ENOENT)
                 fprintf(stderr, "%s: not found\n", av[0]);                          fprintf(stderr, "%s: not found\n", av[0]);
             else                  else
                 perror(av[0]);                          perror(av[0]);
             _exit(1);                  _exit(1);
     }          }
     if (bp) {          if (bp) {
         free(av);                  free(av);
         free(bp);                  free(bp);
     }          }
     free(cmdStart);          free(cmdStart);
     Lst_Replace(cmdNode, NULL);          Lst_Replace(cmdNode, NULL);
   
     /* The child is off and running. Now all we can do is wait...  */          /* The child is off and running. Now all we can do is wait...  */
     while (1) {          while (1) {
   
         while ((stat = wait(&reason)) != cpid) {                  while ((stat = wait(&reason)) != cpid) {
             if (stat == -1 && errno != EINTR)                          if (stat == -1 && errno != EINTR)
                 break;                                  break;
         }                  }
   
         if (interrupted)                  if (interrupted)
             break;                          break;
   
         if (stat != -1) {                  if (stat != -1) {
             if (WIFSTOPPED(reason))                          if (WIFSTOPPED(reason))
                 status = WSTOPSIG(reason);              /* stopped */                                  status = WSTOPSIG(reason);      /* stopped */
             else if (WIFEXITED(reason)) {                          else if (WIFEXITED(reason)) {
                 status = WEXITSTATUS(reason);           /* exited */                                  status = WEXITSTATUS(reason);   /* exited */
                 if (status != 0)                                  if (status != 0)
                     printf("*** Error code %d", status);                                          printf("*** Error code %d", status);
             } else {                          } else {
                 status = WTERMSIG(reason);              /* signaled */                                  status = WTERMSIG(reason);      /* signaled */
                 printf("*** Signal %d", status);                                  printf("*** Signal %d", status);
             }                          }
   
   
             if (!WIFEXITED(reason) || status != 0) {                          if (!WIFEXITED(reason) || status != 0) {
                 if (errCheck) {                                  if (errCheck) {
                     gn->made = ERROR;                                          gn->made = ERROR;
                     if (keepgoing)                                          if (keepgoing)
                         /* Abort the current target, but let others                                                  /* Abort the current target,
                          * continue.  */                                                   * but let others continue.  */
                         printf(" (continuing)\n");                                                  printf(" (continuing)\n");
                 } else {                                  } else {
                     /* Continue executing commands for this target.                                          /* Continue executing commands for this
                      * If we return 0, this will happen...  */                                           * target.  If we return 0, this will
                     printf(" (ignored)\n");                                           * happen...  */
                     status = 0;                                          printf(" (ignored)\n");
                 }                                          status = 0;
             }                                  }
             return !status;                          }
         } else                          return !status;
             Fatal("error in wait: %d", stat);                  } else
             /*NOTREACHED*/                          Fatal("error in wait: %d", stat);
     }                          /*NOTREACHED*/
           }
   
     /* This is reached only if interrupted */          /* This is reached only if interrupted */
     if (!Targ_Precious(gn)) {          if (!Targ_Precious(gn)) {
         char      *file = Varq_Value(TARGET_INDEX, gn);                  char *file = Varq_Value(TARGET_INDEX, gn);
   
         if (!noExecute && eunlink(file) != -1)                  if (!noExecute && eunlink(file) != -1)
             Error("*** %s removed\n", file);                          Error("*** %s removed\n", file);
     }          }
     if (interrupted == SIGINT) {          if (interrupted == SIGINT) {
         GNode *i = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);                  GNode *i = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
         signal(SIGINT, SIG_IGN);                  signal(SIGINT, SIG_IGN);
         signal(SIGTERM, SIG_IGN);                  signal(SIGTERM, SIG_IGN);
         signal(SIGHUP, SIG_IGN);                  signal(SIGHUP, SIG_IGN);
         signal(SIGQUIT, SIG_IGN);                  signal(SIGQUIT, SIG_IGN);
         interrupted = 0;                  interrupted = 0;
         if (i != NULL)                  if (i != NULL)
             Lst_ForEachNodeWhile(&i->commands, CompatRunCommand, i);                          Lst_ForEachNodeWhile(&i->commands, CompatRunCommand, i);
         exit(SIGINT);                  exit(SIGINT);
     }          }
     exit(interrupted);          exit(interrupted);
 }  }
   
 /*-  /*-
Line 366 
Line 367 
 CompatMake(void *gnp,   /* The node to make */  CompatMake(void *gnp,   /* The node to make */
     void *pgnp)         /* Parent to abort if necessary */      void *pgnp)         /* Parent to abort if necessary */
 {  {
     GNode *gn = (GNode *)gnp;          GNode *gn = (GNode *)gnp;
     GNode *pgn = (GNode *)pgnp;          GNode *pgn = (GNode *)pgnp;
   
     if (pgn->type & OP_MADE) {          if (pgn->type & OP_MADE) {
         (void)Dir_MTime(gn);                  (void)Dir_MTime(gn);
         gn->made = UPTODATE;                  gn->made = UPTODATE;
     }  
   
     if (gn->type & OP_USE) {  
         Make_HandleUse(gn, pgn);  
     } else if (gn->made == UNMADE) {  
         /* First mark ourselves to be made, then apply whatever transformations  
          * the suffix module thinks are necessary. Once that's done, we can  
          * descend and make all our children. If any of them has an error  
          * but the -k flag was given, our 'make' field will be set false again.  
          * This is our signal to not attempt to do anything but abort our  
          * parent as well.  */  
         gn->make = true;  
         gn->made = BEINGMADE;  
         Suff_FindDeps(gn);  
         Lst_ForEach(&gn->children, CompatMake, gn);  
         if (!gn->make) {  
             gn->made = ABORTED;  
             pgn->make = false;  
             return;  
         }          }
   
         if (Lst_Member(&gn->iParents, pgn) != NULL) {          if (gn->type & OP_USE) {
             Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn);                  Make_HandleUse(gn, pgn);
         }          } else if (gn->made == UNMADE) {
                   /* First mark ourselves to be made, then apply whatever
                    * transformations the suffix module thinks are necessary. Once
                    * that's done, we can descend and make all our children. If
                    * any of them has an error but the -k flag was given, our
                    * 'make' field will be set false again.  This is our signal to
                    * not attempt to do anything but abort our parent as well.  */
                   gn->make = true;
                   gn->made = BEINGMADE;
                   Suff_FindDeps(gn);
                   Lst_ForEach(&gn->children, CompatMake, gn);
                   if (!gn->make) {
                           gn->made = ABORTED;
                           pgn->make = false;
                           return;
                   }
   
         /* All the children were made ok. Now cmtime contains the modification                  if (Lst_Member(&gn->iParents, pgn) != NULL) {
          * time of the newest child, we need to find out if we exist and when                          Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn),
          * we were modified last. The criteria for datedness are defined by the                              pgn);
          * Make_OODate function.  */                  }
         if (DEBUG(MAKE))  
             printf("Examining %s...", gn->name);  
         if (! Make_OODate(gn)) {  
             gn->made = UPTODATE;  
             if (DEBUG(MAKE))  
                 printf("up-to-date.\n");  
             return;  
         } else if (DEBUG(MAKE))  
             printf("out-of-date.\n");  
   
         /* If the user is just seeing if something is out-of-date, exit now                  /* All the children were made ok. Now cmtime contains the
          * to tell him/her "yes".  */                   * modification time of the newest child, we need to find out
         if (queryFlag)                   * if we exist and when we were modified last. The criteria for
             exit(-1);                   * datedness are defined by the Make_OODate function.  */
                   if (DEBUG(MAKE))
                           printf("Examining %s...", gn->name);
                   if (! Make_OODate(gn)) {
                           gn->made = UPTODATE;
                           if (DEBUG(MAKE))
                                   printf("up-to-date.\n");
                           return;
                   } else if (DEBUG(MAKE))
                           printf("out-of-date.\n");
   
         /* We need to be re-made. We also have to make sure we've got a $?                  /* If the user is just seeing if something is out-of-date, exit
          * variable. To be nice, we also define the $> variable using                   * now to tell him/her "yes".  */
          * Make_DoAllVar().  */                  if (queryFlag)
         Make_DoAllVar(gn);                          exit(-1);
   
         /* Alter our type to tell if errors should be ignored or things                  /* We need to be re-made. We also have to make sure we've got a
          * should not be printed so CompatRunCommand knows what to do.  */                   * $?  variable. To be nice, we also define the $> variable
         if (Targ_Ignore(gn))                   * using Make_DoAllVar().  */
             gn->type |= OP_IGNORE;                  Make_DoAllVar(gn);
         if (Targ_Silent(gn))  
             gn->type |= OP_SILENT;  
   
         if (Job_CheckCommands(gn, Fatal)) {                  /* Alter our type to tell if errors should be ignored or things
             /* Our commands are ok, but we still have to worry about the -t                   * should not be printed so CompatRunCommand knows what to do.
              * flag...  */                   * */
             if (!touchFlag)                  if (Targ_Ignore(gn))
                 Lst_ForEachNodeWhile(&gn->commands, CompatRunCommand, gn);                          gn->type |= OP_IGNORE;
             else                  if (Targ_Silent(gn))
                 Job_Touch(gn, gn->type & OP_SILENT);                          gn->type |= OP_SILENT;
         } else  
             gn->made = ERROR;  
   
         if (gn->made != ERROR) {                  if (Job_CheckCommands(gn, Fatal)) {
             /* If the node was made successfully, mark it so, update                          /* Our commands are ok, but we still have to worry
              * its modification time and timestamp all its parents. Note                           * about the -t flag... */
              * that for .ZEROTIME targets, the timestamping isn't done.                          if (!touchFlag)
              * This is to keep its state from affecting that of its parent.  */                                  Lst_ForEachNodeWhile(&gn->commands,
             gn->made = MADE;                                      CompatRunCommand, gn);
             /* This is what Make does and it's actually a good thing, as it                          else
              * allows rules like                                  Job_Touch(gn, gn->type & OP_SILENT);
              *                  } else
              *  cmp -s y.tab.h parse.h || cp y.tab.h parse.h                          gn->made = ERROR;
              *  
              * to function as intended. Unfortunately, thanks to the stateless  
              * nature of NFS (and the speed of this program), there are times  
              * when the modification time of a file created on a remote  
              * machine will not be modified before the stat() implied by  
              * the Dir_MTime occurs, thus leading us to believe that the file  
              * is unchanged, wreaking havoc with files that depend on this one.  
              *  
              * I have decided it is better to make too much than to make too  
              * little, so this stuff is commented out unless you're sure it's  
              * ok.  
              * -- ardeb 1/12/88  
              */  
             if (noExecute || is_out_of_date(Dir_MTime(gn)))  
                 gn->mtime = now;  
             if (is_strictly_before(gn->mtime, gn->cmtime))  
                 gn->mtime = gn->cmtime;  
             if (DEBUG(MAKE))  
                 printf("update time: %s\n", time_to_string(gn->mtime));  
             if (!(gn->type & OP_EXEC)) {  
                 pgn->childMade = true;  
                 Make_TimeStamp(pgn, gn);  
             }  
         } else if (keepgoing)  
             pgn->make = false;  
         else {  
   
             if (gn->lineno)                  if (gn->made != ERROR) {
                 printf("\n\nStop in %s (line %lu of %s).\n",                          /* If the node was made successfully, mark it so,
                         Var_Value(".CURDIR"),                           * update its modification time and timestamp all its
                         (unsigned long)gn->lineno,                           * parents. Note that for .ZEROTIME targets, the
                         gn->fname);                           * timestamping isn't done.  This is to keep its state
             else                           * from affecting that of its parent.  */
                 printf("\n\nStop in %s.\n", Var_Value(".CURDIR"));                          gn->made = MADE;
             exit(1);                          /* This is what Make does and it's actually a good
         }                           * thing, as it allows rules like
     } else if (gn->made == ERROR)                           *
         /* Already had an error when making this beastie. Tell the parent                           *      cmp -s y.tab.h parse.h || cp y.tab.h parse.h
          * to abort.  */                           *
         pgn->make = false;                           * to function as intended. Unfortunately, thanks to
     else {                           * the stateless nature of NFS (and the speed of this
         if (Lst_Member(&gn->iParents, pgn) != NULL) {                           * program), there are times when the modification time
             Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn), pgn);                           * of a file created on a remote machine will not be
         }                           * modified before the stat() implied by the Dir_MTime
         switch (gn->made) {                           * occurs, thus leading us to believe that the file is
             case BEINGMADE:                           * unchanged, wreaking havoc with files that depend on
                 Error("Graph cycles through %s\n", gn->name);                           * this one.
                 gn->made = ERROR;                           *
                            * I have decided it is better to make too much than to
                            * make too little, so this stuff is commented out
                            * unless you're sure it's ok.  -- ardeb 1/12/88
                            */
                           if (noExecute || is_out_of_date(Dir_MTime(gn)))
                                   gn->mtime = now;
                           if (is_strictly_before(gn->mtime, gn->cmtime))
                                   gn->mtime = gn->cmtime;
                           if (DEBUG(MAKE))
                                   printf("update time: %s\n",
                                       time_to_string(gn->mtime));
                           if (!(gn->type & OP_EXEC)) {
                                   pgn->childMade = true;
                                   Make_TimeStamp(pgn, gn);
                           }
                   } else if (keepgoing)
                           pgn->make = false;
                   else {
   
                           if (gn->lineno)
                                   printf("\n\nStop in %s (line %lu of %s).\n",
                                       Var_Value(".CURDIR"),
                                       (unsigned long)gn->lineno,
                                       gn->fname);
                           else
                                   printf("\n\nStop in %s.\n",
                                       Var_Value(".CURDIR"));
                           exit(1);
                   }
           } else if (gn->made == ERROR)
                   /* Already had an error when making this beastie. Tell the
                    * parent to abort.  */
                 pgn->make = false;                  pgn->make = false;
                 break;          else {
             case MADE:                  if (Lst_Member(&gn->iParents, pgn) != NULL) {
                 if ((gn->type & OP_EXEC) == 0) {                          Varq_Set(IMPSRC_INDEX, Varq_Value(TARGET_INDEX, gn),
                     pgn->childMade = true;                              pgn);
                     Make_TimeStamp(pgn, gn);  
                 }                  }
                 break;                  switch (gn->made) {
             case UPTODATE:                  case BEINGMADE:
                 if ((gn->type & OP_EXEC) == 0)                          Error("Graph cycles through %s\n", gn->name);
                     Make_TimeStamp(pgn, gn);                          gn->made = ERROR;
                 break;                          pgn->make = false;
             default:                          break;
                 break;                  case MADE:
                           if ((gn->type & OP_EXEC) == 0) {
                                   pgn->childMade = true;
                                   Make_TimeStamp(pgn, gn);
                           }
                           break;
                   case UPTODATE:
                           if ((gn->type & OP_EXEC) == 0)
                                   Make_TimeStamp(pgn, gn);
                           break;
                   default:
                           break;
                   }
         }          }
     }  
 }  }
   
 void  void
 Compat_Run(Lst targs)           /* List of target nodes to re-create */  Compat_Run(Lst targs)           /* List of target nodes to re-create */
 {  {
     char          *cp;          /* Pointer to string of shell meta-characters */          char *cp;               /* Pointer to string of shell meta-characters */
     GNode         *gn = NULL;   /* Current root target */          GNode *gn = NULL;       /* Current root target */
     int           errors;       /* Number of targets not remade due to errors */          int errors;             /* Number of targets not remade due to errors */
   
     signal(SIGINT, CompatInterrupt);          signal(SIGINT, CompatInterrupt);
     signal(SIGTERM, CompatInterrupt);          signal(SIGTERM, CompatInterrupt);
     signal(SIGHUP, CompatInterrupt);          signal(SIGHUP, CompatInterrupt);
     signal(SIGQUIT, CompatInterrupt);          signal(SIGQUIT, CompatInterrupt);
   
     for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++)          for (cp = "#=|^(){};&<>*?[]:$`\\\n"; *cp != '\0'; cp++)
         meta[(unsigned char) *cp] = 1;                  meta[(unsigned char) *cp] = 1;
     /* The null character serves as a sentinel in the string.  */          /* The null character serves as a sentinel in the string.  */
     meta[0] = 1;          meta[0] = 1;
   
     ENDNode = Targ_FindNode(".END", TARG_CREATE);          ENDNode = Targ_FindNode(".END", TARG_CREATE);
     /* If the user has defined a .BEGIN target, execute the commands attached          /* If the user has defined a .BEGIN target, execute the commands
      * to it.  */           * attached to it.  */
     if (!queryFlag) {          if (!queryFlag) {
         gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);                  gn = Targ_FindNode(".BEGIN", TARG_NOCREATE);
         if (gn != NULL) {                  if (gn != NULL) {
             Lst_ForEachNodeWhile(&gn->commands, CompatRunCommand, gn);                          Lst_ForEachNodeWhile(&gn->commands, CompatRunCommand,
             if (gn->made == ERROR) {                              gn);
                 printf("\n\nStop.\n");                          if (gn->made == ERROR) {
                 exit(1);                                  printf("\n\nStop.\n");
             }                                  exit(1);
                           }
                   }
         }          }
     }  
   
     /* For each entry in the list of targets to create, call CompatMake on          /* For each entry in the list of targets to create, call CompatMake on
      * it to create the thing. CompatMake will leave the 'made' field of gn           * it to create the thing. CompatMake will leave the 'made' field of gn
      * in one of several states:           * in one of several states:
      *      UPTODATE        gn was already up-to-date           *          UPTODATE        gn was already up-to-date
      *      MADE            gn was recreated successfully           *          MADE            gn was recreated successfully
      *      ERROR           An error occurred while gn was being created           *          ERROR           An error occurred while gn was being created
      *      ABORTED         gn was not remade because one of its inferiors           *          ABORTED         gn was not remade because one of its
      *                      could not be made due to errors.  */           *                          inferiors could not be made due to errors.
     errors = 0;           */
     while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) {          errors = 0;
         CompatMake(gn, gn);          while ((gn = (GNode *)Lst_DeQueue(targs)) != NULL) {
                   CompatMake(gn, gn);
   
         if (gn->made == UPTODATE)                  if (gn->made == UPTODATE)
             printf("`%s' is up to date.\n", gn->name);                          printf("`%s' is up to date.\n", gn->name);
         else if (gn->made == ABORTED) {                  else if (gn->made == ABORTED) {
             printf("`%s' not remade because of errors.\n", gn->name);                          printf("`%s' not remade because of errors.\n",
             errors += 1;                              gn->name);
                           errors += 1;
                   }
         }          }
     }  
   
     /* If the user has defined a .END target, run its commands.  */          /* If the user has defined a .END target, run its commands.  */
     if (errors == 0)          if (errors == 0)
         Lst_ForEachNodeWhile(&ENDNode->commands, CompatRunCommand, ENDNode);                  Lst_ForEachNodeWhile(&ENDNode->commands, CompatRunCommand,
                       ENDNode);
 }  }

Legend:
Removed from v.1.56  
changed lines
  Added in v.1.57