Some lucky people have been spammed with previous versions of this patch.
Caveat: this is work in progress, there might be bugs lurking.

Basically, I'm trying to achieve two goals:
- unify some more compat-make and make-j, so that there's less code duplication
and less weird semantics differences.
- give better, more precise error reports when things go wrong.


The main idea is that make-j used to spawn a subshell that would run commands.
This is all neat, except it gives main-make zero control over what's going
on, especially in case of trouble, and there was some ridiculously
complicated tail-optimization to avoid forking the last command when
possible.

Well, dpb does more or less the same work, but since I started it from scratch,
the architecture was radically different, with a single main process,
and a job data structure that would start each individual task in sequence,
continuation style.

In the process of the rewrite, I took apart the pipe stuff I added a few
years ago. Much to my surprise, it doesn't appear to be THAT useful now,
intermixed commands don't intermix so much, so I haven't put it back yet...
this also means that make-j now sees the terminal.

I also took apart the "make as job control", since that's not really all
that useful either.

Right now, the error reports are probably TOO verbose, and there are probably
bugs to iron out. This seems to work thru make build without trouble.

Improvements you're likely to see with make-j:
- mentions the target being made in case of errors.
- pinpoints error location to the line of the command being run, instead
of a general "in this target" area.
- shows command last run in case of a fatal error and in case the command
was silent.


I have just kept compat-make running as it was, since the goal is to
remove its job-running code completely and use the same code as for jobs...


Index: engine.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/engine.c,v
retrieving revision 1.30
diff -u -p -r1.30 engine.c
--- engine.c    25 Aug 2012 08:12:56 -0000      1.30
+++ engine.c    3 Sep 2012 11:30:03 -0000
@@ -66,13 +66,14 @@
 
 static void MakeTimeStamp(void *, void *);
 static int rewrite_time(const char *);
+typedef void (*psighandler)(int);
 static void setup_signal(int, psighandler);
+static void setup_all_signals(void);
+static void notice_signal(int);
 static void setup_meta(void);
 static char **recheck_command_for_shell(char **);
 
-static int setup_and_run_command(char *, GNode *, int);
-static void run_command(const char *, bool);
-static int run_prepared_gnode(GNode *);
+static int setup_and_run_command(char *, GNode *);
 static void handle_compat_interrupts(GNode *);
 
 bool
@@ -464,27 +465,8 @@ setup_signal(int sig, psighandler h)
                (void)signal(sig, h);
 }
 
-void
-setup_all_signals(psighandler interrupt, psighandler jc)
-{
-       /*
-        * Catch the four signals that POSIX specifies if they aren't ignored.
-        * handle_signal will take care of calling JobInterrupt if appropriate.
-        */
-       setup_signal(SIGINT, interrupt);
-       setup_signal(SIGHUP, interrupt);
-       setup_signal(SIGQUIT, interrupt);
-       setup_signal(SIGTERM, interrupt);
-       setup_signal(SIGTSTP, jc);
-       setup_signal(SIGTTOU, jc);
-       setup_signal(SIGTTIN, jc);
-       setup_signal(SIGWINCH, jc);
-       setup_signal(SIGCONT, jc);
-       got_signal = 0;
-}
-
-void
-SigHandler(int sig)
+static void
+notice_signal(int sig)
 {
        switch(sig) {
        case SIGINT:
@@ -506,6 +488,20 @@ SigHandler(int sig)
        }
 }
 
+void
+setup_all_signals(void)
+{
+       /*
+        * Catch the four signals that POSIX specifies if they aren't ignored.
+        * handle_signal will take care of calling JobInterrupt if appropriate.
+        */
+       setup_signal(SIGINT, notice_signal);
+       setup_signal(SIGHUP, notice_signal);
+       setup_signal(SIGQUIT, notice_signal);
+       setup_signal(SIGTERM, notice_signal);
+       got_signal = 0;
+}
+
 /* The following array is used to make a fast determination of which
  * characters are interpreted specially by the shell.  If a command
  * contains any of these characters, it is executed by the shell, not
@@ -544,7 +540,7 @@ recheck_command_for_shell(char **av)
        return av;
 }
 
-static void
+void
 run_command(const char *cmd, bool errCheck)
 {
        const char *p;
@@ -600,7 +596,7 @@ run_command(const char *cmd, bool errChe
  *-----------------------------------------------------------------------
  */
 static int
-setup_and_run_command(char *cmd, GNode *gn, int dont_fork)
+setup_and_run_command(char *cmd, GNode *gn)
 {
        bool silent;    /* Don't print command */
        bool doExecute; /* Execute the command */
@@ -635,24 +631,14 @@ setup_and_run_command(char *cmd, GNode *
                cmd++;
        /* Print the command before echoing if we're not supposed to be quiet
         * for this one. We also print the command if -n given.  */
-       if (!silent || noExecute) {
+       if (!silent || noExecute)
                printf("%s\n", cmd);
-               fflush(stdout);
-       }
+       fflush(stdout);
        /* If we're not supposed to execute any commands, this is as far as
         * we go...  */
        if (!doExecute)
                return 1;
 
-       /* if we're running in parallel mode, we try not to fork the last
-        * command, since it's exit status will be just fine... unless
-        * errCheck is not set, in which case we must deal with the
-        * status ourselves.
-        */
-       if (dont_fork && errCheck)
-               run_command(cmd, errCheck);
-               /*NOTREACHED*/
-
        /* Fork and execute the single command. If the fork fails, we abort.  */
        switch (cpid = fork()) {
        case -1:
@@ -717,7 +703,7 @@ handle_compat_interrupts(GNode *gn)
                char *file = Var(TARGET_INDEX, gn);
 
                if (!noExecute && eunlink(file) != -1)
-                       Error("*** %s removed\n", file);
+                       Error("*** %s removed", file);
        }
        if (got_SIGINT) {
                signal(SIGINT, SIG_IGN);
@@ -732,87 +718,43 @@ handle_compat_interrupts(GNode *gn)
        exit(255);
 }
 
-void
-expand_commands(GNode *gn)
+int
+run_gnode(GNode *gn)
 {
        LstNode ln;
-       char *cmd;
+       int result;
 
+       if (!gn || (gn->type & OP_DUMMY))
+               return NOSUCHNODE;
+       gn->built_status = MADE;
        Parse_SetLocation(&gn->origin);
        for (ln = Lst_First(&gn->commands); ln != NULL; ln = Lst_Adv(ln)) {
-               cmd = Var_Subst(Lst_Datum(ln), &gn->context, false);
-               Lst_AtEnd(&gn->expanded, cmd);
-       }
-}
+               struct command *command = Lst_Datum(ln);
+               int result;
+               char *cmd;
 
-int
-run_gnode(GNode *gn)
-{
-       if (gn != NULL && (gn->type & OP_DUMMY) == 0) {
-               expand_commands(gn);
+               Parse_SetLocation(&command->location);
+               cmd = Var_Subst(command->string, &gn->context, false);
                if (fatal_errors)
                        exit(1);
-               return run_prepared_gnode(gn);
-       } else {
-               return NOSUCHNODE;
-       }
-}
-
-static int
-run_prepared_gnode(GNode *gn)
-{
-       char *cmd;
-
-       gn->built_status = MADE;
-       while ((cmd = Lst_DeQueue(&gn->expanded)) != NULL) {
-               if (setup_and_run_command(cmd, gn, 0) == 0)
-                       break;
+               result = setup_and_run_command(cmd, gn);
                free(cmd);
+               if (result == 0)
+                       break;
        }
-       free(cmd);
        if (got_signal)
                handle_compat_interrupts(gn);
        return gn->built_status;
 }
 
 void
-run_gnode_parallel(GNode *gn)
-{
-       char *cmd;
-
-       gn->built_status = MADE;
-       /* XXX don't bother freeing cmd, we're dead anyways ! */
-       while ((cmd = Lst_DeQueue(&gn->expanded)) != NULL) {
-               if (setup_and_run_command(cmd, gn,
-                   Lst_IsEmpty(&gn->expanded)) == 0)
-                       break;
-       }
-       /* Normally, we don't reach this point, unless the last command
-        * ignores error, in which case we interpret the status ourselves.
-        */
-       switch(gn->built_status) {
-       case MADE:
-               exit(0);
-       case ERROR:
-               exit(1);
-       default:
-               fprintf(stderr, "Could not run gnode, returned %d\n",
-                   gn->built_status);
-               exit(1);
-       }
-}
-
-void
 setup_engine(int parallel)
 {
        static int already_setup = 0;
 
        if (!already_setup) {
                setup_meta();
-               if (parallel)
-                       setup_all_signals(parallel_handler, parallel_handler);
-               else
-                       setup_all_signals(SigHandler, SIG_DFL);
+               setup_all_signals();
                already_setup = 1;
        }
 }
Index: engine.h
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/engine.h,v
retrieving revision 1.9
diff -u -p -r1.9 engine.h
--- engine.h    19 Jul 2010 19:30:37 -0000      1.9
+++ engine.h    3 Sep 2012 10:21:58 -0000
@@ -74,11 +74,8 @@ extern volatile sig_atomic_t got_SIGINT,
 
 extern void SigHandler(int);
 extern int run_gnode(GNode *);
-extern void run_gnode_parallel(GNode *);
-extern void expand_commands(GNode *);
 
 extern void setup_engine(int);
-typedef void (*psighandler)(int);
-extern void setup_all_signals(psighandler, psighandler);
+extern void run_command(const char *, bool);
 
 #endif
Index: error.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/error.c,v
retrieving revision 1.21
diff -u -p -r1.21 error.c
--- error.c     22 Mar 2012 13:50:30 -0000      1.21
+++ error.c     3 Sep 2012 11:37:35 -0000
@@ -44,7 +44,6 @@
 #include "lowparse.h"
 
 int fatal_errors = 0;
-bool supervise_jobs = false;
 
 static void ParseVErrorInternal(const Location *, int, const char *, va_list);
 /*-
@@ -77,8 +76,7 @@ Fatal(char *fmt, ...)
 {
        va_list ap;
 
-       if (supervise_jobs)
-               Job_Wait();
+       Job_Wait();
 
        va_start(ap, fmt);
        (void)vfprintf(stderr, fmt, ap);
@@ -102,13 +100,15 @@ Fatal(char *fmt, ...)
 void
 Punt(char *fmt, ...)
 {
-       va_list ap;
+       if (fmt) {
+               va_list ap;
 
-       va_start(ap, fmt);
-       (void)fprintf(stderr, "make: ");
-       (void)vfprintf(stderr, fmt, ap);
-       va_end(ap);
-       (void)fprintf(stderr, "\n");
+               va_start(ap, fmt);
+               (void)fprintf(stderr, "make: ");
+               (void)vfprintf(stderr, fmt, ap);
+               va_end(ap);
+               (void)fprintf(stderr, "\n");
+       }
 
        Job_AbortAll();
        if (DEBUG(GRAPH2))
@@ -118,19 +118,16 @@ Punt(char *fmt, ...)
 
 /*
  * Finish --
- *     Called when aborting due to errors in child shell to signal
- *     abnormal exit.
+ *     Called when aborting due to errors in command or fatal signal
  *
  * Side Effects:
  *     The program exits
  */
 void
-Finish(int errors) /* number of errors encountered in Make_Make */
+Finish()
 {
        Job_Wait();
-       if (errors != 0) {
-               Error("Stop in %s:", Var_Value(".CURDIR"));
-       }
+       Error("Stop in %s:", Var_Value(".CURDIR"));
        print_errors();
        if (DEBUG(GRAPH2))
                Targ_PrintGraph(2);
Index: error.h
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/error.h,v
retrieving revision 1.11
diff -u -p -r1.11 error.h
--- error.h     19 Jul 2010 19:46:44 -0000      1.11
+++ error.h     3 Sep 2012 10:21:58 -0000
@@ -44,7 +44,7 @@
 extern void Error(char *, ...);
 extern void Fatal(char *, ...);
 extern void Punt(char *, ...);
-extern void Finish(int);
+extern void Finish();
 
 /*
  * Error levels for parsing. PARSE_FATAL means the process cannot continue
Index: gnode.h
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/gnode.h,v
retrieving revision 1.19
diff -u -p -r1.19 gnode.h
--- gnode.h     11 Apr 2012 18:27:30 -0000      1.19
+++ gnode.h     3 Sep 2012 11:05:59 -0000
@@ -132,7 +132,6 @@ struct GNode_ {
     SymTable context;  /* The local variables */
     Location origin;   /* First line number and file name of commands. */
     LIST commands;     /* Creation commands */
-    LIST expanded;     /* Expanded commands */
     struct Suff_ *suffix;/* Suffix for the node (determined by
                         * Suff_FindDeps and opaque to everyone
                         * but the Suff module) */
@@ -141,6 +140,12 @@ struct GNode_ {
     char *basename;    /* pointer to name stripped of path */
     struct GNode_ *next;
     char name[1];      /* The target's name */
+};
+
+struct command
+{
+       Location location;
+       char string[1];
 };
 
 #define has_been_built(gn) \
Index: job.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/job.c,v
retrieving revision 1.123
diff -u -p -r1.123 job.c
--- job.c       25 Aug 2012 08:12:56 -0000      1.123
+++ job.c       3 Sep 2012 11:35:00 -0000
@@ -109,13 +109,7 @@
  * Each job has several things associated with it:
  *     1) The process id of the child shell
  *     2) The graph node describing the target being made by this job
- *     3) An FILE* for writing out the commands. This is only
- *        used before the job is actually started.
- *     4) Things used for handling the shell's output.
- *        the output is being caught via a pipe and
- *        the descriptors of our pipe, an array in which output is line
- *        buffered and the current position in that buffer are all
- *        maintained for each job.
+ *     3) State associated to latest command run
  *     5) A word of flags which determine how the module handles errors,
  *        echoing, etc. for the job
  *
@@ -127,28 +121,20 @@
  * parents of the node which was just remade. This takes care of the upward
  * traversal of the dependency graph.
  */
-#define JOB_BUFSIZE    1024
-struct job_pipe {
-       int fd;
-       char buffer[JOB_BUFSIZE];
-       size_t pos;
-};
-
 typedef struct Job_ {
-    pid_t      pid;        /* The child's process ID */
-    GNode      *node;      /* The target the child is making */
-    short      flags;      /* Flags to control treatment of job */
-    LstNode    p;
-#define JOB_DIDOUTPUT  0x001
-#define JOB_IS_SPECIAL 0x004   /* Target is a special one. */
+       Location        *location;
+       pid_t           pid;            /* Current command process id */
+       int             status;         /* Last child exit status */
+       LstNode         next_cmd;       /* Next command to run */
+       char            *cmd;           /* Last command run */
+       GNode           *node;          /* Target of this job */
+       unsigned short  flags;
+#define JOB_SILENT     0x001   /* Command was silent */
 #define JOB_IS_EXPENSIVE 0x002
-    struct job_pipe in[2];
+#define JOB_IS_SPECIAL 0x004   /* Target is a special one. */
+#define JOB_ERRCHECK   0x008   /* command wants errcheck */
 } Job;
 
-struct job_pid {
-       pid_t pid;
-};
-
 static int     aborting = 0;       /* why is the make aborting? */
 #define ABORT_ERROR    1           /* Because of an error */
 #define ABORT_INTERRUPT 2          /* Because it was interrupted */
@@ -156,120 +142,65 @@ static int       aborting = 0;       /* why is t
 
 static int     maxJobs;        /* The most children we can run at once */
 static int     nJobs;          /* The number of current children */
-static bool    expensive_job;
-static LIST    runningJobs;    /* The structures that describe them */
+static bool    expensive_job;  /* Mark recursive shit so we shouldn't start
+                                * something else at the same time
+                                */
+static LIST    runningJobs;    /* Jobs current running */
+static LIST    heldJobs;       /* Jobs not running yet because of expensive */
+static LIST    errorJobs;      /* Jobs in error at end */
 static GNode   *lastNode;      /* The node for which output was most recently
                                 * produced. */
-static LIST    job_pids;       /* a simple list that doesn't move that much */
-
-/* data structure linked to job handling through select */
-static fd_set *output_mask = NULL;     /* File descriptors to look for */
-
-static fd_set *actual_mask = NULL;     /* actual select argument */
-static int largest_fd = -1;
-static size_t mask_size = 0;
 
 /* wait possibilities */
 #define JOB_EXITED 0
 #define JOB_SIGNALED 1
 #define JOB_UNKNOWN 4
 
-static LIST    errorsList;
-static int     errors;
-struct error_info {
-       int reason;
-       int code;
-       GNode *n;
-};
-
-/* for blocking/unblocking */
-static sigset_t oset, set;
-static void block_signals(void);
-static void unblock_signals(void);
-
 static void handle_all_signals(void);
 static void handle_signal(int);
 static int JobCmpPid(void *, void *);
-static void process_job_status(Job *, int);
-static void JobExec(Job *);
+static void process_job_status(Job *, bool);
 static void JobStart(GNode *, int);
 static void JobInterrupt(bool, int);
 static void debug_printf(const char *, ...);
 static Job *prepare_job(GNode *, int);
 static void banner(Job *, FILE *);
 static bool Job_Full(void);
+static void remove_job(Job *, bool);
+static bool handle_job_child(Job *);
+static void continue_job(Job *);
 
-/***
- ***  Input/output from jobs
- ***/
-
-/* prepare_pipe(jp, &fd):
- *     set up pipe data structure (buffer and pos) corresponding to
- *     pointed fd, and prepare to watch for it.
- */
-static void prepare_pipe(struct job_pipe *, int *);
-
-/* close_job_pipes(j):
- *     handle final output from job, and close pipes properly
- */
-static void close_job_pipes(Job *);
-
-
-static void handle_all_jobs_output(void);
-
-/* handle_job_output(job, n, finish):
- *     n = 0 or 1 (stdout/stderr), set finish to retrieve everything.
- */
-static void handle_job_output(Job *, int, bool);
-
-static void print_partial_buffer(struct job_pipe *, Job *, FILE *, size_t);
-static void print_partial_buffer_and_shift(struct job_pipe *, Job *, FILE *,
-    size_t);
-static bool print_complete_lines(struct job_pipe *, Job *, FILE *, size_t);
-
-
-static void register_error(int, int, Job *);
 static void loop_handle_running_jobs(void);
-static void Job_CatchChildren(void);
-
-static void
-register_error(int reason, int code, Job *job)
-{
-       struct error_info *p;
-
-       errors++;
-       p = emalloc(sizeof(struct error_info));
-       p->reason = reason;
-       p->code = code;
-       p->n = job->node;
-       Lst_AtEnd(&errorsList, p);
-}
 
 void
 print_errors()
 {
        LstNode ln;
-       struct error_info *p;
-       const char *type;
 
-       for (ln = Lst_First(&errorsList); ln != NULL; ln = Lst_Adv(ln)) {
-               p = (struct error_info *)Lst_Datum(ln);
-               switch(p->reason) {
-               case JOB_EXITED:
+       for (ln = Lst_First(&errorJobs); ln != NULL; ln = Lst_Adv(ln)) {
+               int code;
+               const char *type;
+
+               Job *j = (Job *)Lst_Datum(ln);
+               if (WIFEXITED(j->status)) {
                        type = "Exit status";
-                       break;
-               case JOB_SIGNALED:
+                       code = WEXITSTATUS(j->status);
+               } else if (WIFSIGNALED(j->status)) {
                        type = "Received signal";
-                       break;
-               default:
+                       code = WTERMSIG(j->status);
+               } else {
                        type = "Should not happen";
-                       break;
+                       code = j->status;
                }
-       if (p->n->origin.lineno)
-               Error(" %s %d (%s, line %lu of %s)",
-                   type, p->code, p->n->name, p->n->origin.lineno, 
p->n->origin.fname);
-       else
-               Error(" %s %d (%s)", type, p->code, p->n->name);
+               fprintf(stderr, " %s %d (", type, code);
+               if (j->location) 
+                       fprintf(stderr, "line %lu of %s, ",
+                           j->location->lineno, j->location->fname);
+               fprintf(stderr, "target %s", j->node->name);
+               if (j->node->origin.lineno)
+                       fprintf(stderr, ", line %lu of %s",
+                           j->node->origin.lineno, j->node->origin.fname);
+               fprintf(stderr, ")\n");
        }
 }
 
@@ -283,8 +214,6 @@ banner(Job *job, FILE *out)
        }
 }
 
-volatile sig_atomic_t got_SIGTSTP, got_SIGTTOU, got_SIGTTIN, got_SIGWINCH,
-    got_SIGCONT;
 static void
 handle_all_signals()
 {
@@ -307,89 +236,13 @@ handle_all_signals()
                        got_SIGTERM=0;
                        handle_signal(SIGTERM);
                }
-               if (got_SIGTSTP) {
-                       got_SIGTSTP=0;
-                       signal(SIGTSTP, parallel_handler);
-               }
-               if (got_SIGTTOU) {
-                       got_SIGTTOU=0;
-                       signal(SIGTTOU, parallel_handler);
-               }
-               if (got_SIGTTIN) {
-                       got_SIGTTIN=0;
-                       signal(SIGTTIN, parallel_handler);
-               }
-               if (got_SIGWINCH) {
-                       got_SIGWINCH=0;
-                       signal(SIGWINCH, parallel_handler);
-               }
-               if (got_SIGCONT) {
-                       got_SIGCONT = 0;
-                       signal(SIGCONT, parallel_handler);
-               }
-       }
-}
-
-/* this is safe from interrupts, actually */
-void
-parallel_handler(int signo)
-{
-       int save_errno = errno;
-       LstNode ln;
-       for (ln = Lst_First(&job_pids); ln != NULL; ln = Lst_Adv(ln)) {
-               struct job_pid *p = Lst_Datum(ln);
-               killpg(p->pid, signo);
-       }
-       errno = save_errno;
-
-       switch(signo) {
-       case SIGINT:
-               got_SIGINT++;
-               got_signal = 1;
-               return;
-       case SIGHUP:
-               got_SIGHUP++;
-               got_signal = 1;
-               return;
-       case SIGQUIT:
-               got_SIGQUIT++;
-               got_signal = 1;
-               return;
-       case SIGTERM:
-               got_SIGTERM++;
-               got_signal = 1;
-               return;
-       case SIGTSTP:
-               got_SIGTSTP++;
-               got_signal = 1;
-               break;
-       case SIGTTOU:
-               got_SIGTTOU++;
-               got_signal = 1;
-               break;
-       case SIGTTIN:
-               got_SIGTTIN++;
-               got_signal = 1;
-               break;
-       case SIGWINCH:
-               got_SIGWINCH++;
-               got_signal = 1;
-               break;
-       case SIGCONT:
-               got_SIGCONT++;
-               got_signal = 1;
-               break;
        }
-       (void)killpg(getpid(), signo);
-
-       (void)signal(signo, SIG_DFL);
-       errno = save_errno;
 }
 
 /*-
  *-----------------------------------------------------------------------
  * handle_signal --
- *     handle a signal for ourselves
+ *     handle a signal in the main loop
  *
  *-----------------------------------------------------------------------
  */
@@ -413,7 +266,7 @@ handle_signal(int signo)
                JobInterrupt(false, signo);
 
        if (signo == SIGQUIT)
-               Finish(0);
+               Finish();
 }
 
 /*-
@@ -447,18 +300,6 @@ debug_printf(const char *fmt, ...)
        }
 }
 
-static void
-close_job_pipes(Job *job)
-{
-       int i;
-
-       for (i = 1; i >= 0; i--) {
-               FD_CLR(job->in[i].fd, output_mask);
-               handle_job_output(job, i, true);
-               (void)close(job->in[i].fd);
-       }
-}
-
 /*-
  *-----------------------------------------------------------------------
  * process_job_status  --
@@ -478,10 +319,11 @@ close_job_pipes(Job *job)
 /*ARGSUSED*/
 
 static void
-process_job_status(Job *job, int status)
+process_job_status(Job *job, bool okay)
 {
        int reason, code;
-       bool     done;
+
+       int status = job->status;
 
        debug_printf("Process %ld (%s) exited with status %d.\n",
            (long)job->pid, job->node->name, status);
@@ -493,44 +335,13 @@ process_job_status(Job *job, int status)
                reason = JOB_SIGNALED;
                code = WTERMSIG(status);
        } else {
-               /* can't happen, set things to be bad. */
-               reason = UNKNOWN;
-               code = status;
-       }
-
-       if ((reason == JOB_EXITED &&
-            code != 0 && !(job->node->type & OP_IGNORE)) ||
-           reason == JOB_SIGNALED) {
-               /*
-                * If it exited non-zero and either we're doing things our
-                * way or we're not ignoring errors, the job is finished.
-                * Similarly, if the shell died because of a signal
-                * the job is also finished. In these
-                * cases, finish out the job's output before printing the exit
-                * status...
-                */
-               close_job_pipes(job);
-               done = true;
-       } else if (reason == JOB_EXITED) {
-               /*
-                * Deal with ignored errors. We need to print a message telling
-                * of the ignored error as well as setting status.w_status to 0
-                * so the next command gets run. To do this, we set done to be
-                * true and the job exited non-zero.
-                */
-               done = code != 0;
-               close_job_pipes(job);
-       } else {
-               /*
-                * No need to close things down or anything.
-                */
-               done = false;
+               Punt("Abort: weird process exit from %ld (%s): %d\n",
+                   (long)job->pid, job->node->name, status);
+               /*NOTREACHED*/
        }
 
-       if (done || DEBUG(JOB)) {
+       if (DEBUG(JOB)) {
                if (reason == JOB_EXITED) {
-                       debug_printf("Process %ld (%s) exited.\n",
-                           (long)job->pid, job->node->name);
                        if (code != 0) {
                                banner(job, stdout);
                                (void)fprintf(stdout, "*** Error code %d %s\n",
@@ -542,10 +353,6 @@ process_job_status(Job *job, int status)
                                        reason = JOB_EXITED;
                                        code = 0;
                                }
-                       } else if (DEBUG(JOB)) {
-                               (void)fprintf(stdout,
-                                   "*** %ld (%s) Completed successfully\n",
-                                   (long)job->pid, job->node->name);
                        }
                } else {
                        banner(job, stdout);
@@ -555,159 +362,25 @@ process_job_status(Job *job, int status)
                (void)fflush(stdout);
        }
 
-       done = true;
-
-       if (done &&
+       if (okay &&
            aborting != ABORT_ERROR &&
-           aborting != ABORT_INTERRUPT &&
-           reason == JOB_EXITED && code == 0) {
+           aborting != ABORT_INTERRUPT) {
                /* As long as we aren't aborting and the job didn't return a
                 * non-zero status that we shouldn't ignore, we call
                 * Make_Update to update the parents. */
                job->node->built_status = MADE;
                Make_Update(job->node);
+               free(job);
        } else if (!(reason == JOB_EXITED && code == 0)) {
-               register_error(reason, code, job);
+               Lst_AtEnd(&errorJobs, job);
        }
-       free(job);
 
-       if (errors && !keepgoing &&
+       if (!Lst_IsEmpty(&errorJobs) && !keepgoing &&
            aborting != ABORT_INTERRUPT)
                aborting = ABORT_ERROR;
 
        if (aborting == ABORT_ERROR && Job_Empty())
-               Finish(errors);
-}
-
-static void
-prepare_pipe(struct job_pipe *p, int *fd)
-{
-       p->pos = 0;
-       (void)fcntl(fd[0], F_SETFD, FD_CLOEXEC);
-       p->fd = fd[0];
-       close(fd[1]);
-
-       if (output_mask == NULL || p->fd > largest_fd) {
-               int fdn, ofdn;
-
-               fdn = howmany(p->fd+1, NFDBITS);
-               ofdn = howmany(largest_fd+1, NFDBITS);
-
-               if (fdn != ofdn) {
-                       output_mask = emult_realloc(output_mask, fdn,
-                           sizeof(fd_mask));
-                       memset(((char *)output_mask) + ofdn * sizeof(fd_mask),
-                           0, (fdn-ofdn) * sizeof(fd_mask));
-                       actual_mask = emult_realloc(actual_mask, fdn,
-                           sizeof(fd_mask));
-                       mask_size = fdn * sizeof(fd_mask);
-               }
-               largest_fd = p->fd;
-       }
-       fcntl(p->fd, F_SETFL, O_NONBLOCK);
-       FD_SET(p->fd, output_mask);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * JobExec --
- *     Execute the shell for the given job. Called from JobStart
- *
- * Side Effects:
- *     A shell is executed, outputs is altered and the Job structure added
- *     to the job table.
- *-----------------------------------------------------------------------
- */
-static void
-JobExec(Job *job)
-{
-       pid_t cpid;     /* ID of new child */
-       struct job_pid *p;
-       int fds[4];
-       int *fdout = fds;
-       int *fderr = fds+2;
-       int i;
-
-       banner(job, stdout);
-
-       setup_engine(1);
-
-       /* Create the pipe by which we'll get the shell's output.
-        */
-       if (pipe(fdout) == -1)
-               Punt("Cannot create pipe: %s", strerror(errno));
-
-       if (pipe(fderr) == -1)
-               Punt("Cannot create pipe: %s", strerror(errno));
-
-       block_signals();
-       if ((cpid = fork()) == -1) {
-               Punt("Cannot fork");
-               unblock_signals();
-       } else if (cpid == 0) {
-               supervise_jobs = false;
-               /* standard pipe code to route stdout and stderr */
-               close(fdout[0]);
-               if (dup2(fdout[1], 1) == -1)
-                       Punt("Cannot dup2(outPipe): %s", strerror(errno));
-               if (fdout[1] != 1)
-                       close(fdout[1]);
-               close(fderr[0]);
-               if (dup2(fderr[1], 2) == -1)
-                       Punt("Cannot dup2(errPipe): %s", strerror(errno));
-               if (fderr[1] != 2)
-                       close(fderr[1]);
-
-               /*
-                * We want to switch the child into a different process family
-                * so we can kill it and all its descendants in one fell swoop,
-                * by killing its process family, but not commit suicide.
-                */
-               (void)setpgid(0, getpid());
-
-               if (random_delay)
-                       if (!(nJobs == 1 && no_jobs_left()))
-                               usleep(random() % random_delay);
-
-               setup_all_signals(SigHandler, SIG_DFL);
-               unblock_signals();
-               /* this exits directly */
-               run_gnode_parallel(job->node);
-               /*NOTREACHED*/
-       } else {
-               supervise_jobs = true;
-               job->pid = cpid;
-
-               /* we set the current position in the buffers to the beginning
-                * and mark another stream to watch in the outputs mask
-                */
-               for (i = 0; i < 2; i++)
-                       prepare_pipe(&job->in[i], fds+2*i);
-       }
-       /*
-        * Now the job is actually running, add it to the table.
-        */
-       nJobs++;
-       Lst_AtEnd(&runningJobs, job);
-       if (job->flags & JOB_IS_EXPENSIVE)
-               expensive_job = true;
-       p = emalloc(sizeof(struct job_pid));
-       p->pid = cpid;
-       Lst_AtEnd(&job_pids, p);
-       job->p = Lst_Last(&job_pids);
-
-       unblock_signals();
-       if (DEBUG(JOB)) {
-               LstNode ln;
-
-               (void)fprintf(stdout, "Running %ld (%s)\n", (long)cpid,
-                   job->node->name);
-               for (ln = Lst_First(&job->node->commands); ln != NULL ;
-                   ln = Lst_Adv(ln))
-                       fprintf(stdout, "\t%s\n", (char *)Lst_Datum(ln));
-               (void)fflush(stdout);
-       }
-
+               Finish();
 }
 
 static bool
@@ -757,16 +430,6 @@ expensive_command(const char *s)
        return false;
 }
 
-static bool
-expensive_commands(Lst l)
-{
-       LstNode ln;
-       for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln))
-               if (expensive_command(Lst_Datum(ln)))
-                       return true;
-       return false;
-}
-
 static Job *
 prepare_job(GNode *gn, int flags)
 {
@@ -778,9 +441,6 @@ prepare_job(GNode *gn, int flags)
         * to migrate to the node
         */
        cmdsOK = Job_CheckCommands(gn);
-       expand_commands(gn);
-       if (fatal_errors)
-               Punt("can't continue");
 
        if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) {
                /*
@@ -832,21 +492,131 @@ prepare_job(GNode *gn, int flags)
 
                job->node = gn;
 
+               job->next_cmd = Lst_First(&gn->commands);
                /*
                 * Set the initial value of the flags for this job based on the
                 * global ones and the node's attributes... Any flags supplied
                 * by the caller are also added to the field.
                 */
                job->flags = flags;
+               job->location = NULL;
+
+               return job;
+       }
+}
+
+static bool
+do_run_command(Job *job, const char *cmd)
+{
+       bool silent;    /* Don't print command */
+       bool doExecute; /* Execute the command */
+       bool errCheck;  /* Check errors */
+       pid_t cpid;     /* Child pid */
+
+       silent = job->node->type & OP_SILENT;
+       errCheck = !(job->node->type & OP_IGNORE);
+       doExecute = !noExecute;
+
+       /* How can we execute a null command ? we warn the user that the
+        * command expanded to nothing (is this the right thing to do?).  */
+       if (*cmd == '\0') {
+               Error("%s expands to empty string", cmd);
+               return false;
+       }
+
+       for (;; cmd++) {
+               if (*cmd == '@')
+                       silent = DEBUG(LOUD) ? false : true;
+               else if (*cmd == '-')
+                       errCheck = false;
+               else if (*cmd == '+')
+                       doExecute = true;
+               else
+                       break;
+       }
+       while (isspace(*cmd))
+               cmd++;
+       /* Print the command before fork if make -n */
+       if ( noExecute)
+               printf("%s\n", cmd);
+       
+       if (silent)
+               job->flags |= JOB_SILENT;
+       else
+               job->flags &= ~JOB_SILENT;
 
-               if (gn->type & OP_CHEAP)
-                       return job;
-               if ((gn->type & OP_EXPENSIVE) || 
-                   expensive_commands(&gn->expanded))
+       /* If we're not supposed to execute any commands, this is as far as
+        * we go...  */
+       if (!doExecute)
+               return false;
+       if (job->node->type & OP_CHEAP)
+               ;
+       else 
+               if ((job->node->type & OP_EXPENSIVE) || expensive_command(cmd)) 
{
                        job->flags |= JOB_IS_EXPENSIVE;
+                       expensive_job = true;
+               }
 
-               return job;
+       fflush(stdout);
+
+       /* Fork and execute the single command. If the fork fails, we abort.  */
+       switch (cpid = fork()) {
+       case -1:
+               Punt("Could not fork");
+               /*NOTREACHED*/
+       case 0:
+               if (!silent) {
+                       printf("%s\n", cmd);
+                       fflush(stdout);
+               }
+               if (random_delay)
+                       if (!(nJobs == 1 && no_jobs_left()))
+                               usleep(random() % random_delay);
+
+               run_command(cmd, errCheck);
+               /*NOTREACHED*/
+       default:
+               job->pid = cpid;
+               if (errCheck)
+                       job->flags |= JOB_ERRCHECK;
+               else
+                       job->flags &= ~JOB_ERRCHECK;
+               return true;
+       }
+}
+
+static bool
+job_run_next(Job *job)
+{
+       char *cmd;
+       bool started;
+       GNode *gn = job->node;
+
+       banner(job, stdout);
+
+       if (expensive_job) {
+               Lst_AtEnd(&heldJobs, job);
+               return false;
+       }
+       setup_engine(1);
+       while (job->next_cmd != NULL) {
+               struct command *command = Lst_Datum(job->next_cmd);
+               job->location = &command->location;
+               Parse_SetLocation(job->location);
+               cmd = Var_Subst(command->string, &gn->context, false);
+               job->next_cmd = Lst_Adv(job->next_cmd);
+               if (fatal_errors)
+                       Punt(NULL);
+               started = do_run_command(job, cmd);
+               if (started) {
+                       Lst_AtEnd(&runningJobs, job);
+                       job->cmd = cmd;
+                       return false;
+               } else
+                       free(cmd);
        }
+       job->status = 0;
+       return true;
 }
 
 /*-
@@ -866,153 +636,143 @@ JobStart(GNode *gn,             /* target to 
                                 * e.g. JOB_IS_SPECIAL */
 {
        Job *job;
+       bool finished;
+
        job = prepare_job(gn, flags);
        if (!job)
                return;
-       JobExec(job);
-}
-
-/* Helper functions for JobDoOutput */
-
-
-/* output debugging banner and print characters from 0 to endpos */
-static void
-print_partial_buffer(struct job_pipe *p, Job *job, FILE *out, size_t endPos)
-{
-       size_t i;
+       nJobs++;
+       finished = job_run_next(job);
+       if (finished) {
+               remove_job(job, true);
+       } else if (DEBUG(JOB)) {
+               LstNode ln;
 
-       banner(job, out);
-       job->flags |= JOB_DIDOUTPUT;
-       for (i = 0; i < endPos; i++)
-               putc(p->buffer[i], out);
+               (void)fprintf(stdout, "Running %ld (%s)\n", (long)job->pid,
+                   job->node->name);
+               for (ln = Lst_First(&job->node->commands); ln != NULL ;
+                   ln = Lst_Adv(ln))
+                       fprintf(stdout, "\t%s\n", (char *)Lst_Datum(ln));
+               (void)fflush(stdout);
+       }
 }
 
-/* print partial buffer and shift remaining contents */
 static void
-print_partial_buffer_and_shift(struct job_pipe *p, Job *job, FILE *out,
-    size_t endPos)
+continue_job(Job *job)
 {
-       size_t i;
+       bool finished;
 
-       print_partial_buffer(p, job, out, endPos);
-
-       for (i = endPos; i < p->pos; i++)
-               p->buffer[i-endPos] = p->buffer[i];
-       p->pos -= endPos;
+       finished = job_run_next(job);
+       if (finished) {
+               remove_job(job, true);
+       }
 }
 
-/* print complete lines, looking back to the limit position
- * (stuff before limit was already scanned).
- * returns true if something was printed.
- */
-static bool
-print_complete_lines(struct job_pipe *p, Job *job, FILE *out, size_t limit)
-{
-       size_t i;
+/* Helper functions for JobDoOutput */
 
-       for (i = p->pos; i > limit; i--) {
-               if (p->buffer[i-1] == '\n') {
-                       print_partial_buffer_and_shift(p, job, out, i);
-                       return true;
-               }
-       }
-       return false;
-}
 
-/*-
- *-----------------------------------------------------------------------
- * handle_pipe --
- *     This functions is called whenever there is something to read on the
- *     pipe. We collect more output from the given job and store it in the
- *     job's outBuf. If this makes up lines, we print it tagged by the job's
- *     identifier, as necessary.
- *
- * Side Effects:
- *     curPos may be shifted as may the contents of outBuf.
- *-----------------------------------------------------------------------
- */
 static void
-handle_pipe(struct job_pipe *p,
-       Job *job, FILE *out, bool finish)
+may_remove_job(LstNode ln, int status)
 {
-       int nr;                 /* number of bytes read */
-       int oldpos;             /* optimization */
+       bool okay;
+       Job *job = (Job *)Lst_Datum(ln);
 
-       /* want to get everything ? -> we block */
-       if (finish)
-               fcntl(p->fd, F_SETFL, 0);
-
-       do {
-               nr = read(p->fd, &p->buffer[p->pos],
-                   JOB_BUFSIZE - p->pos);
-               if (nr == -1) {
-                       if (errno == EAGAIN)
-                               break;
-                       if (DEBUG(JOB)) {
-                               perror("JobDoOutput(piperead)");
-                       }
-               }
-               oldpos = p->pos;
-               p->pos += nr;
-               if (!print_complete_lines(p, job, out, oldpos))
-                       if (p->pos == JOB_BUFSIZE) {
-                               print_partial_buffer(p, job, out, p->pos);
-                               p->pos = 0;
-                       }
-       } while (nr != 0);
+       job->status = status;
+       Lst_Remove(&runningJobs, ln);
+       if (job->flags & JOB_IS_EXPENSIVE) {
+               expensive_job = false;
+               job->flags &= ~JOB_IS_EXPENSIVE;
+       }
 
-       /* at end of file, we print whatever is left */
-       if (nr == 0) {
-               print_partial_buffer(p, job, out, p->pos);
-               if (p->pos > 0 && p->buffer[p->pos - 1] != '\n')
-                       putchar('\n');
-               p->pos = 0;
+       okay = handle_job_child(job);
+       if (!okay || job->next_cmd == NULL) {
+               remove_job(job, okay);
+       } else {
+               continue_job(job);
        }
 }
 
 static void
-handle_job_output(Job *job, int i, bool finish)
+remove_job(Job *job, bool okay)
 {
-       handle_pipe(&job->in[i], job, i == 0 ? stdout : stderr, finish);
+       nJobs--;
+       process_job_status(job, okay);
+       while (!expensive_job) {
+               if ((job = Lst_DeQueue(&heldJobs)) != NULL) 
+                       continue_job(job);
+               else
+                       break;
+       }
 }
 
-static void
-remove_job(LstNode ln, int status)
+static bool 
+handle_job_child(Job *job)
 {
-       Job *job;
+       int code;
+       bool okay = false;
 
-       job = (Job *)Lst_Datum(ln);
-       Lst_Remove(&runningJobs, ln);
-       block_signals();
-       free(Lst_Datum(job->p));
-       Lst_Remove(&job_pids, job->p);
-       unblock_signals();
-       nJobs--;
-       if (job->flags & JOB_IS_EXPENSIVE)
-               expensive_job = false;
-       process_job_status(job, status);
-}
+       int status = job->status;
 
+       if (WIFEXITED(status)) {
+               code = WEXITSTATUS(status);     /* exited */
+               if (code != 0)
+                       printf("*** Error code %d", code);
+               else
+                       okay = true;
+       } else {
+               code = WTERMSIG(status);        /* signaled */
+               printf("*** Signal %d", code);
+       }
+
+       if (!okay) {
+               printf(" in target %s (line %lu of %s) ", job->node->name,
+                   job->node->origin.lineno, job->node->origin.fname);
+               if (job->flags & JOB_ERRCHECK) {
+                       job->node->built_status = ERROR;
+                       if (keepgoing)
+                               /* Abort the current target,
+                                * but let others continue.  */
+                               printf(" (continuing)\n");
+                       else {
+                               if (job->flags & JOB_SILENT)
+                                       printf("while running %s", job->cmd);
+                               else 
+                                       printf("running command");
+                               if (job->location)
+                                       printf(" at line %lu of %s", 
+                                           job->location->lineno, 
+                                           job->location->fname);
+                               printf("\n");
+                       }
+               } else {
+                       /* Continue executing commands for
+                        * this target.  If we return 0,
+                        * this will happen...  */
+                       printf(" (ignored)\n");
+                       okay = true;
+               }
+       }
+       free(job->cmd);
+       return okay;
+}
 /*-
  *-----------------------------------------------------------------------
- * Job_CatchChildren --
- *     Handle the exit of a child. Called by handle_running_jobs
+ * handle_running_jobs(wait) --
+ *     Handle the exit of children
+ *     only wait for the first job, unless wait is true
  *
  * Side Effects:
- *     The job descriptor is removed from the list of children.
+ *     Jobs may be removed from the list
  *
- * Notes:
- *     We do waits, blocking or not, according to the wisdom of our
- *     caller, until there are no more children to report. For each
- *     job, call process_job_status to finish things off.
  *-----------------------------------------------------------------------
  */
 void
-Job_CatchChildren()
+handle_running_jobs(bool wait)
 {
        pid_t pid;      /* pid of dead child */
        LstNode jnode;  /* list element for finding job */
        int status;     /* Exit/termination status */
+       int wflag = 0;
 
        /*
         * Don't even bother if we know there's no one around.
@@ -1020,73 +780,26 @@ Job_CatchChildren()
        if (nJobs == 0)
                return;
 
-       while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
+       while ((pid = waitpid(WAIT_ANY, &status, wflag)) > 0) {
                handle_all_signals();
+               if (!wait)
+                       wflag = WNOHANG;
 
                jnode = Lst_Find(&runningJobs, JobCmpPid, &pid);
 
                if (jnode == NULL) {
                        Error("Child (%ld) not in table?", (long)pid);
                } else {
-                       remove_job(jnode, status);
-               }
-       }
-}
-
-void
-handle_all_jobs_output(void)
-{
-       int nfds;
-       struct timeval timeout;
-       LstNode ln, ln2;
-       Job *job;
-       int i;
-       int status;
-
-       /* no jobs */
-       if (Lst_IsEmpty(&runningJobs))
-               return;
-
-       (void)fflush(stdout);
-
-       memcpy(actual_mask, output_mask, mask_size);
-       timeout.tv_sec = SEL_SEC;
-       timeout.tv_usec = SEL_USEC;
-
-       nfds = select(largest_fd+1, actual_mask, NULL, NULL, &timeout);
-       handle_all_signals();
-       for (ln = Lst_First(&runningJobs); nfds && ln != NULL; ln = ln2) {
-               ln2 = Lst_Adv(ln);
-               job = (Job *)Lst_Datum(ln);
-               job->flags &= ~JOB_DIDOUTPUT;
-               for (i = 1; i >= 0; i--) {
-                       if (FD_ISSET(job->in[i].fd, actual_mask)) {
-                               nfds--;
-                               handle_job_output(job, i, false);
-                       }
-               }
-               if (job->flags & JOB_DIDOUTPUT) {
-                       if (waitpid(job->pid, &status, WNOHANG) == job->pid) {
-                               remove_job(ln, status);
-                       } else {
-                               Lst_Requeue(&runningJobs, ln);
-                       }
+                       may_remove_job(jnode, status);
                }
        }
 }
 
-void
-handle_running_jobs()
-{
-       handle_all_jobs_output();
-       Job_CatchChildren();
-}
-
 static void
 loop_handle_running_jobs()
 {
        while (nJobs)
-               handle_running_jobs();
+               handle_running_jobs(true);
 }
 /*-
  *-----------------------------------------------------------------------
@@ -1105,18 +818,6 @@ Job_Make(GNode *gn)
 }
 
 
-static void
-block_signals()
-{
-       sigprocmask(SIG_BLOCK, &set, &oset);
-}
-
-static void
-unblock_signals()
-{
-       sigprocmask(SIG_SETMASK, &oset, NULL);
-}
-
 /*-
  *-----------------------------------------------------------------------
  * Job_Init --
@@ -1130,18 +831,11 @@ void
 Job_Init(int maxproc)
 {
        Static_Lst_Init(&runningJobs);
-       Static_Lst_Init(&errorsList);
+       Static_Lst_Init(&heldJobs);
+       Static_Lst_Init(&errorJobs);
        maxJobs = maxproc;
+
        nJobs = 0;
-       errors = 0;
-       sigemptyset(&set);
-       sigaddset(&set, SIGINT);
-       sigaddset(&set, SIGHUP);
-       sigaddset(&set, SIGQUIT);
-       sigaddset(&set, SIGTERM);
-       sigaddset(&set, SIGTSTP);
-       sigaddset(&set, SIGTTOU);
-       sigaddset(&set, SIGTTIN);
 
        aborting = 0;
 
@@ -1172,7 +866,7 @@ Job_Full()
 bool
 can_start_job(void)
 {
-       if (Job_Full() || expensive_job)
+       if (Job_Full())
                return false;
        else
                return true;
@@ -1229,7 +923,7 @@ JobInterrupt(bool runINTERRUPT,    /* true 
                if (job->pid) {
                        debug_printf("JobInterrupt passing signal to "
                            "child %ld.\n", (long)job->pid);
-                       killpg(job->pid, signo);
+                       kill(job->pid, signo);
                }
        }
 
@@ -1251,13 +945,15 @@ JobInterrupt(bool runINTERRUPT,  /* true 
  *     attached to the .END target.
  *
  * Results:
- *     Number of errors reported.
+ *     Errors have been reported.
  *
  *-----------------------------------------------------------------------
  */
-int
+bool
 Job_Finish(void)
 {
+       bool errors = !Lst_IsEmpty(&errorJobs);
+
        if ((end_node->type & OP_DUMMY) == 0) {
                if (errors) {
                        Error("Errors reported so .END ignored");
Index: job.h
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/job.h,v
retrieving revision 1.25
diff -u -p -r1.25 job.h
--- job.h       19 Jul 2010 19:46:44 -0000      1.25
+++ job.h       3 Sep 2012 10:21:58 -0000
@@ -58,7 +58,7 @@ extern void Job_End(void);
 extern void Job_Wait(void);
 extern void Job_AbortAll(void);
 extern void print_errors(void);
-extern void handle_running_jobs(void);
+extern void handle_running_jobs(bool);
 extern void parallel_handler(int);
 
 #endif /* _JOB_H_ */
Index: make.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/make.c,v
retrieving revision 1.63
diff -u -p -r1.63 make.c
--- make.c      21 Apr 2012 04:35:32 -0000      1.63
+++ make.c      3 Sep 2012 11:28:09 -0000
@@ -558,7 +558,7 @@ Make_Run(Lst targs)         /* the initial list
         * the keepgoing flag was given.
         */
        while (!Job_Empty()) {
-               handle_running_jobs();
+               handle_running_jobs(false);
                (void)MakeStartJobs();
        }
 
Index: parse.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/parse.c,v
retrieving revision 1.104
diff -u -p -r1.104 parse.c
--- parse.c     20 Apr 2012 13:28:11 -0000      1.104
+++ parse.c     3 Sep 2012 11:06:31 -0000
@@ -1441,7 +1441,14 @@ parse_commands(struct growableArray *tar
 {
        /* add the command to the list of
         * commands of all targets in the dependency spec */
-       char *cmd = estrdup(line);
+
+       struct command *cmd;
+       size_t len = strlen(line);
+
+       cmd = emalloc(sizeof(struct command) + len);
+       memcpy(&cmd->string, line, len+1);
+       Parse_FillLocation(&cmd->location);
+
 
        Array_ForEach(targets, ParseAddCmd, cmd);
 #ifdef CLEANUP
Index: targ.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/targ.c,v
retrieving revision 1.65
diff -u -p -r1.65 targ.c
--- targ.c      1 Sep 2012 16:44:25 -0000       1.65
+++ targ.c      3 Sep 2012 10:21:58 -0000
@@ -195,7 +195,6 @@ Targ_NewGNi(const char *name, const char
        gn->origin.fname = NULL;
        gn->impliedsrc = NULL;
        Lst_Init(&gn->commands);
-       Lst_Init(&gn->expanded);
        gn->suffix = NULL;
        gn->next = NULL;
        gn->basename = NULL;
Index: varmodifiers.c
===================================================================
RCS file: /home/openbsd/cvs/src/usr.bin/make/varmodifiers.c,v
retrieving revision 1.30
diff -u -p -r1.30 varmodifiers.c
--- varmodifiers.c      16 Aug 2011 14:18:25 -0000      1.30
+++ varmodifiers.c      3 Sep 2012 11:17:45 -0000
@@ -815,7 +815,7 @@ VarREError(int err, regex_t *pat, const 
        errlen = regerror(err, pat, 0, 0);
        errbuf = emalloc(errlen);
        regerror(err, pat, errbuf, errlen);
-       Error("%s: %s", str, errbuf);
+       Error("%s: %s\n", str, errbuf);
        free(errbuf);
 }
 
@@ -886,13 +886,13 @@ VarRESubstitute(struct Name *word, bool 
                                }
 
                                if (n > pat->nsub) {
-                                       Error("No subexpression %s",
+                                       Error("No subexpression %s\n",
                                            &errstr[0]);
                                        subbuf = "";
                                        sublen = 0;
                                } else if (pat->matches[n].rm_so == -1 &&
                                    pat->matches[n].rm_eo == -1) {
-                                       Error("No match for subexpression %s",
+                                       Error("No match for subexpression %s\n",
                                            &errstr[0]);
                                        subbuf = "";
                                        sublen = 0;
@@ -1503,7 +1503,7 @@ VarModifiers_Apply(char *str, const stru
                        printf("Result is \"%s\"\n", str);
        }
        if (*tstr == '\0')
-               Error("Unclosed variable specification");
+               Error("Unclosed variable specification\n");
        else
                tstr++;

Reply via email to