Imported Upstream version 4.0
[platform/upstream/make.git] / main.c
diff --git a/main.c b/main.c
index c6989e3..f60e6be 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,7 +1,5 @@
 /* Argument parsing and main program of GNU Make.
-Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-2010 Free Software Foundation, Inc.
+Copyright (C) 1988-2013 Free Software Foundation, Inc.
 This file is part of GNU Make.
 
 GNU Make is free software; you can redistribute it and/or modify it under the
@@ -16,9 +14,9 @@ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 You should have received a copy of the GNU General Public License along with
 this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#include "make.h"
-#include "dep.h"
+#include "makeint.h"
 #include "filedef.h"
+#include "dep.h"
 #include "variable.h"
 #include "job.h"
 #include "commands.h"
@@ -32,9 +30,11 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 # include <proto/dos.h>
 #endif
 #ifdef WINDOWS32
-#include <windows.h>
-#include <io.h>
-#include "pathstuff.h"
+# include <windows.h>
+# include <io.h>
+# include "pathstuff.h"
+# include "sub_proc.h"
+# include "w32err.h"
 #endif
 #ifdef __EMX__
 # include <sys/types.h>
@@ -64,11 +64,11 @@ void verify_file_data_base (void);
 # define HAVE_WAIT_NOHANG
 #endif
 
-#ifndef        HAVE_UNISTD_H
+#ifndef HAVE_UNISTD_H
 int chdir ();
 #endif
-#ifndef        STDC_HEADERS
-# ifndef sun                   /* Sun has an incorrect decl in a header.  */
+#ifndef STDC_HEADERS
+# ifndef sun                    /* Sun has an incorrect decl in a header.  */
 void exit (int) __attribute__ ((noreturn));
 # endif
 double atof ();
@@ -79,7 +79,7 @@ static void print_data_base (void);
 static void print_version (void);
 static void decode_switches (int argc, char **argv, int env);
 static void decode_env_switches (char *envar, unsigned int len);
-static const char *define_makeflags (int all, int makefile);
+static struct variable *define_makeflags (int all, int makefile);
 static char *quote_for_env (char *out, const char *in);
 static void initialize_global_hash_tables (void);
 
@@ -88,29 +88,29 @@ static void initialize_global_hash_tables (void);
 
 struct command_switch
   {
-    int c;                     /* The switch character.  */
+    int c;                      /* The switch character.  */
 
-    enum                       /* Type of the value.  */
+    enum                        /* Type of the value.  */
       {
-       flag,                   /* Turn int flag on.  */
-       flag_off,               /* Turn int flag off.  */
-       string,                 /* One string per switch.  */
-       filename,               /* A string containing a file name.  */
-       positive_int,           /* A positive integer.  */
-       floating,               /* A floating-point number (double).  */
-       ignore                  /* Ignored.  */
+        flag,                   /* Turn int flag on.  */
+        flag_off,               /* Turn int flag off.  */
+        string,                 /* One string per switch.  */
+        filename,               /* A string containing a file name.  */
+        positive_int,           /* A positive integer.  */
+        floating,               /* A floating-point number (double).  */
+        ignore                  /* Ignored.  */
       } type;
 
-    void *value_ptr;   /* Pointer to the value-holding variable.  */
+    void *value_ptr;    /* Pointer to the value-holding variable.  */
 
-    unsigned int env:1;                /* Can come from MAKEFLAGS.  */
-    unsigned int toenv:1;      /* Should be put in MAKEFLAGS.  */
-    unsigned int no_makefile:1;        /* Don't propagate when remaking makefiles.  */
+    unsigned int env:1;         /* Can come from MAKEFLAGS.  */
+    unsigned int toenv:1;       /* Should be put in MAKEFLAGS.  */
+    unsigned int no_makefile:1; /* Don't propagate when remaking makefiles.  */
 
-    const void *noarg_value;   /* Pointer to value used if no arg given.  */
-    const void *default_value; /* Pointer to default value.  */
+    const void *noarg_value;    /* Pointer to value used if no arg given.  */
+    const void *default_value;  /* Pointer to default value.  */
 
-    char *long_name;           /* Long option name.  */
+    char *long_name;            /* Long option name.  */
   };
 
 /* True if C is a switch value that corresponds to a short option.  */
@@ -122,14 +122,18 @@ struct command_switch
 
 struct stringlist
   {
-    const char **list; /* Nil-terminated list of strings.  */
-    unsigned int idx;  /* Index into above.  */
-    unsigned int max;  /* Number of pointers allocated.  */
+    const char **list;  /* Nil-terminated list of strings.  */
+    unsigned int idx;   /* Index into above.  */
+    unsigned int max;   /* Number of pointers allocated.  */
   };
 
 
 /* The recognized command switches.  */
 
+/* Nonzero means do extra verification (that may slow things down).  */
+
+int verify_flag;
+
 /* Nonzero means do not print commands to be executed (-s).  */
 
 int silent_flag;
@@ -146,14 +150,14 @@ int just_print_flag;
 
 /* Print debugging info (--debug).  */
 
-static struct stringlist *db_flags;
+static struct stringlist *db_flags = 0;
 static int debug_flag = 0;
 
 int db_level = 0;
 
-/* Output level (--verbosity).  */
+/* Synchronize output (--output-sync).  */
 
-static struct stringlist *verbosity_flags;
+static struct stringlist *output_sync_option = 0;
 
 #ifdef WINDOWS32
 /* Suspend make in main for a short time to allow debugger to attach */
@@ -235,6 +239,11 @@ static struct stringlist *jobserver_fds = 0;
 int job_fds[2] = { -1, -1 };
 int job_rfd = -1;
 
+/* Handle for the mutex used on Windows to synchronize output of our
+   children under -O.  */
+
+static struct stringlist *sync_mutex = 0;
+
 /* Maximum load average at which multiple jobs will be run.
    Negative values mean unlimited, while zero means limit to
    zero load (which could be useful to start infinite jobs remotely
@@ -343,6 +352,9 @@ static const char *const usage[] =
   -o FILE, --old-file=FILE, --assume-old=FILE\n\
                               Consider FILE to be very old and don't remake it.\n"),
     N_("\
+  -O[TYPE], --output-sync[=TYPE]\n\
+                              Synchronize output of parallel jobs by TYPE.\n"),
+    N_("\
   -p, --print-data-base       Print make's internal database.\n"),
     N_("\
   -q, --question              Run no recipe; exit status says if up to date.\n"),
@@ -358,6 +370,8 @@ static const char *const usage[] =
     N_("\
   -t, --touch                 Touch targets instead of remaking them.\n"),
     N_("\
+  --trace                     Print tracing information.\n"),
+    N_("\
   -v, --version               Print the version number of make and exit.\n"),
     N_("\
   -w, --print-directory       Print the current directory.\n"),
@@ -371,40 +385,26 @@ static const char *const usage[] =
     NULL
   };
 
-/* The table of command switches.  */
+/* The table of command switches.
+   Order matters here: this is the order MAKEFLAGS will be constructed.
+   So be sure all simple flags (single char, no argument) come first.  */
 
 static const struct command_switch switches[] =
   {
     { 'b', ignore, 0, 0, 0, 0, 0, 0, 0 },
     { 'B', flag, &always_make_set, 1, 1, 0, 0, 0, "always-make" },
-    { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" },
     { 'd', flag, &debug_flag, 1, 1, 0, 0, 0, 0 },
-    { CHAR_MAX+1, string, &db_flags, 1, 1, 0, "basic", 0, "debug" },
 #ifdef WINDOWS32
     { 'D', flag, &suspend_flag, 1, 1, 0, 0, 0, "suspend-for-debug" },
 #endif
     { 'e', flag, &env_overrides, 1, 1, 0, 0, 0, "environment-overrides", },
-    { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" },
     { 'h', flag, &print_usage_flag, 0, 0, 0, 0, 0, "help" },
     { 'i', flag, &ignore_errors_flag, 1, 1, 0, 0, 0, "ignore-errors" },
-    { 'I', filename, &include_directories, 1, 1, 0, 0, 0,
-      "include-dir" },
-    { 'j', positive_int, &job_slots, 1, 1, 0, &inf_jobs, &default_job_slots,
-      "jobs" },
-    { CHAR_MAX+2, string, &jobserver_fds, 1, 1, 0, 0, 0, "jobserver-fds" },
     { 'k', flag, &keep_going_flag, 1, 1, 0, 0, &default_keep_going_flag,
       "keep-going" },
-#ifndef NO_FLOAT
-    { 'l', floating, &max_load_average, 1, 1, 0, &default_load_average,
-      &default_load_average, "load-average" },
-#else
-    { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average,
-      &default_load_average, "load-average" },
-#endif
     { 'L', flag, &check_symlink_flag, 1, 1, 0, 0, 0, "check-symlink-times" },
     { 'm', ignore, 0, 0, 0, 0, 0, 0, 0 },
     { 'n', flag, &just_print_flag, 1, 1, 1, 0, 0, "just-print" },
-    { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" },
     { 'p', flag, &print_data_base_flag, 1, 1, 0, 0, 0, "print-data-base" },
     { 'q', flag, &question_flag, 1, 1, 1, 0, 0, "question" },
     { 'r', flag, &no_builtin_rules_flag, 1, 1, 0, 0, 0, "no-builtin-rules" },
@@ -415,15 +415,36 @@ static const struct command_switch switches[] =
       "no-keep-going" },
     { 't', flag, &touch_flag, 1, 1, 1, 0, 0, "touch" },
     { 'v', flag, &print_version_flag, 1, 1, 0, 0, 0, "version" },
-    { CHAR_MAX+3, string, &verbosity_flags, 1, 1, 0, 0, 0,
-      "verbosity" },
     { 'w', flag, &print_directory_flag, 1, 1, 0, 0, 0, "print-directory" },
+
+    /* These options take arguments.  */
+    { 'C', filename, &directories, 0, 0, 0, 0, 0, "directory" },
+    { 'f', filename, &makefiles, 0, 0, 0, 0, 0, "file" },
+    { 'I', filename, &include_directories, 1, 1, 0, 0, 0,
+      "include-dir" },
+    { 'j', positive_int, &job_slots, 1, 1, 0, &inf_jobs, &default_job_slots,
+      "jobs" },
+#ifndef NO_FLOAT
+    { 'l', floating, &max_load_average, 1, 1, 0, &default_load_average,
+      &default_load_average, "load-average" },
+#else
+    { 'l', positive_int, &max_load_average, 1, 1, 0, &default_load_average,
+      &default_load_average, "load-average" },
+#endif
+    { 'o', filename, &old_files, 0, 0, 0, 0, 0, "old-file" },
+    { 'O', string, &output_sync_option, 1, 1, 0, "target", 0, "output-sync" },
+    { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" },
+
+    /* These are long-style options.  */
+    { CHAR_MAX+1, string, &db_flags, 1, 1, 0, "basic", 0, "debug" },
+    { CHAR_MAX+2, string, &jobserver_fds, 1, 1, 0, 0, 0, "jobserver-fds" },
+    { CHAR_MAX+3, flag, &trace_flag, 1, 1, 0, 0, 0, "trace" },
     { CHAR_MAX+4, flag, &inhibit_print_directory_flag, 1, 1, 0, 0, 0,
       "no-print-directory" },
-    { 'W', filename, &new_files, 0, 0, 0, 0, 0, "what-if" },
     { CHAR_MAX+5, flag, &warn_undefined_variables_flag, 1, 1, 0, 0, 0,
       "warn-undefined-variables" },
     { CHAR_MAX+6, string, &eval_strings, 1, 0, 0, 0, 0, "eval" },
+    { CHAR_MAX+7, string, &sync_mutex, 1, 1, 0, 0, 0, "sync-mutex" },
     { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
   };
 
@@ -431,15 +452,15 @@ static const struct command_switch switches[] =
 
 static struct option long_option_aliases[] =
   {
-    { "quiet",         no_argument,            0, 's' },
-    { "stop",          no_argument,            0, 'S' },
-    { "new-file",      required_argument,      0, 'W' },
-    { "assume-new",    required_argument,      0, 'W' },
-    { "assume-old",    required_argument,      0, 'o' },
-    { "max-load",      optional_argument,      0, 'l' },
-    { "dry-run",       no_argument,            0, 'n' },
-    { "recon",         no_argument,            0, 'n' },
-    { "makefile",      required_argument,      0, 'f' },
+    { "quiet",          no_argument,            0, 's' },
+    { "stop",           no_argument,            0, 'S' },
+    { "new-file",       required_argument,      0, 'W' },
+    { "assume-new",     required_argument,      0, 'W' },
+    { "assume-old",     required_argument,      0, 'o' },
+    { "max-load",       optional_argument,      0, 'l' },
+    { "dry-run",        no_argument,            0, 'n' },
+    { "recon",          no_argument,            0, 'n' },
+    { "makefile",       required_argument,      0, 'f' },
   };
 
 /* List of goal targets.  */
@@ -486,7 +507,7 @@ struct variable * default_goal_var;
 
 struct file *default_file;
 
-/* Nonzero if we have seen the magic `.POSIX' target.
+/* Nonzero if we have seen the magic '.POSIX' target.
    This turns on pedantic compliance with POSIX.2.  */
 
 int posix_pedantic;
@@ -502,7 +523,17 @@ int second_expansion;
 
 int one_shell;
 
-/* Nonzero if we have seen the `.NOTPARALLEL' target.
+/* One of OUTPUT_SYNC_* if the "--output-sync" option was given.  This
+   attempts to synchronize the output of parallel jobs such that the results
+   of each job stay together.  */
+
+int output_sync = OUTPUT_SYNC_NONE;
+
+/* Nonzero if the "--trace" option was given.  */
+
+int trace_flag = 0;
+
+/* Nonzero if we have seen the '.NOTPARALLEL' target.
    This turns off parallel builds for this invocation of make.  */
 
 int not_parallel;
@@ -512,13 +543,25 @@ int not_parallel;
    warning at the end of the run. */
 
 int clock_skew_detected;
+
+/* Map of possible stop characters for searching strings.  */
+#ifndef UCHAR_MAX
+# define UCHAR_MAX 255
+#endif
+unsigned short stopchar_map[UCHAR_MAX + 1] = {0};
+
+/* If output-sync is enabled we'll collect all the output generated due to
+   options, while reading makefiles, etc.  */
+
+struct output make_sync;
+
 \f
 /* Mask of signals that are being caught with fatal_error_signal.  */
 
-#ifdef POSIX
+#ifdef  POSIX
 sigset_t fatal_signal_set;
 #else
-# ifdef        HAVE_SIGSETMASK
+# ifdef HAVE_SIGSETMASK
 int fatal_signal_mask;
 # endif
 #endif
@@ -554,6 +597,46 @@ initialize_global_hash_tables (void)
   hash_init_function_table ();
 }
 
+/* This character map locate stop chars when parsing GNU makefiles.
+   Each element is true if we should stop parsing on that character.  */
+
+static void
+initialize_stopchar_map ()
+{
+  int i;
+
+  stopchar_map[(int)'\0'] = MAP_NUL;
+  stopchar_map[(int)'#'] = MAP_COMMENT;
+  stopchar_map[(int)';'] = MAP_SEMI;
+  stopchar_map[(int)'='] = MAP_EQUALS;
+  stopchar_map[(int)':'] = MAP_COLON;
+  stopchar_map[(int)'%'] = MAP_PERCENT;
+  stopchar_map[(int)'|'] = MAP_PIPE;
+  stopchar_map[(int)'.'] = MAP_DOT | MAP_USERFUNC;
+  stopchar_map[(int)','] = MAP_COMMA;
+  stopchar_map[(int)'$'] = MAP_VARIABLE;
+
+  stopchar_map[(int)'-'] = MAP_USERFUNC;
+  stopchar_map[(int)'_'] = MAP_USERFUNC;
+
+  stopchar_map[(int)'/'] = MAP_PATHSEP;
+#if defined(VMS)
+  stopchar_map[(int)']'] = MAP_PATHSEP;
+#elif defined(HAVE_DOS_PATHS)
+  stopchar_map[(int)'\\'] = MAP_PATHSEP;
+#endif
+
+  for (i = 1; i <= UCHAR_MAX; ++i)
+    {
+      if (isblank(i))
+        stopchar_map[i] = MAP_BLANK;
+      if (isspace(i))
+        stopchar_map[i] |= MAP_SPACE;
+      if (isalnum(i))
+        stopchar_map[i] = MAP_USERFUNC;
+    }
+}
+
 static const char *
 expand_command_line_file (char *name)
 {
@@ -567,7 +650,7 @@ expand_command_line_file (char *name)
     {
       expanded = tilde_expand (name);
       if (expanded != 0)
-       name = expanded;
+        name = expanded;
     }
 
   /* This is also done in parse_file_seq, so this is redundant
@@ -577,16 +660,16 @@ expand_command_line_file (char *name)
     {
       name += 2;
       while (*name == '/')
-       /* Skip following slashes: ".//foo" is "foo", not "/foo".  */
-       ++name;
+        /* Skip following slashes: ".//foo" is "foo", not "/foo".  */
+        ++name;
     }
 
   if (*name == '\0')
     {
       /* It was all slashes!  Move back to the dot and truncate
-        it after the first slash, so it becomes just "./".  */
+         it after the first slash, so it becomes just "./".  */
       do
-       --name;
+        --name;
       while (name[0] != '.');
       name[2] = '\0';
     }
@@ -617,52 +700,127 @@ decode_debug_flags (void)
   if (debug_flag)
     db_level = DB_ALL;
 
-  if (!db_flags)
+  if (db_flags)
+    for (pp=db_flags->list; *pp; ++pp)
+      {
+        const char *p = *pp;
+
+        while (1)
+          {
+            switch (tolower (p[0]))
+              {
+              case 'a':
+                db_level |= DB_ALL;
+                break;
+              case 'b':
+                db_level |= DB_BASIC;
+                break;
+              case 'i':
+                db_level |= DB_BASIC | DB_IMPLICIT;
+                break;
+              case 'j':
+                db_level |= DB_JOBS;
+                break;
+              case 'm':
+                db_level |= DB_BASIC | DB_MAKEFILES;
+                break;
+              case 'n':
+                db_level = 0;
+                break;
+              case 'v':
+                db_level |= DB_BASIC | DB_VERBOSE;
+                break;
+              default:
+                fatal (NILF, _("unknown debug level specification '%s'"), p);
+              }
+
+            while (*(++p) != '\0')
+              if (*p == ',' || *p == ' ')
+                {
+                  ++p;
+                  break;
+                }
+
+            if (*p == '\0')
+              break;
+          }
+      }
+
+  if (db_level)
+    verify_flag = 1;
+
+  if (! db_level)
+    debug_flag = 0;
+}
+
+static void
+decode_output_sync_flags (void)
+{
+  const char **pp;
+
+  if (!output_sync_option)
     return;
 
-  for (pp=db_flags->list; *pp; ++pp)
+  for (pp=output_sync_option->list; *pp; ++pp)
     {
       const char *p = *pp;
 
-      while (1)
-        {
-          switch (tolower (p[0]))
-            {
-            case 'a':
-              db_level |= DB_ALL;
-              break;
-            case 'b':
-              db_level |= DB_BASIC;
-              break;
-            case 'i':
-              db_level |= DB_BASIC | DB_IMPLICIT;
-              break;
-            case 'j':
-              db_level |= DB_JOBS;
-              break;
-            case 'm':
-              db_level |= DB_BASIC | DB_MAKEFILES;
-              break;
-            case 'v':
-              db_level |= DB_BASIC | DB_VERBOSE;
-              break;
-            default:
-              fatal (NILF, _("unknown debug level specification `%s'"), p);
-            }
+      if (streq (p, "none"))
+        output_sync = OUTPUT_SYNC_NONE;
+      else if (streq (p, "line"))
+        output_sync = OUTPUT_SYNC_LINE;
+      else if (streq (p, "target"))
+        output_sync = OUTPUT_SYNC_TARGET;
+      else if (streq (p, "recurse"))
+        output_sync = OUTPUT_SYNC_RECURSE;
+      else
+        fatal (NILF, _("unknown output-sync type '%s'"), p);
+    }
 
-          while (*(++p) != '\0')
-            if (*p == ',' || *p == ' ')
-              break;
+  if (sync_mutex)
+    {
+      const char *mp;
+      unsigned int idx;
 
-          if (*p == '\0')
-            break;
+      for (idx = 1; idx < sync_mutex->idx; idx++)
+        if (!streq (sync_mutex->list[0], sync_mutex->list[idx]))
+          fatal (NILF, _("internal error: multiple --sync-mutex options"));
 
-          ++p;
-        }
+      /* Now parse the mutex handle string.  */
+      mp = sync_mutex->list[0];
+      RECORD_SYNC_MUTEX (mp);
     }
 }
 
 #ifdef WINDOWS32
+
+#ifndef NO_OUTPUT_SYNC
+
+/* This is called from start_job_command when it detects that
+   output_sync option is in effect.  The handle to the synchronization
+   mutex is passed, as a string, to sub-makes via the --sync-mutex
+   command-line argument.  */
+void
+prepare_mutex_handle_string (sync_handle_t handle)
+{
+  if (!sync_mutex)
+    {
+      /* 2 hex digits per byte + 2 characters for "0x" + null.  */
+      char hdl_string[2 * sizeof (sync_handle_t) + 2 + 1];
+
+      /* Prepare the mutex handle string for our children.  */
+      sprintf (hdl_string, "0x%x", handle);
+      sync_mutex = xmalloc (sizeof (struct stringlist));
+      sync_mutex->list = xmalloc (sizeof (char *));
+      sync_mutex->list[0] = xstrdup (hdl_string);
+      sync_mutex->idx = 1;
+      sync_mutex->max = 1;
+      define_makeflags (1, 0);
+    }
+}
+
+#endif  /* NO_OUTPUT_SYNC */
+
 /*
  * HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture
  * exception and print it to stderr instead.
@@ -673,11 +831,11 @@ decode_debug_flags (void)
  *   debuggers can attach.
  */
 LONG WINAPI
-handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo )
+handle_runtime_exceptions (struct _EXCEPTION_POINTERS *exinfo)
 {
   PEXCEPTION_RECORD exrec = exinfo->ExceptionRecord;
-  LPSTR cmdline = GetCommandLine();
-  LPSTR prg = strtok(cmdline, " ");
+  LPSTR cmdline = GetCommandLine ();
+  LPSTR prg = strtok (cmdline, " ");
   CHAR errmsg[1024];
 #ifdef USE_EVENT_LOG
   HANDLE hEventSource;
@@ -686,54 +844,54 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo )
 
   if (! ISDB (DB_VERBOSE))
     {
-      sprintf(errmsg,
-              _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"),
-              prg, exrec->ExceptionCode, exrec->ExceptionAddress);
-      fprintf(stderr, errmsg);
-      exit(255);
+      sprintf (errmsg,
+               _("%s: Interrupt/Exception caught (code = 0x%lx, addr = 0x%p)\n"),
+               prg, exrec->ExceptionCode, exrec->ExceptionAddress);
+      fprintf (stderr, errmsg);
+      exit (255);
     }
 
-  sprintf(errmsg,
-          _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"),
-          prg, exrec->ExceptionCode, exrec->ExceptionFlags,
-          exrec->ExceptionAddress);
+  sprintf (errmsg,
+           _("\nUnhandled exception filter called from program %s\nExceptionCode = %lx\nExceptionFlags = %lx\nExceptionAddress = 0x%p\n"),
+           prg, exrec->ExceptionCode, exrec->ExceptionFlags,
+           exrec->ExceptionAddress);
 
   if (exrec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
       && exrec->NumberParameters >= 2)
-    sprintf(&errmsg[strlen(errmsg)],
-            (exrec->ExceptionInformation[0]
-             ? _("Access violation: write operation at address 0x%p\n")
-             : _("Access violation: read operation at address 0x%p\n")),
-            (PVOID)exrec->ExceptionInformation[1]);
+    sprintf (&errmsg[strlen(errmsg)],
+             (exrec->ExceptionInformation[0]
+              ? _("Access violation: write operation at address 0x%p\n")
+              : _("Access violation: read operation at address 0x%p\n")),
+             (PVOID)exrec->ExceptionInformation[1]);
 
   /* turn this on if we want to put stuff in the event log too */
 #ifdef USE_EVENT_LOG
-  hEventSource = RegisterEventSource(NULL, "GNU Make");
+  hEventSource = RegisterEventSource (NULL, "GNU Make");
   lpszStrings[0] = errmsg;
 
   if (hEventSource != NULL)
     {
-      ReportEvent(hEventSource,         /* handle of event source */
-                  EVENTLOG_ERROR_TYPE,  /* event type */
-                  0,                    /* event category */
-                  0,                    /* event ID */
-                  NULL,                 /* current user's SID */
-                  1,                    /* strings in lpszStrings */
-                  0,                    /* no bytes of raw data */
-                  lpszStrings,          /* array of error strings */
-                  NULL);                /* no raw data */
-
-      (VOID) DeregisterEventSource(hEventSource);
+      ReportEvent (hEventSource,         /* handle of event source */
+                   EVENTLOG_ERROR_TYPE,  /* event type */
+                   0,                    /* event category */
+                   0,                    /* event ID */
+                   NULL,                 /* current user's SID */
+                   1,                    /* strings in lpszStrings */
+                   0,                    /* no bytes of raw data */
+                   lpszStrings,          /* array of error strings */
+                   NULL);                /* no raw data */
+
+      (VOID) DeregisterEventSource (hEventSource);
     }
 #endif
 
   /* Write the error to stderr too */
-  fprintf(stderr, errmsg);
+  fprintf (stderr, errmsg);
 
 #ifdef DEBUG
   return EXCEPTION_CONTINUE_SEARCH;
 #else
-  exit(255);
+  exit (255);
   return (255); /* not reached */
 #endif
 }
@@ -741,7 +899,7 @@ handle_runtime_exceptions( struct _EXCEPTION_POINTERS *exinfo )
 /*
  * On WIN32 systems we don't have the luxury of a /bin directory that
  * is mapped globally to every drive mounted to the system. Since make could
- * be invoked from any drive, and we don't want to propogate /bin/sh
+ * be invoked from any drive, and we don't want to propagate /bin/sh
  * to every single drive. Allow ourselves a chance to search for
  * a value for default shell here (if the default path does not exist).
  */
@@ -773,75 +931,92 @@ find_and_set_default_shell (const char *token)
       || ((tokend - 4 == search_token
            || (tokend - 4 > search_token
                && (tokend[-5] == '/' || tokend[-5] == '\\')))
-          && !strcasecmp (tokend - 4, "cmd.exe"))) {
-    batch_mode_shell = 1;
-    unixy_shell = 0;
-    sprintf (sh_path, "%s", search_token);
-    default_shell = xstrdup (w32ify (sh_path, 0));
-    DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"),
-                     default_shell));
-    sh_found = 1;
-  } else if (!no_default_sh_exe &&
-             (token == NULL || !strcmp (search_token, default_shell))) {
-    /* no new information, path already set or known */
-    sh_found = 1;
-  } else if (file_exists_p (search_token)) {
-    /* search token path was found */
-    sprintf (sh_path, "%s", search_token);
-    default_shell = xstrdup (w32ify (sh_path, 0));
-    DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"),
-                     default_shell));
-    sh_found = 1;
-  } else {
-    char *p;
-    struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH"));
-
-    /* Search Path for shell */
-    if (v && v->value) {
-      char *ep;
-
-      p  = v->value;
-      ep = strchr (p, PATH_SEPARATOR_CHAR);
-
-      while (ep && *ep) {
-        *ep = '\0';
-
-        if (dir_file_exists_p (p, search_token)) {
-          sprintf (sh_path, "%s/%s", p, search_token);
-          default_shell = xstrdup (w32ify (sh_path, 0));
-          sh_found = 1;
-          *ep = PATH_SEPARATOR_CHAR;
-
-          /* terminate loop */
-          p += strlen (p);
-        } else {
-          *ep = PATH_SEPARATOR_CHAR;
-           p = ++ep;
-        }
+          && !strcasecmp (tokend - 4, "cmd.exe")))
+    {
+      batch_mode_shell = 1;
+      unixy_shell = 0;
+      sprintf (sh_path, "%s", search_token);
+      default_shell = xstrdup (w32ify (sh_path, 0));
+      DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"),
+                       default_shell));
+      sh_found = 1;
+    }
+  else if (!no_default_sh_exe
+           && (token == NULL || !strcmp (search_token, default_shell)))
+    {
+      /* no new information, path already set or known */
+      sh_found = 1;
+    }
+  else if (_access (search_token, 0) == 0)
+    {
+      /* search token path was found */
+      sprintf (sh_path, "%s", search_token);
+      default_shell = xstrdup (w32ify (sh_path, 0));
+      DB (DB_VERBOSE, (_("find_and_set_shell() setting default_shell = %s\n"),
+                       default_shell));
+      sh_found = 1;
+    }
+  else
+    {
+      char *p;
+      struct variable *v = lookup_variable (STRING_SIZE_TUPLE ("PATH"));
 
-        ep = strchr (p, PATH_SEPARATOR_CHAR);
-      }
+      /* Search Path for shell */
+      if (v && v->value)
+        {
+          char *ep;
 
-      /* be sure to check last element of Path */
-      if (p && *p && dir_file_exists_p (p, search_token)) {
-          sprintf (sh_path, "%s/%s", p, search_token);
-          default_shell = xstrdup (w32ify (sh_path, 0));
-          sh_found = 1;
-      }
+          p  = v->value;
+          ep = strchr (p, PATH_SEPARATOR_CHAR);
+
+          while (ep && *ep)
+            {
+              *ep = '\0';
+
+              sprintf (sh_path, "%s/%s", p, search_token);
+              if (_access (sh_path, 0) == 0)
+                {
+                  default_shell = xstrdup (w32ify (sh_path, 0));
+                  sh_found = 1;
+                  *ep = PATH_SEPARATOR_CHAR;
+
+                  /* terminate loop */
+                  p += strlen (p);
+                }
+              else
+                {
+                  *ep = PATH_SEPARATOR_CHAR;
+                  p = ++ep;
+                }
+
+              ep = strchr (p, PATH_SEPARATOR_CHAR);
+            }
 
-      if (sh_found)
-        DB (DB_VERBOSE,
-            (_("find_and_set_shell() path search set default_shell = %s\n"),
-             default_shell));
+          /* be sure to check last element of Path */
+          if (p && *p)
+            {
+              sprintf (sh_path, "%s/%s", p, search_token);
+              if (_access (sh_path, 0) == 0)
+                {
+                  default_shell = xstrdup (w32ify (sh_path, 0));
+                  sh_found = 1;
+                }
+            }
+
+          if (sh_found)
+            DB (DB_VERBOSE,
+                (_("find_and_set_shell() path search set default_shell = %s\n"),
+                 default_shell));
+        }
     }
-  }
 
   /* naive test */
-  if (!unixy_shell && sh_found &&
-      (strstr (default_shell, "sh") || strstr (default_shell, "SH"))) {
-    unixy_shell = 1;
-    batch_mode_shell = 0;
-  }
+  if (!unixy_shell && sh_found
+      && (strstr (default_shell, "sh") || strstr (default_shell, "SH")))
+    {
+      unixy_shell = 1;
+      batch_mode_shell = 0;
+    }
 
 #ifdef BATCH_MODE_ONLY_SHELL
   batch_mode_shell = 1;
@@ -863,51 +1038,6 @@ msdos_return_to_initial_directory (void)
 }
 #endif  /* __MSDOS__ */
 
-char *mktemp (char *template);
-int mkstemp (char *template);
-
-FILE *
-open_tmpfile(char **name, const char *template)
-{
-#ifdef HAVE_FDOPEN
-  int fd;
-#endif
-
-#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
-# define TEMPLATE_LEN   strlen (template)
-#else
-# define TEMPLATE_LEN   L_tmpnam
-#endif
-  *name = xmalloc (TEMPLATE_LEN + 1);
-  strcpy (*name, template);
-
-#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
-  /* It's safest to use mkstemp(), if we can.  */
-  fd = mkstemp (*name);
-  if (fd == -1)
-    return 0;
-  return fdopen (fd, "w");
-#else
-# ifdef HAVE_MKTEMP
-  (void) mktemp (*name);
-# else
-  (void) tmpnam (*name);
-# endif
-
-# ifdef HAVE_FDOPEN
-  /* Can't use mkstemp(), but guard against a race condition.  */
-  fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600);
-  if (fd == -1)
-    return 0;
-  return fdopen (fd, "w");
-# else
-  /* Not secure, but what can we do?  */
-  return fopen (*name, "w");
-# endif
-#endif
-}
-
-
 #ifdef _AMIGA
 int
 main (int argc, char **argv)
@@ -918,20 +1048,25 @@ main (int argc, char **argv, char **envp)
 {
   static char *stdin_nm = 0;
   int makefile_status = MAKE_SUCCESS;
-  struct dep *read_makefiles;
+  struct dep *read_files;
   PATH_VAR (current_directory);
   unsigned int restarts = 0;
+  unsigned int syncing = 0;
 #ifdef WINDOWS32
   char *unix_path = NULL;
   char *windows32_path = NULL;
 
-  SetUnhandledExceptionFilter(handle_runtime_exceptions);
+  SetUnhandledExceptionFilter (handle_runtime_exceptions);
 
   /* start off assuming we have no shell */
   unixy_shell = 0;
   no_default_sh_exe = 1;
 #endif
 
+  output_init (&make_sync);
+
+  initialize_stopchar_map();
+
 #ifdef SET_STACK_SIZE
  /* Get rid of any avoidable limit on stack size.  */
   {
@@ -950,24 +1085,23 @@ main (int argc, char **argv, char **envp)
   }
 #endif
 
-#ifdef HAVE_ATEXIT
-  atexit (close_stdout);
-#endif
-
   /* Needed for OS/2 */
-  initialize_main(&argc, &argv);
+  initialize_main (&argc, &argv);
 
-  reading_file = 0;
+#ifdef MAKE_MAINTAINER_MODE
+  /* In maintainer mode we always enable verification.  */
+  verify_flag = 1;
+#endif
 
 #if defined (__MSDOS__) && !defined (_POSIX_SOURCE)
-  /* Request the most powerful version of `system', to
+  /* Request the most powerful version of 'system', to
      make up for the dumb default shell.  */
   __system_flags = (__system_redirect
-                   | __system_use_shell
-                   | __system_allow_multiple_cmds
-                   | __system_allow_long_cmds
-                   | __system_handle_null_commands
-                   | __system_emulate_chdir);
+                    | __system_use_shell
+                    | __system_allow_multiple_cmds
+                    | __system_allow_long_cmds
+                    | __system_handle_null_commands
+                    | __system_emulate_chdir);
 
 #endif
 
@@ -978,22 +1112,22 @@ main (int argc, char **argv, char **envp)
   (void)bindtextdomain (PACKAGE, LOCALEDIR);
   (void)textdomain (PACKAGE);
 
-#ifdef POSIX
+#ifdef  POSIX
   sigemptyset (&fatal_signal_set);
-#define        ADD_SIG(sig)    sigaddset (&fatal_signal_set, sig)
+#define ADD_SIG(sig)    sigaddset (&fatal_signal_set, sig)
 #else
-#ifdef HAVE_SIGSETMASK
+#ifdef  HAVE_SIGSETMASK
   fatal_signal_mask = 0;
-#define        ADD_SIG(sig)    fatal_signal_mask |= sigmask (sig)
+#define ADD_SIG(sig)    fatal_signal_mask |= sigmask (sig)
 #else
-#define        ADD_SIG(sig)    (void)sig      /* Needed to avoid warnings in MSVC.  */
+#define ADD_SIG(sig)    (void)sig
 #endif
 #endif
 
-#define        FATAL_SIG(sig)                                                        \
-  if (bsd_signal (sig, fatal_error_signal) == SIG_IGN)                       \
-    bsd_signal (sig, SIG_IGN);                                               \
-  else                                                                       \
+#define FATAL_SIG(sig)                                                        \
+  if (bsd_signal (sig, fatal_error_signal) == SIG_IGN)                        \
+    bsd_signal (sig, SIG_IGN);                                                \
+  else                                                                        \
     ADD_SIG (sig);
 
 #ifdef SIGHUP
@@ -1012,7 +1146,7 @@ main (int argc, char **argv, char **envp)
   FATAL_SIG (SIGFPE);
 #endif
 
-#ifdef SIGDANGER
+#ifdef  SIGDANGER
   FATAL_SIG (SIGDANGER);
 #endif
 #ifdef SIGXCPU
@@ -1022,7 +1156,7 @@ main (int argc, char **argv, char **envp)
   FATAL_SIG (SIGXFSZ);
 #endif
 
-#undef FATAL_SIG
+#undef  FATAL_SIG
 
   /* Do not ignore the child-death signal.  This must be done before
      any children could possibly be created; otherwise, the wait
@@ -1038,18 +1172,7 @@ main (int argc, char **argv, char **envp)
 # endif
 #endif
 
-  /* Make sure stdout is line-buffered.  */
-
-#ifdef HAVE_SETVBUF
-# ifdef SETVBUF_REVERSED
-  setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
-# else /* setvbuf not reversed.  */
-  /* Some buggy systems lose if we pass 0 instead of allocating ourselves.  */
-  setvbuf (stdout, 0, _IOLBF, BUFSIZ);
-# endif        /* setvbuf reversed.  */
-#elif HAVE_SETLINEBUF
-  setlinebuf (stdout);
-#endif /* setlinebuf missing.  */
+  output_init (NULL);
 
   /* Figure out where this program lives.  */
 
@@ -1066,27 +1189,26 @@ main (int argc, char **argv, char **envp)
 #endif
 #if defined(__MSDOS__) || defined(__EMX__)
       if (program == 0)
-       program = strrchr (argv[0], '\\');
+        program = strrchr (argv[0], '\\');
       else
-       {
-         /* Some weird environments might pass us argv[0] with
-            both kinds of slashes; we must find the rightmost.  */
-         char *p = strrchr (argv[0], '\\');
-         if (p && p > program)
-           program = p;
-       }
+        {
+          /* Some weird environments might pass us argv[0] with
+             both kinds of slashes; we must find the rightmost.  */
+          char *p = strrchr (argv[0], '\\');
+          if (p && p > program)
+            program = p;
+        }
       if (program == 0 && argv[0][1] == ':')
-       program = argv[0] + 1;
+        program = argv[0] + 1;
 #endif
 #ifdef WINDOWS32
       if (program == 0)
         {
           /* Extract program from full path */
-          int argv0_len;
           program = strrchr (argv[0], '\\');
           if (program)
             {
-              argv0_len = strlen(program);
+              int argv0_len = strlen (program);
               if (argv0_len > 4 && streq (&program[argv0_len - 4], ".exe"))
                 /* Remove .exe extension */
                 program[argv0_len - 4] = '\0';
@@ -1094,9 +1216,9 @@ main (int argc, char **argv, char **envp)
         }
 #endif
       if (program == 0)
-       program = argv[0];
+        program = argv[0];
       else
-       ++program;
+        ++program;
     }
 
   /* Set up to access user data (files).  */
@@ -1112,7 +1234,7 @@ main (int argc, char **argv, char **envp)
   if (getcwd (current_directory, GET_PATH_MAX) == 0)
 #endif
     {
-#ifdef HAVE_GETCWD
+#ifdef  HAVE_GETCWD
       perror_with_name ("getcwd", "");
 #else
       error (NILF, "getwd: %s", current_directory);
@@ -1122,6 +1244,7 @@ main (int argc, char **argv, char **envp)
     }
   else
     directory_before_chdir = xstrdup (current_directory);
+
 #ifdef  __MSDOS__
   /* Make sure we will return to the initial directory, come what may.  */
   atexit (msdos_return_to_initial_directory);
@@ -1134,25 +1257,39 @@ main (int argc, char **argv, char **envp)
   define_variable_cname (".SHELLFLAGS", "-c", o_default, 0);
 
   /* Set up .FEATURES
-     We must do this in multiple calls because define_variable_cname() is
-     a macro and some compilers (MSVC) don't like conditionals in macros.  */
+     Use a separate variable because define_variable_cname() is a macro and
+     some compilers (MSVC) don't like conditionals in macros.  */
   {
     const char *features = "target-specific order-only second-expansion"
-                           " else-if shortest-stem undefine"
+                           " else-if shortest-stem undefine oneshell"
 #ifndef NO_ARCHIVES
                            " archives"
 #endif
 #ifdef MAKE_JOBSERVER
                            " jobserver"
 #endif
+#ifndef NO_OUTPUT_SYNC
+                           " output-sync"
+#endif
 #ifdef MAKE_SYMLINKS
                            " check-symlink"
 #endif
+#ifdef HAVE_GUILE
+                           " guile"
+#endif
+#ifdef MAKE_LOAD
+                           " load"
+#endif
                            ;
 
     define_variable_cname (".FEATURES", features, o_default, 0);
   }
 
+#ifdef HAVE_GUILE
+  /* Configure GNU Guile support */
+  guile_gmake_setup (NILF);
+#endif
+
   /* Read in variables from the environment.  It is important that this be
      done before $(MAKE) is figured out so its definitions will not be
      from the environment.  */
@@ -1163,62 +1300,67 @@ main (int argc, char **argv, char **envp)
 
     for (i = 0; envp[i] != 0; ++i)
       {
-        int do_not_define = 0;
+        struct variable *v;
         char *ep = envp[i];
+        /* By default, export all variables culled from the environment.  */
+        enum variable_export export = v_export;
+        unsigned int len;
 
-        while (*ep != '\0' && *ep != '=')
+        while (! STOP_SET (*ep, MAP_EQUALS))
           ++ep;
+
+        /* If there's no equals sign it's a malformed environment.  Ignore.  */
+        if (*ep == '\0')
+          continue;
+
 #ifdef WINDOWS32
-        if (!unix_path && strneq(envp[i], "PATH=", 5))
+        if (!unix_path && strneq (envp[i], "PATH=", 5))
           unix_path = ep+1;
-        else if (!strnicmp(envp[i], "Path=", 5)) {
-          do_not_define = 1; /* it gets defined after loop exits */
-          if (!windows32_path)
-            windows32_path = ep+1;
-        }
-#endif
-        /* The result of pointer arithmetic is cast to unsigned int for
-           machines where ptrdiff_t is a different size that doesn't widen
-           the same.  */
-        if (!do_not_define)
+        else if (!strnicmp (envp[i], "Path=", 5))
           {
-            struct variable *v;
-
-            v = define_variable (envp[i], (unsigned int) (ep - envp[i]),
-                                 ep + 1, o_env, 1);
-            /* Force exportation of every variable culled from the
-               environment.  We used to rely on target_environment's
-               v_default code to do this.  But that does not work for the
-               case where an environment variable is redefined in a makefile
-               with `override'; it should then still be exported, because it
-               was originally in the environment.  */
-            v->export = v_export;
-
-            /* Another wrinkle is that POSIX says the value of SHELL set in
-               the makefile won't change the value of SHELL given to
-               subprocesses.  */
-            if (streq (v->name, "SHELL"))
-              {
-#ifndef __MSDOS__
-                v->export = v_noexport;
+            if (!windows32_path)
+              windows32_path = ep+1;
+            /* PATH gets defined after the loop exits.  */
+            continue;
+          }
 #endif
-                shell_var.name = "SHELL";
-                shell_var.length = 5;
-                shell_var.value = xstrdup (ep + 1);
-              }
 
-            /* If MAKE_RESTARTS is set, remember it but don't export it.  */
-            if (streq (v->name, "MAKE_RESTARTS"))
+        /* Length of the variable name, and skip the '='.  */
+        len = ep++ - envp[i];
+
+        /* If this is MAKE_RESTARTS, check to see if the "already printed
+           the enter statement" flag is set.  */
+        if (len == 13 && strneq (envp[i], "MAKE_RESTARTS", 13))
+          {
+            if (*ep == '-')
               {
-                v->export = v_noexport;
-                restarts = (unsigned int) atoi (ep + 1);
+                OUTPUT_TRACED ();
+                ++ep;
               }
+            restarts = (unsigned int) atoi (ep);
+            export = v_noexport;
+          }
+
+        v = define_variable (envp[i], len, ep, o_env, 1);
+
+        /* POSIX says the value of SHELL set in the makefile won't change the
+           value of SHELL given to subprocesses.  */
+        if (streq (v->name, "SHELL"))
+          {
+#ifndef __MSDOS__
+            export = v_noexport;
+#endif
+            shell_var.name = "SHELL";
+            shell_var.length = 5;
+            shell_var.value = xstrdup (ep);
           }
+
+        v->export = export;
       }
   }
 #ifdef WINDOWS32
     /* If we didn't find a correctly spelled PATH we define PATH as
-     * either the first mispelled value or an empty string
+     * either the first misspelled value or an empty string
      */
     if (!unix_path)
       define_variable_cname ("PATH", windows32_path ? windows32_path : "",
@@ -1226,38 +1368,50 @@ main (int argc, char **argv, char **envp)
 #endif
 #else /* For Amiga, read the ENV: device, ignoring all dirs */
     {
-       BPTR env, file, old;
-       char buffer[1024];
-       int len;
-       __aligned struct FileInfoBlock fib;
-
-       env = Lock ("ENV:", ACCESS_READ);
-       if (env)
-       {
-           old = CurrentDir (DupLock(env));
-           Examine (env, &fib);
-
-           while (ExNext (env, &fib))
-           {
-               if (fib.fib_DirEntryType < 0) /* File */
-               {
-                   /* Define an empty variable. It will be filled in
-                       variable_lookup(). Makes startup quite a bit
-                       faster. */
-                       define_variable (fib.fib_FileName,
-                           strlen (fib.fib_FileName),
-                       "", o_env, 1)->export = v_export;
-               }
-           }
-           UnLock (env);
-           UnLock(CurrentDir(old));
-       }
+        BPTR env, file, old;
+        char buffer[1024];
+        int len;
+        __aligned struct FileInfoBlock fib;
+
+        env = Lock ("ENV:", ACCESS_READ);
+        if (env)
+          {
+            old = CurrentDir (DupLock (env));
+            Examine (env, &fib);
+
+            while (ExNext (env, &fib))
+              {
+                if (fib.fib_DirEntryType < 0) /* File */
+                  {
+                    /* Define an empty variable. It will be filled in
+                       variable_lookup(). Makes startup quite a bit faster. */
+                    define_variable (fib.fib_FileName,
+                                     strlen (fib.fib_FileName),
+                                     "", o_env, 1)->export = v_export;
+                  }
+              }
+            UnLock (env);
+            UnLock (CurrentDir (old));
+          }
     }
 #endif
 
   /* Decode the switches.  */
 
+  decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS"));
+
+  /* Clear GNUMAKEFLAGS to avoid duplication.  */
+  define_variable_cname ("GNUMAKEFLAGS", "", o_env, 0);
+
   decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
+
+  /* In output sync mode we need to sync any output generated by reading the
+     makefiles, such as in $(info ...) or stderr from $(shell ...) etc.  */
+
+  syncing = make_sync.syncout = (output_sync == OUTPUT_SYNC_LINE
+                                 || output_sync == OUTPUT_SYNC_TARGET);
+  OUTPUT_SET (&make_sync);
+
 #if 0
   /* People write things like:
         MFLAGS="CC=gcc -pipe" "CFLAGS=-g"
@@ -1267,30 +1421,48 @@ main (int argc, char **argv, char **envp)
 
   decode_switches (argc, argv, 0);
 
-#ifdef WINDOWS32
-  if (suspend_flag) {
-        fprintf(stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId());
-        fprintf(stderr, _("%s is suspending for 30 seconds..."), argv[0]);
-        Sleep(30 * 1000);
-        fprintf(stderr, _("done sleep(30). Continuing.\n"));
+  /* Reset in case the switches changed our minds.  */
+  syncing = (output_sync == OUTPUT_SYNC_LINE
+             || output_sync == OUTPUT_SYNC_TARGET);
+
+  if (make_sync.syncout && ! syncing)
+    output_close (&make_sync);
+
+  make_sync.syncout = syncing;
+  OUTPUT_SET (&make_sync);
+
+  /* Figure out the level of recursion.  */
+  {
+    struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
+    if (v && v->value[0] != '\0' && v->value[0] != '-')
+      makelevel = (unsigned int) atoi (v->value);
+    else
+      makelevel = 0;
   }
-#endif
 
-  decode_debug_flags ();
+#ifdef WINDOWS32
+  if (suspend_flag)
+    {
+      fprintf (stderr, "%s (pid = %ld)\n", argv[0], GetCurrentProcessId ());
+      fprintf (stderr, _("%s is suspending for 30 seconds..."), argv[0]);
+      Sleep (30 * 1000);
+      fprintf (stderr, _("done sleep(30). Continuing.\n"));
+    }
+#endif
 
   /* Set always_make_flag if -B was given and we've not restarted already.  */
   always_make_flag = always_make_set && (restarts == 0);
 
-  /* Print version information.  */
-  if (print_version_flag || print_data_base_flag || db_level)
+  /* Print version information, and exit.  */
+  if (print_version_flag)
     {
       print_version ();
-
-      /* `make --version' is supposed to just print the version and exit.  */
-      if (print_version_flag)
-        die (0);
+      die (0);
     }
 
+  if (ISDB (DB_BASIC))
+    print_version ();
+
 #ifndef VMS
   /* Set the "MAKE_COMMAND" variable to the name we were invoked with.
      (If it is a relative pathname with a slash, prepend our directory name
@@ -1304,10 +1476,9 @@ main (int argc, char **argv, char **envp)
    * matter if the path is one way or the other for
    * CreateProcess().
    */
-  if (strpbrk(argv[0], "/:\\") ||
-      strstr(argv[0], "..") ||
-      strneq(argv[0], "//", 2))
-    argv[0] = xstrdup(w32ify(argv[0],1));
+  if (strpbrk (argv[0], "/:\\") || strstr (argv[0], "..")
+      || strneq (argv[0], "//", 2))
+    argv[0] = xstrdup (w32ify (argv[0], 1));
 #else /* WINDOWS32 */
 #if defined (__MSDOS__) || defined (__EMX__)
   if (strchr (argv[0], '\\'))
@@ -1316,8 +1487,8 @@ main (int argc, char **argv, char **envp)
 
       argv[0] = xstrdup (argv[0]);
       for (p = argv[0]; *p; p++)
-       if (*p == '\\')
-         *p = '/';
+        if (*p == '\\')
+          *p = '/';
     }
   /* If argv[0] is not in absolute form, prepend the current
      directory.  This can happen when Make is invoked by another DJGPP
@@ -1344,58 +1515,150 @@ main (int argc, char **argv, char **envp)
 #endif /* WINDOWS32 */
 #endif
 
-  /* The extra indirection through $(MAKE_COMMAND) is done
-     for hysterical raisins.  */
-  define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0);
-  define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1);
+  /* We may move, but until we do, here we are.  */
+  starting_directory = current_directory;
 
-  if (command_variables != 0)
-    {
-      struct command_variable *cv;
-      struct variable *v;
-      unsigned int len = 0;
-      char *value, *p;
+#ifdef MAKE_JOBSERVER
+  /* If the jobserver-fds option is seen, make sure that -j is reasonable.
+     This can't be usefully set in the makefile, and we want to verify the
+     FDs are valid before any other aspect of make has a chance to start
+     using them for something else.  */
 
-      /* Figure out how much space will be taken up by the command-line
-        variable definitions.  */
-      for (cv = command_variables; cv != 0; cv = cv->next)
-       {
-         v = cv->variable;
-         len += 2 * strlen (v->name);
-         if (! v->recursive)
-           ++len;
-         ++len;
-         len += 2 * strlen (v->value);
-         ++len;
-       }
+  if (jobserver_fds)
+    {
+      const char *cp;
+      unsigned int ui;
 
-      /* Now allocate a buffer big enough and fill it.  */
-      p = value = alloca (len);
-      for (cv = command_variables; cv != 0; cv = cv->next)
-       {
-         v = cv->variable;
-         p = quote_for_env (p, v->name);
-         if (! v->recursive)
-           *p++ = ':';
-         *p++ = '=';
-         p = quote_for_env (p, v->value);
-         *p++ = ' ';
-       }
-      p[-1] = '\0';            /* Kill the final space and terminate.  */
+      for (ui=1; ui < jobserver_fds->idx; ++ui)
+        if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
+          fatal (NILF, _("internal error: multiple --jobserver-fds options"));
 
-      /* Define an unchangeable variable with a name that no POSIX.2
-        makefile could validly use for its own variable.  */
-      define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0);
+      /* Now parse the fds string and make sure it has the proper format.  */
 
-      /* Define the variable; this will not override any user definition.
-         Normally a reference to this variable is written into the value of
-         MAKEFLAGS, allowing the user to override this value to affect the
-         exported value of MAKEFLAGS.  In POSIX-pedantic mode, we cannot
-         allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so
-         a reference to this hidden variable is written instead. */
-      define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}",
-                             o_env, 1);
-    }
+      cp = jobserver_fds->list[0];
+
+#ifdef WINDOWS32
+      if (! open_jobserver_semaphore (cp))
+        {
+          DWORD err = GetLastError ();
+          fatal (NILF, _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
+                 cp, err, map_windows32_error_to_string (err));
+        }
+      DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), cp));
+#else
+      if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
+        fatal (NILF,
+               _("internal error: invalid --jobserver-fds string '%s'"), cp);
+
+      DB (DB_JOBS,
+          (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
+#endif
+
+      /* The combination of a pipe + !job_slots means we're using the
+         jobserver.  If !job_slots and we don't have a pipe, we can start
+         infinite jobs.  If we see both a pipe and job_slots >0 that means the
+         user set -j explicitly.  This is broken; in this case obey the user
+         (ignore the jobserver pipe for this make) but print a message.
+         If we've restarted, we already printed this the first time.  */
+
+      if (job_slots > 0)
+        {
+          if (! restarts)
+            error (NILF, _("warning: -jN forced in submake: disabling jobserver mode."));
+        }
+#ifndef WINDOWS32
+#ifdef HAVE_FCNTL
+# define FD_OK(_f) ((fcntl ((_f), F_GETFD) != -1) || (errno != EBADF))
+#else
+# define FD_OK(_f) 1
+#endif
+      /* Create a duplicate pipe, that will be closed in the SIGCHLD
+         handler.  If this fails with EBADF, the parent has closed the pipe
+         on us because it didn't think we were a submake.  If so, print a
+         warning then default to -j1.  */
+      else if (!FD_OK (job_fds[0]) || !FD_OK (job_fds[1])
+               || (job_rfd = dup (job_fds[0])) < 0)
+        {
+          if (errno != EBADF)
+            pfatal_with_name (_("dup jobserver"));
+
+          error (NILF,
+                 _("warning: jobserver unavailable: using -j1.  Add '+' to parent make rule."));
+          job_slots = 1;
+          job_fds[0] = job_fds[1] = -1;
+        }
+#endif
+
+      if (job_slots > 0)
+        {
+#ifdef WINDOWS32
+          free_jobserver_semaphore ();
+#else
+          if (job_fds[0] >= 0)
+            close (job_fds[0]);
+          if (job_fds[1] >= 0)
+            close (job_fds[1]);
+#endif
+          job_fds[0] = job_fds[1] = -1;
+          free (jobserver_fds->list);
+          free (jobserver_fds);
+          jobserver_fds = 0;
+        }
+    }
+#endif
+
+  /* The extra indirection through $(MAKE_COMMAND) is done
+     for hysterical raisins.  */
+  define_variable_cname ("MAKE_COMMAND", argv[0], o_default, 0);
+  define_variable_cname ("MAKE", "$(MAKE_COMMAND)", o_default, 1);
+
+  if (command_variables != 0)
+    {
+      struct command_variable *cv;
+      struct variable *v;
+      unsigned int len = 0;
+      char *value, *p;
+
+      /* Figure out how much space will be taken up by the command-line
+         variable definitions.  */
+      for (cv = command_variables; cv != 0; cv = cv->next)
+        {
+          v = cv->variable;
+          len += 2 * strlen (v->name);
+          if (! v->recursive)
+            ++len;
+          ++len;
+          len += 2 * strlen (v->value);
+          ++len;
+        }
+
+      /* Now allocate a buffer big enough and fill it.  */
+      p = value = alloca (len);
+      for (cv = command_variables; cv != 0; cv = cv->next)
+        {
+          v = cv->variable;
+          p = quote_for_env (p, v->name);
+          if (! v->recursive)
+            *p++ = ':';
+          *p++ = '=';
+          p = quote_for_env (p, v->value);
+          *p++ = ' ';
+        }
+      p[-1] = '\0';             /* Kill the final space and terminate.  */
+
+      /* Define an unchangeable variable with a name that no POSIX.2
+         makefile could validly use for its own variable.  */
+      define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0);
+
+      /* Define the variable; this will not override any user definition.
+         Normally a reference to this variable is written into the value of
+         MAKEFLAGS, allowing the user to override this value to affect the
+         exported value of MAKEFLAGS.  In POSIX-pedantic mode, we cannot
+         allow the user's setting of MAKEOVERRIDES to affect MAKEFLAGS, so
+         a reference to this hidden variable is written instead. */
+      define_variable_cname ("MAKEOVERRIDES", "${-*-command-variables-*-}",
+                             o_env, 1);
+    }
 
   /* If there were -C flags, move ourselves about.  */
   if (directories != 0)
@@ -1429,17 +1692,8 @@ main (int argc, char **argv, char **envp)
    * lookups to fail because the current directory (.) was pointing
    * at the wrong place when it was first evaluated.
    */
-   no_default_sh_exe = !find_and_set_default_shell(NULL);
-
+   no_default_sh_exe = !find_and_set_default_shell (NULL);
 #endif /* WINDOWS32 */
-  /* Figure out the level of recursion.  */
-  {
-    struct variable *v = lookup_variable (STRING_SIZE_TUPLE (MAKELEVEL_NAME));
-    if (v != 0 && v->value[0] != '\0' && v->value[0] != '-')
-      makelevel = (unsigned int) atoi (v->value);
-    else
-      makelevel = 0;
-  }
 
   /* Except under -s, always do -w in sub-makes and under -C.  */
   if (!silent_flag && (directories != 0 || makelevel > 0))
@@ -1458,27 +1712,24 @@ main (int argc, char **argv, char **envp)
   construct_include_path (include_directories == 0
                           ? 0 : include_directories->list);
 
-  /* Figure out where we are now, after chdir'ing.  */
-  if (directories == 0)
-    /* We didn't move, so we're still in the same place.  */
-    starting_directory = current_directory;
-  else
+  /* If we chdir'ed, figure out where we are now.  */
+  if (directories)
     {
 #ifdef WINDOWS32
       if (getcwd_fs (current_directory, GET_PATH_MAX) == 0)
 #else
       if (getcwd (current_directory, GET_PATH_MAX) == 0)
 #endif
-       {
-#ifdef HAVE_GETCWD
-         perror_with_name ("getcwd", "");
+        {
+#ifdef  HAVE_GETCWD
+          perror_with_name ("getcwd", "");
 #else
-         error (NILF, "getwd: %s", current_directory);
+          error (NILF, "getwd: %s", current_directory);
 #endif
-         starting_directory = 0;
-       }
+          starting_directory = 0;
+        }
       else
-       starting_directory = current_directory;
+        starting_directory = current_directory;
     }
 
   define_variable_cname ("CURDIR", current_directory, o_file, 0);
@@ -1489,12 +1740,12 @@ main (int argc, char **argv, char **envp)
     {
       unsigned int i;
       for (i = 0; i < makefiles->idx; ++i)
-       if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\0')
-         {
-           /* This makefile is standard input.  Since we may re-exec
-              and thus re-read the makefiles, we read standard input
-              into a temporary file and read from that.  */
-           FILE *outfile;
+        if (makefiles->list[i][0] == '-' && makefiles->list[i][1] == '\0')
+          {
+            /* This makefile is standard input.  Since we may re-exec
+               and thus re-read the makefiles, we read standard input
+               into a temporary file and read from that.  */
+            FILE *outfile;
             char *template, *tmpdir;
 
             if (stdin_nm)
@@ -1511,63 +1762,63 @@ main (int argc, char **argv, char **envp)
 #endif
 #define DEFAULT_TMPFILE     "GmXXXXXX"
 
-           if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0')
+            if (((tmpdir = getenv ("TMPDIR")) == NULL || *tmpdir == '\0')
 #if defined (__MSDOS__) || defined (WINDOWS32) || defined (__EMX__)
                 /* These are also used commonly on these platforms.  */
                 && ((tmpdir = getenv ("TEMP")) == NULL || *tmpdir == '\0')
                 && ((tmpdir = getenv ("TMP")) == NULL || *tmpdir == '\0')
 #endif
                )
-             tmpdir = DEFAULT_TMPDIR;
+              tmpdir = DEFAULT_TMPDIR;
 
-            template = alloca (strlen (tmpdir) + sizeof (DEFAULT_TMPFILE) + 1);
-           strcpy (template, tmpdir);
+            template = alloca (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2);
+            strcpy (template, tmpdir);
 
 #ifdef HAVE_DOS_PATHS
-           if (strchr ("/\\", template[strlen (template) - 1]) == NULL)
-             strcat (template, "/");
+            if (strchr ("/\\", template[strlen (template) - 1]) == NULL)
+              strcat (template, "/");
 #else
 # ifndef VMS
-           if (template[strlen (template) - 1] != '/')
-             strcat (template, "/");
+            if (template[strlen (template) - 1] != '/')
+              strcat (template, "/");
 # endif /* !VMS */
 #endif /* !HAVE_DOS_PATHS */
 
-           strcat (template, DEFAULT_TMPFILE);
-           outfile = open_tmpfile (&stdin_nm, template);
-           if (outfile == 0)
-             pfatal_with_name (_("fopen (temporary file)"));
-           while (!feof (stdin) && ! ferror (stdin))
-             {
-               char buf[2048];
-               unsigned int n = fread (buf, 1, sizeof (buf), stdin);
-               if (n > 0 && fwrite (buf, 1, n, outfile) != n)
-                 pfatal_with_name (_("fwrite (temporary file)"));
-             }
-           fclose (outfile);
-
-           /* Replace the name that read_all_makefiles will
-              see with the name of the temporary file.  */
+            strcat (template, DEFAULT_TMPFILE);
+            outfile = output_tmpfile (&stdin_nm, template);
+            if (outfile == 0)
+              pfatal_with_name (_("fopen (temporary file)"));
+            while (!feof (stdin) && ! ferror (stdin))
+              {
+                char buf[2048];
+                unsigned int n = fread (buf, 1, sizeof (buf), stdin);
+                if (n > 0 && fwrite (buf, 1, n, outfile) != n)
+                  pfatal_with_name (_("fwrite (temporary file)"));
+              }
+            fclose (outfile);
+
+            /* Replace the name that read_all_makefiles will
+               see with the name of the temporary file.  */
             makefiles->list[i] = strcache_add (stdin_nm);
 
-           /* Make sure the temporary file will not be remade.  */
+            /* Make sure the temporary file will not be remade.  */
             {
               struct file *f = enter_file (strcache_add (stdin_nm));
               f->updated = 1;
-              f->update_status = 0;
+              f->update_status = us_success;
               f->command_state = cs_finished;
               /* Can't be intermediate, or it'll be removed too early for
                  make re-exec.  */
               f->intermediate = 0;
               f->dontcare = 0;
             }
-         }
+          }
     }
 
 #ifndef __EMX__ /* Don't use a SIGCHLD handler for OS/2 */
 #if defined(MAKE_JOBSERVER) || !defined(HAVE_WAIT_NOHANG)
   /* Set up to handle children dying.  This must be done before
-     reading in the makefiles so that `shell' function calls will work.
+     reading in the makefiles so that 'shell' function calls will work.
 
      If we don't have a hanging wait we have to fall back to old, broken
      functionality here and rely on the signal handler and counting
@@ -1596,7 +1847,6 @@ main (int argc, char **argv, char **envp)
 #endif
 
   /* Define the initial list of suffixes for old-style rules.  */
-
   set_default_suffixes ();
 
   /* Define the file rules for the built-in suffix rules.  These will later
@@ -1604,17 +1854,14 @@ main (int argc, char **argv, char **envp)
      install_default_implicit_rules, but since that happens after reading
      makefiles, it results in the built-in pattern rules taking precedence
      over makefile-specified suffix rules, which is wrong.  */
-
   install_default_suffix_rules ();
 
   /* Define some internal and special variables.  */
-
   define_automatic_variables ();
 
-  /* Set up the MAKEFLAGS and MFLAGS variables
-     so makefiles can look at them.  */
-
-  define_makeflags (0, 0);
+  /* Set up the MAKEFLAGS and MFLAGS variables for makefiles to see.
+     Initialize it to be exported but allow the makefile to reset it.  */
+  define_makeflags (0, 0)->export = v_export;
 
   /* Define the default variables.  */
   define_default_variables ();
@@ -1630,13 +1877,13 @@ main (int argc, char **argv, char **envp)
     {
       char *p, *value;
       unsigned int i;
-      unsigned int len = sizeof ("--eval=") * eval_strings->idx;
+      unsigned int len = (CSTRLEN ("--eval=") + 1) * eval_strings->idx;
 
       for (i = 0; i < eval_strings->idx; ++i)
         {
           p = xstrdup (eval_strings->list[i]);
           len += 2 * strlen (p);
-          eval_buffer (p);
+          eval_buffer (p, NULL);
           free (p);
         }
 
@@ -1644,7 +1891,7 @@ main (int argc, char **argv, char **envp)
       for (i = 0; i < eval_strings->idx; ++i)
         {
           strcpy (p, "--eval=");
-          p += strlen (p);
+          p += CSTRLEN ("--eval=");
           p = quote_for_env (p, eval_strings->list[i]);
           *(p++) = ' ';
         }
@@ -1655,13 +1902,12 @@ main (int argc, char **argv, char **envp)
 
   /* Read all the makefiles.  */
 
-  read_makefiles
-    = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list);
+  read_files = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list);
 
 #ifdef WINDOWS32
   /* look one last time after reading all Makefiles */
   if (no_default_sh_exe)
-    no_default_sh_exe = !find_and_set_default_shell(NULL);
+    no_default_sh_exe = !find_and_set_default_shell (NULL);
 #endif /* WINDOWS32 */
 
 #if defined (__MSDOS__) || defined (__EMX__)
@@ -1674,24 +1920,59 @@ main (int argc, char **argv, char **envp)
 
     if (shv && *shv->value)
       {
-       char *shell_path = recursively_expand(shv);
-
-       if (shell_path && _is_unixy_shell (shell_path))
-         unixy_shell = 1;
-       else
-         unixy_shell = 0;
-       if (shell_path)
-         default_shell = shell_path;
+        char *shell_path = recursively_expand (shv);
+
+        if (shell_path && _is_unixy_shell (shell_path))
+          unixy_shell = 1;
+        else
+          unixy_shell = 0;
+        if (shell_path)
+          default_shell = shell_path;
       }
   }
 #endif /* __MSDOS__ || __EMX__ */
 
-  /* Decode switches again, in case the variables were set by the makefile.  */
-  decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
+  {
+    int old_builtin_rules_flag = no_builtin_rules_flag;
+    int old_builtin_variables_flag = no_builtin_variables_flag;
+
+    /* Decode switches again, for variables set by the makefile.  */
+    decode_env_switches (STRING_SIZE_TUPLE ("GNUMAKEFLAGS"));
+
+    /* Clear GNUMAKEFLAGS to avoid duplication.  */
+    define_variable_cname ("GNUMAKEFLAGS", "", o_override, 0);
+
+    decode_env_switches (STRING_SIZE_TUPLE ("MAKEFLAGS"));
 #if 0
-  decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
+    decode_env_switches (STRING_SIZE_TUPLE ("MFLAGS"));
 #endif
 
+    /* Reset in case the switches changed our mind.  */
+    syncing = (output_sync == OUTPUT_SYNC_LINE
+               || output_sync == OUTPUT_SYNC_TARGET);
+
+    if (make_sync.syncout && ! syncing)
+      output_close (&make_sync);
+
+    make_sync.syncout = syncing;
+    OUTPUT_SET (&make_sync);
+
+    /* If we've disabled builtin rules, get rid of them.  */
+    if (no_builtin_rules_flag && ! old_builtin_rules_flag)
+      {
+        if (suffix_file->builtin)
+          {
+            free_dep_chain (suffix_file->deps);
+            suffix_file->deps = 0;
+          }
+        define_variable_cname ("SUFFIXES", "", o_default, 0);
+      }
+
+    /* If we've disabled builtin variables, get rid of them.  */
+    if (no_builtin_variables_flag && ! old_builtin_variables_flag)
+      undefine_default_variables ();
+  }
+
 #if defined (__MSDOS__) || defined (__EMX__)
   if (job_slots != 1
 # ifdef __EMX__
@@ -1707,74 +1988,36 @@ main (int argc, char **argv, char **envp)
 #endif
 
 #ifdef MAKE_JOBSERVER
-  /* If the jobserver-fds option is seen, make sure that -j is reasonable.  */
+  /* If we have >1 slot but no jobserver-fds, then we're a top-level make.
+     Set up the pipe and install the fds option for our children.  */
 
-  if (jobserver_fds)
+  if (job_slots > 1)
     {
-      const char *cp;
-      unsigned int ui;
-
-      for (ui=1; ui < jobserver_fds->idx; ++ui)
-        if (!streq (jobserver_fds->list[0], jobserver_fds->list[ui]))
-          fatal (NILF, _("internal error: multiple --jobserver-fds options"));
-
-      /* Now parse the fds string and make sure it has the proper format.  */
-
-      cp = jobserver_fds->list[0];
-
-      if (sscanf (cp, "%d,%d", &job_fds[0], &job_fds[1]) != 2)
-        fatal (NILF,
-               _("internal error: invalid --jobserver-fds string `%s'"), cp);
-
-      DB (DB_JOBS,
-          (_("Jobserver client (fds %d,%d)\n"), job_fds[0], job_fds[1]));
-
-      /* The combination of a pipe + !job_slots means we're using the
-         jobserver.  If !job_slots and we don't have a pipe, we can start
-         infinite jobs.  If we see both a pipe and job_slots >0 that means the
-         user set -j explicitly.  This is broken; in this case obey the user
-         (ignore the jobserver pipe for this make) but print a message.  */
-
-      if (job_slots > 0)
-        error (NILF,
-               _("warning: -jN forced in submake: disabling jobserver mode."));
+      char *cp;
 
-      /* Create a duplicate pipe, that will be closed in the SIGCHLD
-         handler.  If this fails with EBADF, the parent has closed the pipe
-         on us because it didn't think we were a submake.  If so, print a
-         warning then default to -j1.  */
+#ifdef WINDOWS32
+      /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS objects
+       * and one of them is the job-server semaphore object.  Limit the
+       * number of available job slots to (MAXIMUM_WAIT_OBJECTS - 1). */
 
-      else if ((job_rfd = dup (job_fds[0])) < 0)
+      if (job_slots >= MAXIMUM_WAIT_OBJECTS)
         {
-          if (errno != EBADF)
-            pfatal_with_name (_("dup jobserver"));
-
-          error (NILF,
-                 _("warning: jobserver unavailable: using -j1.  Add `+' to parent make rule."));
-          job_slots = 1;
+          job_slots = MAXIMUM_WAIT_OBJECTS - 1;
+          DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), job_slots));
         }
 
-      if (job_slots > 0)
+      if (! create_jobserver_semaphore (job_slots - 1))
         {
-          close (job_fds[0]);
-          close (job_fds[1]);
-          job_fds[0] = job_fds[1] = -1;
-          free (jobserver_fds->list);
-          free (jobserver_fds);
-          jobserver_fds = 0;
+          DWORD err = GetLastError ();
+          fatal (NILF, _("creating jobserver semaphore: (Error %ld: %s)"),
+                 err, map_windows32_error_to_string (err));
         }
-    }
-
-  /* If we have >1 slot but no jobserver-fds, then we're a top-level make.
-     Set up the pipe and install the fds option for our children.  */
-
-  if (job_slots > 1)
-    {
-      char *cp;
+#else
       char c = '+';
 
       if (pipe (job_fds) < 0 || (job_rfd = dup (job_fds[0])) < 0)
-       pfatal_with_name (_("creating jobs pipe"));
+        pfatal_with_name (_("creating jobs pipe"));
+#endif
 
       /* Every make assumes that it always has one job it can run.  For the
          submakes it's the token they were given by their parent.  For the
@@ -1783,6 +2026,10 @@ main (int argc, char **argv, char **envp)
 
       master_job_slots = job_slots;
 
+#ifdef WINDOWS32
+      /* We're using the jobserver so set job_slots to 0. */
+      job_slots = 0;
+#else
       while (--job_slots)
         {
           int r;
@@ -1791,14 +2038,19 @@ main (int argc, char **argv, char **envp)
           if (r != 1)
             pfatal_with_name (_("init jobserver pipe"));
         }
+#endif
 
       /* Fill in the jobserver_fds struct for our children.  */
 
-      cp = xmalloc ((sizeof ("1024")*2)+1);
+#ifdef WINDOWS32
+      cp = xmalloc (MAX_PATH + 1);
+      strcpy (cp, get_jobserver_semaphore_name ());
+#else
+      cp = xmalloc ((CSTRLEN ("1024") * 2) + 2);
       sprintf (cp, "%d,%d", job_fds[0], job_fds[1]);
+#endif
 
-      jobserver_fds = (struct stringlist *)
-                        xmalloc (sizeof (struct stringlist));
+      jobserver_fds = xmalloc (sizeof (struct stringlist));
       jobserver_fds->list = xmalloc (sizeof (char *));
       jobserver_fds->list[0] = cp;
       jobserver_fds->idx = 1;
@@ -1818,7 +2070,7 @@ main (int argc, char **argv, char **envp)
 
   define_makeflags (1, 0);
 
-  /* Make each `struct dep' point at the `struct file' for the file
+  /* Make each 'struct dep' point at the 'struct file' for the file
      depended on.  Also do magic for special targets.  */
 
   snap_deps ();
@@ -1857,7 +2109,7 @@ main (int argc, char **argv, char **envp)
           struct file *f = enter_file (*p);
           f->last_mtime = f->mtime_before_update = OLD_MTIME;
           f->updated = 1;
-          f->update_status = 0;
+          f->update_status = us_success;
           f->command_state = cs_finished;
         }
     }
@@ -1866,16 +2118,21 @@ main (int argc, char **argv, char **envp)
     {
       const char **p;
       for (p = new_files->list; *p != 0; ++p)
-       {
-         struct file *f = enter_file (*p);
-         f->last_mtime = f->mtime_before_update = NEW_MTIME;
-       }
+        {
+          struct file *f = enter_file (*p);
+          f->last_mtime = f->mtime_before_update = NEW_MTIME;
+        }
     }
 
   /* Initialize the remote job module.  */
   remote_setup ();
 
-  if (read_makefiles != 0)
+  /* Dump any output we've collected.  */
+
+  OUTPUT_UNSET ();
+  output_close (&make_sync);
+
+  if (read_files != 0)
     {
       /* Update any makefiles if necessary.  */
 
@@ -1884,7 +2141,7 @@ main (int argc, char **argv, char **envp)
       char **nargv;
       int nargc;
       int orig_db_level = db_level;
-      int status;
+      enum update_status status;
 
       if (! ISDB (DB_MAKEFILES))
         db_level = DB_NONE;
@@ -1892,88 +2149,88 @@ main (int argc, char **argv, char **envp)
       DB (DB_BASIC, (_("Updating makefiles....\n")));
 
       /* Remove any makefiles we don't want to try to update.
-        Also record the current modtimes so we can compare them later.  */
+         Also record the current modtimes so we can compare them later.  */
       {
-       register struct dep *d, *last;
-       last = 0;
-       d = read_makefiles;
-       while (d != 0)
-         {
-           struct file *f = d->file;
-           if (f->double_colon)
-             for (f = f->double_colon; f != NULL; f = f->prev)
-               {
-                 if (f->deps == 0 && f->cmds != 0)
-                   {
-                     /* This makefile is a :: target with commands, but
-                        no dependencies.  So, it will always be remade.
-                        This might well cause an infinite loop, so don't
-                        try to remake it.  (This will only happen if
-                        your makefiles are written exceptionally
-                        stupidly; but if you work for Athena, that's how
-                        you write your makefiles.)  */
-
-                     DB (DB_VERBOSE,
-                          (_("Makefile `%s' might loop; not remaking it.\n"),
+        register struct dep *d, *last;
+        last = 0;
+        d = read_files;
+        while (d != 0)
+          {
+            struct file *f = d->file;
+            if (f->double_colon)
+              for (f = f->double_colon; f != NULL; f = f->prev)
+                {
+                  if (f->deps == 0 && f->cmds != 0)
+                    {
+                      /* This makefile is a :: target with commands, but
+                         no dependencies.  So, it will always be remade.
+                         This might well cause an infinite loop, so don't
+                         try to remake it.  (This will only happen if
+                         your makefiles are written exceptionally
+                         stupidly; but if you work for Athena, that's how
+                         you write your makefiles.)  */
+
+                      DB (DB_VERBOSE,
+                          (_("Makefile '%s' might loop; not remaking it.\n"),
                            f->name));
 
-                     if (last == 0)
-                       read_makefiles = d->next;
-                     else
-                       last->next = d->next;
+                      if (last == 0)
+                        read_files = d->next;
+                      else
+                        last->next = d->next;
 
-                     /* Free the storage.  */
+                      /* Free the storage.  */
                       free_dep (d);
 
-                     d = last == 0 ? read_makefiles : last->next;
+                      d = last == 0 ? read_files : last->next;
 
-                     break;
-                   }
-               }
-           if (f == NULL || !f->double_colon)
-             {
+                      break;
+                    }
+                }
+            if (f == NULL || !f->double_colon)
+              {
                 makefile_mtimes = xrealloc (makefile_mtimes,
                                             (mm_idx+1)
                                             * sizeof (FILE_TIMESTAMP));
-               makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file);
-               last = d;
-               d = d->next;
-             }
-         }
+                makefile_mtimes[mm_idx++] = file_mtime_no_search (d->file);
+                last = d;
+                d = d->next;
+              }
+          }
       }
 
-      /* Set up `MAKEFLAGS' specially while remaking makefiles.  */
+      /* Set up 'MAKEFLAGS' specially while remaking makefiles.  */
       define_makeflags (1, 1);
 
       rebuilding_makefiles = 1;
-      status = update_goal_chain (read_makefiles);
+      status = update_goal_chain (read_files);
       rebuilding_makefiles = 0;
 
       switch (status)
-       {
-       case 1:
+        {
+        case us_question:
           /* The only way this can happen is if the user specified -q and asked
            * for one of the makefiles to be remade as a target on the command
            * line.  Since we're not actually updating anything with -q we can
            * treat this as "did nothing".
            */
 
-       case -1:
-         /* Did nothing.  */
-         break;
-
-       case 2:
-         /* Failed to update.  Figure out if we care.  */
-         {
-           /* Nonzero if any makefile was successfully remade.  */
-           int any_remade = 0;
-           /* Nonzero if any makefile we care about failed
-              in updating or could not be found at all.  */
-           int any_failed = 0;
-           unsigned int i;
+        case us_none:
+          /* Did nothing.  */
+          break;
+
+        case us_failed:
+          /* Failed to update.  Figure out if we care.  */
+          {
+            /* Nonzero if any makefile was successfully remade.  */
+            int any_remade = 0;
+            /* Nonzero if any makefile we care about failed
+               in updating or could not be found at all.  */
+            int any_failed = 0;
+            unsigned int i;
             struct dep *d;
 
-           for (i = 0, d = read_makefiles; d != 0; ++i, d = d->next)
+            for (i = 0, d = read_files; d != 0; ++i, d = d->next)
               {
                 /* Reset the considered flag; we may need to look at the file
                    again to print an error.  */
@@ -1982,7 +2239,7 @@ main (int argc, char **argv, char **envp)
                 if (d->file->updated)
                   {
                     /* This makefile was updated.  */
-                    if (d->file->update_status == 0)
+                    if (d->file->update_status == us_success)
                       {
                         /* It was successfully updated.  */
                         any_remade |= (file_mtime_no_search (d->file)
@@ -1993,7 +2250,7 @@ main (int argc, char **argv, char **envp)
                         FILE_TIMESTAMP mtime;
                         /* The update failed and this makefile was not
                            from the MAKEFILES variable, so we care.  */
-                        error (NILF, _("Failed to remake makefile `%s'."),
+                        error (NILF, _("Failed to remake makefile '%s'."),
                                d->file->name);
                         mtime = file_mtime_no_search (d->file);
                         any_remade |= (mtime != NONEXISTENT_MTIME
@@ -2010,55 +2267,53 @@ main (int argc, char **argv, char **envp)
                         /* An included makefile.  We don't need
                            to die, but we do want to complain.  */
                         error (NILF,
-                               _("Included makefile `%s' was not found."),
+                               _("Included makefile '%s' was not found."),
                                dep_name (d));
                       else
                         {
                           /* A normal makefile.  We must die later.  */
-                          error (NILF, _("Makefile `%s' was not found"),
+                          error (NILF, _("Makefile '%s' was not found"),
                                  dep_name (d));
                           any_failed = 1;
                         }
                     }
               }
             /* Reset this to empty so we get the right error message below.  */
-            read_makefiles = 0;
+            read_files = 0;
 
-           if (any_remade)
-             goto re_exec;
-           if (any_failed)
-             die (2);
+            if (any_remade)
+              goto re_exec;
+            if (any_failed)
+              die (2);
             break;
-         }
-
-       case 0:
-       re_exec:
-         /* Updated successfully.  Re-exec ourselves.  */
+          }
 
-         remove_intermediates (0);
+        case us_success:
+        re_exec:
+          /* Updated successfully.  Re-exec ourselves.  */
 
-         if (print_data_base_flag)
-           print_data_base ();
+          remove_intermediates (0);
 
-         log_working_directory (0);
+          if (print_data_base_flag)
+            print_data_base ();
 
           clean_jobserver (0);
 
-         if (makefiles != 0)
-           {
-             /* These names might have changed.  */
-             int i, j = 0;
-             for (i = 1; i < argc; ++i)
-               if (strneq (argv[i], "-f", 2)) /* XXX */
-                 {
-                   if (argv[i][2] == '\0')
+          if (makefiles != 0)
+            {
+              /* These names might have changed.  */
+              int i, j = 0;
+              for (i = 1; i < argc; ++i)
+                if (strneq (argv[i], "-f", 2)) /* XXX */
+                  {
+                    if (argv[i][2] == '\0')
                       /* This cast is OK since we never modify argv.  */
-                     argv[++i] = (char *) makefiles->list[j];
-                   else
-                     argv[i] = xstrdup (concat (2, "-f", makefiles->list[j]));
-                   ++j;
-                 }
-           }
+                      argv[++i] = (char *) makefiles->list[j];
+                    else
+                      argv[i] = xstrdup (concat (2, "-f", makefiles->list[j]));
+                    ++j;
+                  }
+            }
 
           /* Add -o option for the stdin temporary file, if necessary.  */
           nargc = argc;
@@ -2072,118 +2327,111 @@ main (int argc, char **argv, char **envp)
           else
             nargv = argv;
 
-         if (directories != 0 && directories->idx > 0)
-           {
-             int bad = 1;
-             if (directory_before_chdir != 0)
-               {
-                 if (chdir (directory_before_chdir) < 0)
-                     perror_with_name ("chdir", "");
-                 else
-                   bad = 0;
-               }
-             if (bad)
-               fatal (NILF, _("Couldn't change back to original directory."));
-           }
+          if (directories != 0 && directories->idx > 0)
+            {
+              int bad = 1;
+              if (directory_before_chdir != 0)
+                {
+                  if (chdir (directory_before_chdir) < 0)
+                      perror_with_name ("chdir", "");
+                  else
+                    bad = 0;
+                }
+              if (bad)
+                fatal (NILF, _("Couldn't change back to original directory."));
+            }
 
           ++restarts;
 
-          /* Reset makeflags in case they were changed.  */
-          {
-            const char *pv = define_makeflags (1, 1);
-            char *p = alloca (sizeof ("MAKEFLAGS=") + strlen (pv) + 1);
-            sprintf (p, "MAKEFLAGS=%s", pv);
-            putenv (p);
-          }
+          /* If we're re-exec'ing the first make, put back the number of
+             job slots so define_makefiles() will get it right.  */
+          if (master_job_slots)
+            job_slots = master_job_slots;
 
-         if (ISDB (DB_BASIC))
-           {
-             char **p;
-             printf (_("Re-executing[%u]:"), restarts);
-             for (p = nargv; *p != 0; ++p)
-               printf (" %s", *p);
-             putchar ('\n');
-           }
+          if (ISDB (DB_BASIC))
+            {
+              char **p;
+              printf (_("Re-executing[%u]:"), restarts);
+              for (p = nargv; *p != 0; ++p)
+                printf (" %s", *p);
+              putchar ('\n');
+            }
 
 #ifndef _AMIGA
           {
             char **p;
             for (p = environ; *p != 0; ++p)
               {
-                if (strneq (*p, MAKELEVEL_NAME, MAKELEVEL_LENGTH)
-                    && (*p)[MAKELEVEL_LENGTH] == '=')
+                if (strneq (*p, MAKELEVEL_NAME "=", MAKELEVEL_LENGTH+1))
                   {
                     *p = alloca (40);
                     sprintf (*p, "%s=%u", MAKELEVEL_NAME, makelevel);
                   }
-                if (strneq (*p, "MAKE_RESTARTS=", 14))
+                else if (strneq (*p, "MAKE_RESTARTS=", CSTRLEN ("MAKE_RESTARTS=")))
                   {
                     *p = alloca (40);
-                    sprintf (*p, "MAKE_RESTARTS=%u", restarts);
+                    sprintf (*p, "MAKE_RESTARTS=%s%u",
+                             OUTPUT_IS_TRACED () ? "-" : "", restarts);
                     restarts = 0;
                   }
               }
           }
 #else /* AMIGA */
-         {
-           char buffer[256];
+          {
+            char buffer[256];
 
             sprintf (buffer, "%u", makelevel);
             SetVar (MAKELEVEL_NAME, buffer, -1, GVF_GLOBAL_ONLY);
 
-            sprintf (buffer, "%u", restarts);
+            sprintf (buffer, "%s%u", OUTPUT_IS_TRACED () ? "-" : "", restarts);
             SetVar ("MAKE_RESTARTS", buffer, -1, GVF_GLOBAL_ONLY);
             restarts = 0;
-         }
+          }
 #endif
 
           /* If we didn't set the restarts variable yet, add it.  */
           if (restarts)
             {
               char *b = alloca (40);
-              sprintf (b, "MAKE_RESTARTS=%u", restarts);
+              sprintf (b, "MAKE_RESTARTS=%s%u",
+                       OUTPUT_IS_TRACED () ? "-" : "", restarts);
               putenv (b);
             }
 
-         fflush (stdout);
-         fflush (stderr);
+          fflush (stdout);
+          fflush (stderr);
 
           /* Close the dup'd jobserver pipe if we opened one.  */
           if (job_rfd >= 0)
             close (job_rfd);
 
 #ifdef _AMIGA
-         exec_command (nargv);
-         exit (0);
+          exec_command (nargv);
+          exit (0);
 #elif defined (__EMX__)
-         {
-           /* It is not possible to use execve() here because this
-              would cause the parent process to be terminated with
-              exit code 0 before the child process has been terminated.
-              Therefore it may be the best solution simply to spawn the
-              child process including all file handles and to wait for its
-              termination. */
-           int pid;
-           int status;
-           pid = child_execute_job (0, 1, nargv, environ);
-
-           /* is this loop really necessary? */
-           do {
-             pid = wait (&status);
-           } while (pid <= 0);
-           /* use the exit code of the child process */
-           exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
-         }
+          {
+            /* It is not possible to use execve() here because this
+               would cause the parent process to be terminated with
+               exit code 0 before the child process has been terminated.
+               Therefore it may be the best solution simply to spawn the
+               child process including all file handles and to wait for its
+               termination. */
+            int pid;
+            int r;
+            pid = child_execute_job (FD_STDIN, FD_STDOUT, FD_STDERR,
+                                     nargv, environ);
+
+            /* is this loop really necessary? */
+            do {
+              pid = wait (&r);
+            } while (pid <= 0);
+            /* use the exit code of the child process */
+            exit (WIFEXITED(r) ? WEXITSTATUS(r) : EXIT_FAILURE);
+          }
 #else
-         exec_command (nargv, environ);
+          exec_command (nargv, environ);
 #endif
-         /* NOTREACHED */
-
-       default:
-#define BOGUS_UPDATE_STATUS 0
-         assert (BOGUS_UPDATE_STATUS);
-         break;
-       }
+        }
 
       db_level = orig_db_level;
 
@@ -2192,7 +2440,7 @@ main (int argc, char **argv, char **envp)
         free (makefile_mtimes);
     }
 
-  /* Set up `MAKEFLAGS' again for the normal targets.  */
+  /* Set up 'MAKEFLAGS' again for the normal targets.  */
   define_makeflags (1, 0);
 
   /* Set always_make_flag if -B was given.  */
@@ -2203,10 +2451,10 @@ main (int argc, char **argv, char **envp)
     {
       const char **p;
       for (p = new_files->list; *p != 0; ++p)
-       {
-         struct file *f = enter_file (*p);
-         f->last_mtime = f->mtime_before_update = NEW_MTIME;
-       }
+        {
+          struct file *f = enter_file (*p);
+          f->last_mtime = f->mtime_before_update = NEW_MTIME;
+        }
     }
 
   /* If there is a temp file from reading a makefile from stdin, get rid of
@@ -2239,7 +2487,7 @@ main (int argc, char **argv, char **envp)
             {
               struct nameseq *ns;
 
-              ns = PARSE_FILE_SEQ (&p, struct nameseq, '\0', NULL, 0);
+              ns = PARSE_SIMPLE_SEQ (&p, struct nameseq);
               if (ns)
                 {
                   /* .DEFAULT_GOAL should contain one target. */
@@ -2266,7 +2514,7 @@ main (int argc, char **argv, char **envp)
 
   if (!goals)
     {
-      if (read_makefiles == 0)
+      if (read_files == 0)
         fatal (NILF, _("No targets specified and no makefile found"));
 
       fatal (NILF, _("No targets"));
@@ -2277,27 +2525,23 @@ main (int argc, char **argv, char **envp)
   DB (DB_BASIC, (_("Updating goal targets....\n")));
 
   {
-    int status;
-
     switch (update_goal_chain (goals))
     {
-      case -1:
+      case us_none:
         /* Nothing happened.  */
-      case 0:
-        /* Updated successfully.  */
-        status = makefile_status;
+        /* FALLTHROUGH */
+      case us_success:
+        /* Keep the previous result.  */
         break;
-      case 1:
+      case us_question:
         /* We are under -q and would run some commands.  */
-        status = MAKE_TROUBLE;
+        makefile_status = MAKE_TROUBLE;
         break;
-      case 2:
+      case us_failed:
         /* Updating failed.  POSIX.2 specifies exit status >1 for this;
            but in VMS, there is only success and failure.  */
-        status = MAKE_FAILURE;
+        makefile_status = MAKE_FAILURE;
         break;
-      default:
-        abort ();
     }
 
     /* If we detected some clock skew, generate one last warning */
@@ -2306,19 +2550,19 @@ main (int argc, char **argv, char **envp)
              _("warning:  Clock skew detected.  Your build may be incomplete."));
 
     /* Exit.  */
-    die (status);
+    die (makefile_status);
   }
 
   /* NOTREACHED */
-  return 0;
+  exit (0);
 }
 \f
 /* Parsing of arguments, decoding of switches.  */
 
 static char options[1 + sizeof (switches) / sizeof (switches[0]) * 3];
 static struct option long_options[(sizeof (switches) / sizeof (switches[0])) +
-                                 (sizeof (long_option_aliases) /
-                                  sizeof (long_option_aliases[0]))];
+                                  (sizeof (long_option_aliases) /
+                                   sizeof (long_option_aliases[0]))];
 
 /* Fill in the string and vector for getopt.  */
 static void
@@ -2341,89 +2585,93 @@ init_switches (void)
   for (i = 0; switches[i].c != '\0'; ++i)
     {
       long_options[i].name = (switches[i].long_name == 0 ? "" :
-                             switches[i].long_name);
+                              switches[i].long_name);
       long_options[i].flag = 0;
       long_options[i].val = switches[i].c;
       if (short_option (switches[i].c))
-       *p++ = switches[i].c;
+        *p++ = switches[i].c;
       switch (switches[i].type)
-       {
-       case flag:
-       case flag_off:
-       case ignore:
-         long_options[i].has_arg = no_argument;
-         break;
-
-       case string:
+        {
+        case flag:
+        case flag_off:
+        case ignore:
+          long_options[i].has_arg = no_argument;
+          break;
+
+        case string:
         case filename:
-       case positive_int:
-       case floating:
-         if (short_option (switches[i].c))
-           *p++ = ':';
-         if (switches[i].noarg_value != 0)
-           {
-             if (short_option (switches[i].c))
-               *p++ = ':';
-             long_options[i].has_arg = optional_argument;
-           }
-         else
-           long_options[i].has_arg = required_argument;
-         break;
-       }
+        case positive_int:
+        case floating:
+          if (short_option (switches[i].c))
+            *p++ = ':';
+          if (switches[i].noarg_value != 0)
+            {
+              if (short_option (switches[i].c))
+                *p++ = ':';
+              long_options[i].has_arg = optional_argument;
+            }
+          else
+            long_options[i].has_arg = required_argument;
+          break;
+        }
     }
   *p = '\0';
   for (c = 0; c < (sizeof (long_option_aliases) /
-                  sizeof (long_option_aliases[0]));
+                   sizeof (long_option_aliases[0]));
        ++c)
     long_options[i++] = long_option_aliases[c];
   long_options[i].name = 0;
 }
 
+
+/* Non-option argument.  It might be a variable definition.  */
 static void
 handle_non_switch_argument (char *arg, int env)
 {
-  /* Non-option argument.  It might be a variable definition.  */
   struct variable *v;
+
   if (arg[0] == '-' && arg[1] == '\0')
-    /* Ignore plain `-' for compatibility.  */
+    /* Ignore plain '-' for compatibility.  */
     return;
+
   v = try_variable_definition (0, arg, o_command, 0);
   if (v != 0)
     {
       /* It is indeed a variable definition.  If we don't already have this
-        one, record a pointer to the variable for later use in
-        define_makeflags.  */
+         one, record a pointer to the variable for later use in
+         define_makeflags.  */
       struct command_variable *cv;
 
       for (cv = command_variables; cv != 0; cv = cv->next)
         if (cv->variable == v)
           break;
 
-      if (! cv) {
-        cv = xmalloc (sizeof (*cv));
-        cv->variable = v;
-        cv->next = command_variables;
-        command_variables = cv;
-      }
+      if (! cv)
+        {
+          cv = xmalloc (sizeof (*cv));
+          cv->variable = v;
+          cv->next = command_variables;
+          command_variables = cv;
+        }
     }
   else if (! env)
     {
       /* Not an option or variable definition; it must be a goal
-        target!  Enter it as a file and add it to the dep chain of
-        goals.  */
+         target!  Enter it as a file and add it to the dep chain of
+         goals.  */
       struct file *f = enter_file (strcache_add (expand_command_line_file (arg)));
       f->cmd_target = 1;
 
       if (goals == 0)
-       {
-         goals = alloc_dep ();
-         lastgoal = goals;
-       }
+        {
+          goals = alloc_dep ();
+          lastgoal = goals;
+        }
       else
-       {
-         lastgoal->next = alloc_dep ();
-         lastgoal = lastgoal->next;
-       }
+        {
+          lastgoal->next = alloc_dep ();
+          lastgoal = lastgoal->next;
+        }
 
       lastgoal->file = f;
 
@@ -2508,47 +2756,47 @@ decode_switches (int argc, char **argv, int env)
       /* Parse the next argument.  */
       c = getopt_long (argc, argv, options, long_options, (int *) 0);
       if (c == EOF)
-       /* End of arguments, or "--" marker seen.  */
-       break;
+        /* End of arguments, or "--" marker seen.  */
+        break;
       else if (c == 1)
-       /* An argument not starting with a dash.  */
-       handle_non_switch_argument (optarg, env);
+        /* An argument not starting with a dash.  */
+        handle_non_switch_argument (optarg, env);
       else if (c == '?')
-       /* Bad option.  We will print a usage message and die later.
-          But continue to parse the other options so the user can
-          see all he did wrong.  */
-       bad = 1;
+        /* Bad option.  We will print a usage message and die later.
+           But continue to parse the other options so the user can
+           see all he did wrong.  */
+        bad = 1;
       else
-       for (cs = switches; cs->c != '\0'; ++cs)
-         if (cs->c == c)
-           {
-             /* Whether or not we will actually do anything with
-                this switch.  We test this individually inside the
-                switch below rather than just once outside it, so that
-                options which are to be ignored still consume args.  */
-             int doit = !env || cs->env;
-
-             switch (cs->type)
-               {
-               default:
-                 abort ();
-
-               case ignore:
-                 break;
-
-               case flag:
-               case flag_off:
-                 if (doit)
-                   *(int *) cs->value_ptr = cs->type == flag;
-                 break;
-
-               case string:
-               case filename:
-                 if (!doit)
-                   break;
-
-                 if (optarg == 0)
-                   optarg = xstrdup (cs->noarg_value);
+        for (cs = switches; cs->c != '\0'; ++cs)
+          if (cs->c == c)
+            {
+              /* Whether or not we will actually do anything with
+                 this switch.  We test this individually inside the
+                 switch below rather than just once outside it, so that
+                 options which are to be ignored still consume args.  */
+              int doit = !env || cs->env;
+
+              switch (cs->type)
+                {
+                default:
+                  abort ();
+
+                case ignore:
+                  break;
+
+                case flag:
+                case flag_off:
+                  if (doit)
+                    *(int *) cs->value_ptr = cs->type == flag;
+                  break;
+
+                case string:
+                case filename:
+                  if (!doit)
+                    break;
+
+                  if (optarg == 0)
+                    optarg = xstrdup (cs->noarg_value);
                   else if (*optarg == '\0')
                     {
                       char opt[2] = "c";
@@ -2559,39 +2807,38 @@ decode_switches (int argc, char **argv, int env)
                       else
                         op = cs->long_name;
 
-                      error (NILF, _("the `%s%s' option requires a non-empty string argument"),
+                      error (NILF, _("the '%s%s' option requires a non-empty string argument"),
                              short_option (cs->c) ? "-" : "--", op);
                       bad = 1;
                     }
 
-                 sl = *(struct stringlist **) cs->value_ptr;
-                 if (sl == 0)
-                   {
-                     sl = (struct stringlist *)
-                       xmalloc (sizeof (struct stringlist));
-                     sl->max = 5;
-                     sl->idx = 0;
-                     sl->list = xmalloc (5 * sizeof (char *));
-                     *(struct stringlist **) cs->value_ptr = sl;
-                   }
-                 else if (sl->idx == sl->max - 1)
-                   {
-                     sl->max += 5;
+                  sl = *(struct stringlist **) cs->value_ptr;
+                  if (sl == 0)
+                    {
+                      sl = xmalloc (sizeof (struct stringlist));
+                      sl->max = 5;
+                      sl->idx = 0;
+                      sl->list = xmalloc (5 * sizeof (char *));
+                      *(struct stringlist **) cs->value_ptr = sl;
+                    }
+                  else if (sl->idx == sl->max - 1)
+                    {
+                      sl->max += 5;
                       /* MSVC erroneously warns without a cast here.  */
-                     sl->list = xrealloc ((void *)sl->list,
+                      sl->list = xrealloc ((void *)sl->list,
                                            sl->max * sizeof (char *));
-                   }
+                    }
                   if (cs->type == filename)
                     sl->list[sl->idx++] = expand_command_line_file (optarg);
                   else
                     sl->list[sl->idx++] = optarg;
-                 sl->list[sl->idx] = 0;
-                 break;
+                  sl->list[sl->idx] = 0;
+                  break;
 
-               case positive_int:
+                case positive_int:
                   /* See if we have an option argument; if we do require that
                      it's all digits, not something like "10foo".  */
-                 if (optarg == 0 && argc > optind)
+                  if (optarg == 0 && argc > optind)
                     {
                       const char *cp;
                       for (cp=argv[optind]; ISDIGIT (cp[0]); ++cp)
@@ -2600,50 +2847,50 @@ decode_switches (int argc, char **argv, int env)
                         optarg = argv[optind++];
                     }
 
-                 if (!doit)
-                   break;
+                  if (!doit)
+                    break;
 
-                 if (optarg != 0)
-                   {
-                     int i = atoi (optarg);
+                  if (optarg != 0)
+                    {
+                      int i = atoi (optarg);
                       const char *cp;
 
                       /* Yes, I realize we're repeating this in some cases.  */
                       for (cp = optarg; ISDIGIT (cp[0]); ++cp)
                         ;
 
-                     if (i < 1 || cp[0] != '\0')
-                       {
-                          error (NILF, _("the `-%c' option requires a positive integral argument"),
+                      if (i < 1 || cp[0] != '\0')
+                        {
+                          error (NILF, _("the '-%c' option requires a positive integer argument"),
                                  cs->c);
-                         bad = 1;
-                       }
-                     else
-                       *(unsigned int *) cs->value_ptr = i;
-                   }
-                 else
-                   *(unsigned int *) cs->value_ptr
-                     = *(unsigned int *) cs->noarg_value;
-                 break;
+                          bad = 1;
+                        }
+                      else
+                        *(unsigned int *) cs->value_ptr = i;
+                    }
+                  else
+                    *(unsigned int *) cs->value_ptr
+                      = *(unsigned int *) cs->noarg_value;
+                  break;
 
 #ifndef NO_FLOAT
-               case floating:
-                 if (optarg == 0 && optind < argc
-                     && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.'))
-                   optarg = argv[optind++];
+                case floating:
+                  if (optarg == 0 && optind < argc
+                      && (ISDIGIT (argv[optind][0]) || argv[optind][0] == '.'))
+                    optarg = argv[optind++];
 
-                 if (doit)
-                   *(double *) cs->value_ptr
-                     = (optarg != 0 ? atof (optarg)
-                        : *(double *) cs->noarg_value);
+                  if (doit)
+                    *(double *) cs->value_ptr
+                      = (optarg != 0 ? atof (optarg)
+                         : *(double *) cs->noarg_value);
 
-                 break;
+                  break;
 #endif
-               }
+                }
 
-             /* We've found the switch.  Stop looking.  */
-             break;
-           }
+              /* We've found the switch.  Stop looking.  */
+              break;
+            }
     }
 
   /* There are no more options according to getting getopt, but there may
@@ -2653,12 +2900,15 @@ decode_switches (int argc, char **argv, int env)
   while (optind < argc)
     handle_non_switch_argument (argv[optind++], env);
 
-
   if (!env && (bad || print_usage_flag))
     {
       print_usage (bad);
       die (bad ? 2 : 0);
     }
+
+  /* If there are any options that need to be decoded do it now.  */
+  decode_debug_flags ();
+  decode_output_sync_flags ();
 }
 
 /* Decode switches from environment variable ENVAR (which is LEN chars long).
@@ -2704,17 +2954,17 @@ decode_env_switches (char *envar, unsigned int len)
   while (*value != '\0')
     {
       if (*value == '\\' && value[1] != '\0')
-       ++value;                /* Skip the backslash.  */
+        ++value;                /* Skip the backslash.  */
       else if (isblank ((unsigned char)*value))
-       {
-         /* End of the word.  */
-         *p++ = '\0';
-         argv[++argc] = p;
-         do
-           ++value;
-         while (isblank ((unsigned char)*value));
-         continue;
-       }
+        {
+          /* End of the word.  */
+          *p++ = '\0';
+          argv[++argc] = p;
+          do
+            ++value;
+          while (isblank ((unsigned char)*value));
+          continue;
+        }
       *p++ = *value++;
     }
   *p = '\0';
@@ -2743,7 +2993,7 @@ quote_for_env (char *out, const char *in)
   while (*in != '\0')
     {
       if (*in == '$')
-       *out++ = '$';
+        *out++ = '$';
       else if (isblank ((unsigned char)*in) || *in == '\\')
         *out++ = '\\';
       *out++ = *in++;
@@ -2754,9 +3004,9 @@ quote_for_env (char *out, const char *in)
 
 /* Define the MAKEFLAGS and MFLAGS variables to reflect the settings of the
    command switches.  Include options with args if ALL is nonzero.
-   Don't include options with the `no_makefile' flag set if MAKEFILE.  */
+   Don't include options with the 'no_makefile' flag set if MAKEFILE.  */
 
-static const char *
+static struct variable *
 define_makeflags (int all, int makefile)
 {
   const char ref[] = "$(MAKEOVERRIDES)";
@@ -2764,11 +3014,9 @@ define_makeflags (int all, int makefile)
   const char evalref[] = "$(-*-eval-flags-*-)";
   const struct command_switch *cs;
   char *flagstring;
-  register char *p;
-  unsigned int words;
-  struct variable *v;
+  char *p;
 
-  /* We will construct a linked list of `struct flag's describing
+  /* We will construct a linked list of 'struct flag's describing
      all the flags which need to go in MAKEFLAGS.  Then, once we
      know how many there are and their lengths, we can put them all
      together in a string.  */
@@ -2780,259 +3028,210 @@ define_makeflags (int all, int makefile)
       const char *arg;
     };
   struct flag *flags = 0;
+  struct flag *last = 0;
   unsigned int flagslen = 0;
-#define        ADD_FLAG(ARG, LEN) \
-  do {                                                                       \
-    struct flag *new = alloca (sizeof (struct flag));                        \
-    new->cs = cs;                                                            \
-    new->arg = (ARG);                                                        \
-    new->next = flags;                                                       \
-    flags = new;                                                             \
-    if (new->arg == 0)                                                       \
-      ++flagslen;              /* Just a single flag letter.  */             \
-    else                                                                     \
-      /* " -x foo", plus space to expand "foo".  */                          \
-      flagslen += 1 + 1 + 1 + 1 + (3 * (LEN));                               \
-    if (!short_option (cs->c))                                               \
+#define ADD_FLAG(ARG, LEN) \
+  do {                                                                        \
+    struct flag *new = alloca (sizeof (struct flag));                         \
+    new->cs = cs;                                                             \
+    new->arg = (ARG);                                                         \
+    new->next = 0;                                                            \
+    if (! flags)                                                              \
+      flags = new;                                                            \
+    else                                                                      \
+      last->next = new;                                                       \
+    last = new;                                                               \
+    if (new->arg == 0)                                                        \
+      /* Just a single flag letter: " -x"  */                                 \
+      flagslen += 3;                                                          \
+    else                                                                      \
+      /* " -xfoo", plus space to escape "foo".  */                            \
+      flagslen += 1 + 1 + 1 + (3 * (LEN));                                    \
+    if (!short_option (cs->c))                                                \
       /* This switch has no single-letter version, so we use the long.  */    \
-      flagslen += 2 + strlen (cs->long_name);                                \
+      flagslen += 2 + strlen (cs->long_name);                                 \
   } while (0)
 
   for (cs = switches; cs->c != '\0'; ++cs)
     if (cs->toenv && (!makefile || !cs->no_makefile))
       switch (cs->type)
-       {
-       case ignore:
-         break;
-
-       case flag:
-       case flag_off:
-         if (!*(int *) cs->value_ptr == (cs->type == flag_off)
-             && (cs->default_value == 0
-                 || *(int *) cs->value_ptr != *(int *) cs->default_value))
-           ADD_FLAG (0, 0);
-         break;
-
-       case positive_int:
-         if (all)
-           {
-             if ((cs->default_value != 0
-                  && (*(unsigned int *) cs->value_ptr
-                      == *(unsigned int *) cs->default_value)))
-               break;
-             else if (cs->noarg_value != 0
-                      && (*(unsigned int *) cs->value_ptr ==
-                          *(unsigned int *) cs->noarg_value))
-               ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
-             else if (cs->c == 'j')
-               /* Special case for `-j'.  */
-               ADD_FLAG ("1", 1);
-             else
-               {
-                 char *buf = alloca (30);
-                 sprintf (buf, "%u", *(unsigned int *) cs->value_ptr);
-                 ADD_FLAG (buf, strlen (buf));
-               }
-           }
-         break;
+        {
+        case ignore:
+          break;
+
+        case flag:
+        case flag_off:
+          if (!*(int *) cs->value_ptr == (cs->type == flag_off)
+              && (cs->default_value == 0
+                  || *(int *) cs->value_ptr != *(int *) cs->default_value))
+            ADD_FLAG (0, 0);
+          break;
+
+        case positive_int:
+          if (all)
+            {
+              if ((cs->default_value != 0
+                   && (*(unsigned int *) cs->value_ptr
+                       == *(unsigned int *) cs->default_value)))
+                break;
+              else if (cs->noarg_value != 0
+                       && (*(unsigned int *) cs->value_ptr ==
+                           *(unsigned int *) cs->noarg_value))
+                ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
+              else
+                {
+                  char *buf = alloca (30);
+                  sprintf (buf, "%u", *(unsigned int *) cs->value_ptr);
+                  ADD_FLAG (buf, strlen (buf));
+                }
+            }
+          break;
 
 #ifndef NO_FLOAT
-       case floating:
-         if (all)
-           {
-             if (cs->default_value != 0
-                 && (*(double *) cs->value_ptr
-                     == *(double *) cs->default_value))
-               break;
-             else if (cs->noarg_value != 0
-                      && (*(double *) cs->value_ptr
-                          == *(double *) cs->noarg_value))
-               ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
-             else
-               {
-                 char *buf = alloca (100);
-                 sprintf (buf, "%g", *(double *) cs->value_ptr);
-                 ADD_FLAG (buf, strlen (buf));
-               }
-           }
-         break;
-#endif
-
-       case filename:
-       case string:
-         if (all)
-           {
-             struct stringlist *sl = *(struct stringlist **) cs->value_ptr;
-             if (sl != 0)
-               {
-                 /* Add the elements in reverse order, because all the flags
-                    get reversed below; and the order matters for some
-                    switches (like -I).  */
-                 unsigned int i = sl->idx;
-                 while (i-- > 0)
-                   ADD_FLAG (sl->list[i], strlen (sl->list[i]));
-               }
-           }
-         break;
-
-       default:
-         abort ();
-       }
-
-  /* Four more for the possible " -- ".  */
-  flagslen += 4 + sizeof (posixref) + sizeof (evalref);
-
-#undef ADD_FLAG
+        case floating:
+          if (all)
+            {
+              if (cs->default_value != 0
+                  && (*(double *) cs->value_ptr
+                      == *(double *) cs->default_value))
+                break;
+              else if (cs->noarg_value != 0
+                       && (*(double *) cs->value_ptr
+                           == *(double *) cs->noarg_value))
+                ADD_FLAG ("", 0); /* Optional value omitted; see below.  */
+              else
+                {
+                  char *buf = alloca (100);
+                  sprintf (buf, "%g", *(double *) cs->value_ptr);
+                  ADD_FLAG (buf, strlen (buf));
+                }
+            }
+          break;
+#endif
+
+        case filename:
+        case string:
+          if (all)
+            {
+              struct stringlist *sl = *(struct stringlist **) cs->value_ptr;
+              if (sl != 0)
+                {
+                  unsigned int i;
+                  for (i = 0; i < sl->idx; ++i)
+                    ADD_FLAG (sl->list[i], strlen (sl->list[i]));
+                }
+            }
+          break;
+
+        default:
+          abort ();
+        }
+
+#undef  ADD_FLAG
+
+  /* Four more for the possible " -- ", plus variable references.  */
+  flagslen += 4 + CSTRLEN (posixref) + 1 + CSTRLEN (evalref) + 1;
 
   /* Construct the value in FLAGSTRING.
      We allocate enough space for a preceding dash and trailing null.  */
   flagstring = alloca (1 + flagslen + 1);
   memset (flagstring, '\0', 1 + flagslen + 1);
   p = flagstring;
-  words = 1;
+
+  /* Start with a dash, for MFLAGS.  */
   *p++ = '-';
-  while (flags != 0)
+
+  /* Add simple options as a group.  */
+  while (flags != 0 && !flags->arg && short_option (flags->cs->c))
+    {
+      *p++ = flags->cs->c;
+      flags = flags->next;
+    }
+
+  /* Now add more complex flags: ones with options and/or long names.  */
+  while (flags)
     {
+      *p++ = ' ';
+      *p++ = '-';
+
       /* Add the flag letter or name to the string.  */
       if (short_option (flags->cs->c))
-       *p++ = flags->cs->c;
+        *p++ = flags->cs->c;
       else
-       {
-          if (*p != '-')
-            {
-              *p++ = ' ';
-              *p++ = '-';
-            }
-         *p++ = '-';
-         strcpy (p, flags->cs->long_name);
-         p += strlen (p);
-       }
-      if (flags->arg != 0)
-       {
-         /* A flag that takes an optional argument which in this case is
-            omitted is specified by ARG being "".  We must distinguish
-            because a following flag appended without an intervening " -"
-            is considered the arg for the first.  */
-         if (flags->arg[0] != '\0')
-           {
-             /* Add its argument too.  */
-             *p++ = !short_option (flags->cs->c) ? '=' : ' ';
-             p = quote_for_env (p, flags->arg);
-           }
-         ++words;
-         /* Write a following space and dash, for the next flag.  */
-         *p++ = ' ';
-         *p++ = '-';
-       }
-      else if (!short_option (flags->cs->c))
-       {
-         ++words;
-         /* Long options must each go in their own word,
-            so we write the following space and dash.  */
-         *p++ = ' ';
-         *p++ = '-';
-       }
+        {
+          /* Long options require a double-dash.  */
+          *p++ = '-';
+          strcpy (p, flags->cs->long_name);
+          p += strlen (p);
+        }
+      /* An omitted optional argument has an ARG of "".  */
+      if (flags->arg && flags->arg[0] != '\0')
+        {
+          if (!short_option (flags->cs->c))
+            /* Long options require '='.  */
+            *p++ = '=';
+          p = quote_for_env (p, flags->arg);
+        }
       flags = flags->next;
     }
 
-  /* Define MFLAGS before appending variable definitions.  */
-
+  /* If no flags at all, get rid of the initial dash.  */
   if (p == &flagstring[1])
-    /* No flags.  */
-    flagstring[0] = '\0';
-  else if (p[-1] == '-')
     {
-      /* Kill the final space and dash.  */
-      p -= 2;
-      *p = '\0';
+      flagstring[0] = '\0';
+      p = flagstring;
     }
-  else
-    /* Terminate the string.  */
-    *p = '\0';
 
-  /* Since MFLAGS is not parsed for flags, there is no reason to
+  /* Define MFLAGS before appending variable definitions.  Omit an initial
+     empty dash.  Since MFLAGS is not parsed for flags, there is no reason to
      override any makefile redefinition.  */
-  define_variable_cname ("MFLAGS", flagstring, o_env, 1);
+  define_variable_cname ("MFLAGS",
+                         flagstring + (flagstring[0] == '-' && flagstring[1] == ' ' ? 2 : 0),
+                         o_env, 1);
 
   /* Write a reference to -*-eval-flags-*-, which contains all the --eval
      flag options.  */
   if (eval_strings)
     {
-      if (p == &flagstring[1])
-       /* No flags written, so elide the leading dash already written.  */
-       p = flagstring;
-      else
-        *p++ = ' ';
-      memcpy (p, evalref, sizeof (evalref) - 1);
-      p += sizeof (evalref) - 1;
+      *p++ = ' ';
+      memcpy (p, evalref, CSTRLEN (evalref));
+      p += CSTRLEN (evalref);
     }
 
-  if (all && command_variables != 0)
+  if (all && command_variables)
     {
-      /* Now write a reference to $(MAKEOVERRIDES), which contains all the
-        command-line variable definitions.  */
+      /* Write a reference to $(MAKEOVERRIDES), which contains all the
+         command-line variable definitions.  Separate the variables from the
+         switches with a "--" arg.  */
 
-      if (p == &flagstring[1])
-       /* No flags written, so elide the leading dash already written.  */
-       p = flagstring;
-      else
-       {
-         /* Separate the variables from the switches with a "--" arg.  */
-         if (p[-1] != '-')
-           {
-             /* We did not already write a trailing " -".  */
-             *p++ = ' ';
-             *p++ = '-';
-           }
-         /* There is a trailing " -"; fill it out to " -- ".  */
-         *p++ = '-';
-         *p++ = ' ';
-       }
+      strcpy (p, " -- ");
+      p += 4;
 
       /* Copy in the string.  */
       if (posix_pedantic)
-       {
-         memcpy (p, posixref, sizeof (posixref) - 1);
-         p += sizeof (posixref) - 1;
-       }
+        {
+          memcpy (p, posixref, CSTRLEN (posixref));
+          p += CSTRLEN (posixref);
+        }
       else
-       {
-         memcpy (p, ref, sizeof (ref) - 1);
-         p += sizeof (ref) - 1;
-       }
-    }
-  else if (p == &flagstring[1])
-    {
-      words = 0;
-      --p;
+        {
+          memcpy (p, ref, CSTRLEN (ref));
+          p += CSTRLEN (ref);
+        }
     }
-  else if (p[-1] == '-')
-    /* Kill the final space and dash.  */
-    p -= 2;
-  /* Terminate the string.  */
-  *p = '\0';
 
-  /* If there are switches, omit the leading dash unless it is a single long
-     option with two leading dashes.  */
-  if (flagstring[0] == '-' && flagstring[1] != '-')
+  /* If there is a leading dash, omit it.  */
+  if (flagstring[0] == '-')
     ++flagstring;
 
-  v = define_variable_cname ("MAKEFLAGS", flagstring,
-                             /* This used to use o_env, but that lost when a
-                                makefile defined MAKEFLAGS.  Makefiles set
-                                MAKEFLAGS to add switches, but we still want
-                                to redefine its value with the full set of
-                                switches.  Of course, an override or command
-                                definition will still take precedence.  */
-                             o_file, 1);
-
-  if (! all)
-    /* The first time we are called, set MAKEFLAGS to always be exported.
-       We should not do this again on the second call, because that is
-       after reading makefiles which might have done `unexport MAKEFLAGS'. */
-    v->export = v_export;
-
-  return v->value;
+  /* This used to use o_env, but that lost when a makefile defined MAKEFLAGS.
+     Makefiles set MAKEFLAGS to add switches, but we still want to redefine
+     its value with the full set of switches.  Then we used o_file, but that
+     lost when users added -e, causing a previous MAKEFLAGS env. var. to take
+     precedence over the new one.  Of course, an override or command
+     definition will still take precedence.  */
+  return define_variable_cname ("MAKEFLAGS", flagstring,
+                                env_overrides ? o_env_override : o_file, 1);
 }
 \f
 /* Print version information.  */
@@ -3059,9 +3258,10 @@ print_version (void)
   /* Print this untranslated.  The coding standards recommend translating the
      (C) to the copyright symbol, but this string is going to change every
      year, and none of the rest of it should be translated (including the
-     word "Copyright", so it hardly seems worth it.  */
+     word "Copyright"), so it hardly seems worth it.  */
 
-  printf ("%sCopyright (C) 2010  Free Software Foundation, Inc.\n", precede);
+  printf ("%sCopyright (C) 1988-2013 Free Software Foundation, Inc.\n",
+          precede);
 
   printf (_("%sLicense GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n\
 %sThis is free software: you are free to change and redistribute it.\n\
@@ -3071,7 +3271,7 @@ print_version (void)
   printed_version = 1;
 
   /* Flush stdout so the user doesn't have to wait to see the
-     version information while things are thought about.  */
+     version information while make thinks about things.  */
   fflush (stdout);
 }
 
@@ -3080,9 +3280,10 @@ print_version (void)
 static void
 print_data_base ()
 {
-  time_t when;
+  time_t when = time ((time_t *) 0);
+
+  print_version ();
 
-  when = time ((time_t *) 0);
   printf (_("\n# Make data base, printed on %s"), ctime (&when));
 
   print_variable_data_base ();
@@ -3099,27 +3300,37 @@ print_data_base ()
 static void
 clean_jobserver (int status)
 {
-  char token = '+';
-
   /* Sanity: have we written all our jobserver tokens back?  If our
      exit status is 2 that means some kind of syntax error; we might not
      have written all our tokens so do that now.  If tokens are left
      after any other error code, that's bad.  */
 
+#ifdef WINDOWS32
+  if (has_jobserver_semaphore () && jobserver_tokens)
+#else
+  char token = '+';
+
   if (job_fds[0] != -1 && jobserver_tokens)
+#endif
     {
       if (status != 2)
         error (NILF,
                "INTERNAL: Exiting with %u jobserver tokens (should be 0)!",
                jobserver_tokens);
       else
-        while (jobserver_tokens--)
+        /* Don't write back the "free" token */
+        while (--jobserver_tokens)
           {
+#ifdef WINDOWS32
+            if (! release_jobserver_semaphore ())
+              perror_with_name ("release_jobserver_semaphore", "");
+#else
             int r;
 
             EINTRLOOP (r, write (job_fds[1], &token, 1));
             if (r != 1)
               perror_with_name ("write", "");
+#endif
           }
     }
 
@@ -3131,18 +3342,27 @@ clean_jobserver (int status)
       /* We didn't write one for ourself, so start at 1.  */
       unsigned int tcnt = 1;
 
+#ifdef WINDOWS32
+      while (acquire_jobserver_semaphore ())
+          ++tcnt;
+#else
       /* Close the write side, so the read() won't hang.  */
       close (job_fds[1]);
 
       while (read (job_fds[0], &token, 1) == 1)
         ++tcnt;
+#endif
 
       if (tcnt != master_job_slots)
         error (NILF,
                "INTERNAL: Exiting with %u jobserver tokens available; should be %u!",
                tcnt, master_job_slots);
 
+#ifdef WINDOWS32
+      free_jobserver_semaphore ();
+#else
       close (job_fds[0]);
+#endif
 
       /* Clean out jobserver_fds so we don't pass this information to any
          sub-makes.  Also reset job_slots since it will be put on the command
@@ -3172,12 +3392,12 @@ die (int status)
       dying = 1;
 
       if (print_version_flag)
-       print_version ();
+        print_version ();
 
       /* Wait for children to die.  */
       err = (status != 0);
       while (job_slots_used > 0)
-       reap_children (1, err);
+        reap_children (1, err);
 
       /* Let the remote job module clean up its state.  */
       remote_cleanup ();
@@ -3186,80 +3406,34 @@ die (int status)
       remove_intermediates (0);
 
       if (print_data_base_flag)
-       print_data_base ();
+        print_data_base ();
 
-      verify_file_data_base ();
+      if (verify_flag)
+        verify_file_data_base ();
 
       clean_jobserver (status);
 
+      if (output_context)
+        {
+          assert (output_context == &make_sync);
+          OUTPUT_UNSET ();
+          output_close (&make_sync);
+        }
+
+      output_close (NULL);
+
       /* Try to move back to the original directory.  This is essential on
-        MS-DOS (where there is really only one process), and on Unix it
-        puts core files in the original directory instead of the -C
-        directory.  Must wait until after remove_intermediates(), or unlinks
+         MS-DOS (where there is really only one process), and on Unix it
+         puts core files in the original directory instead of the -C
+         directory.  Must wait until after remove_intermediates(), or unlinks
          of relative pathnames fail.  */
       if (directory_before_chdir != 0)
         {
           /* If it fails we don't care: shut up GCC.  */
-          int _x;
+          int _x UNUSED;
           _x = chdir (directory_before_chdir);
         }
-
-      log_working_directory (0);
     }
 
   exit (status);
 }
-\f
-/* Write a message indicating that we've just entered or
-   left (according to ENTERING) the current directory.  */
-
-void
-log_working_directory (int entering)
-{
-  static int entered = 0;
-
-  /* Print nothing without the flag.  Don't print the entering message
-     again if we already have.  Don't print the leaving message if we
-     haven't printed the entering message.  */
-  if (! print_directory_flag || entering == entered)
-    return;
-
-  entered = entering;
-
-  if (print_data_base_flag)
-    fputs ("# ", stdout);
-
-  /* Use entire sentences to give the translators a fighting chance.  */
-
-  if (makelevel == 0)
-    if (starting_directory == 0)
-      if (entering)
-        printf (_("%s: Entering an unknown directory\n"), program);
-      else
-        printf (_("%s: Leaving an unknown directory\n"), program);
-    else
-      if (entering)
-        printf (_("%s: Entering directory `%s'\n"),
-                program, starting_directory);
-      else
-        printf (_("%s: Leaving directory `%s'\n"),
-                program, starting_directory);
-  else
-    if (starting_directory == 0)
-      if (entering)
-        printf (_("%s[%u]: Entering an unknown directory\n"),
-                program, makelevel);
-      else
-        printf (_("%s[%u]: Leaving an unknown directory\n"),
-                program, makelevel);
-    else
-      if (entering)
-        printf (_("%s[%u]: Entering directory `%s'\n"),
-                program, makelevel, starting_directory);
-      else
-        printf (_("%s[%u]: Leaving directory `%s'\n"),
-                program, makelevel, starting_directory);
-
-  /* Flush stdout to be sure this comes before any stderr output.  */
-  fflush (stdout);
-}