Support .ONESHELL on MS-Windows, for default Windows shells.
authorEli Zaretskii <eliz@gnu.org>
Sat, 27 Apr 2013 16:12:01 +0000 (19:12 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 27 Apr 2013 16:12:01 +0000 (19:12 +0300)
 read.c (record_files): Pay attention to .ONESHELL in MS-Windows.
 job.c (construct_command_argv_internal): Support .ONESHELL on
 MS-Windows, when the shell is not a Unixy shell.

ChangeLog
job.c
read.c

index 93fa286ab84ad08e1c767fe20123c927472eba7d..ad9b9d43e2f8990318d1267932ca3d02c547f646 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2013-04-27  Eli Zaretskii  <eliz@gnu.org>
+
+       * read.c (record_files): Pay attention to .ONESHELL in MS-Windows.
+
+       * job.c (construct_command_argv_internal): Support .ONESHELL on
+       MS-Windows, when the shell is not a Unixy shell.
+
 2013-04-27  Eli Zaretskii  <eliz@gnu.org>
 
        * job.c: Fix compilation error on GNU/Linux due to "label at end
diff --git a/job.c b/job.c
index 4d0120e648717c6645fe72884ce9830a378f4d22..61568f940d3b35a776bd2b024cfb4713997a777c 100644 (file)
--- a/job.c
+++ b/job.c
@@ -3232,7 +3232,12 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
 #if defined __MSDOS__ || defined (__EMX__)
        if (unixy_shell)     /* the test is complicated and we already did it */
 #else
-       if (is_bourne_compatible_shell(shell))
+       if (is_bourne_compatible_shell(shell)
+#ifdef WINDOWS32
+           /* If we didn't find any sh.exe, don't behave is if we did!  */
+           && !no_default_sh_exe
+#endif
+           )
 #endif
           {
             const char *f = line;
@@ -3267,31 +3272,103 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
                   }
               }
             *t = '\0';
-          }
 
-        /* Create an argv list for the shell command line.  */
-        {
-          int n = 0;
+           /* Create an argv list for the shell command line.  */
+           {
+             int n = 0;
 
-          new_argv = xmalloc ((4 + sflags_len/2) * sizeof (char *));
-          new_argv[n++] = xstrdup (shell);
+             new_argv = xmalloc ((4 + sflags_len/2) * sizeof (char *));
+             new_argv[n++] = xstrdup (shell);
 
-          /* Chop up the shellflags (if any) and assign them.  */
-          if (! shellflags)
-            new_argv[n++] = xstrdup ("");
-          else
-            {
-              const char *s = shellflags;
-              char *t;
-              unsigned int len;
-              while ((t = find_next_token (&s, &len)) != 0)
-                new_argv[n++] = xstrndup (t, len);
-            }
+             /* Chop up the shellflags (if any) and assign them.  */
+             if (! shellflags)
+               new_argv[n++] = xstrdup ("");
+             else
+               {
+                 const char *s = shellflags;
+                 char *t;
+                 unsigned int len;
+                 while ((t = find_next_token (&s, &len)) != 0)
+                   new_argv[n++] = xstrndup (t, len);
+               }
 
-          /* Set the command to invoke.  */
-          new_argv[n++] = line;
-          new_argv[n++] = NULL;
-        }
+             /* Set the command to invoke.  */
+             new_argv[n++] = line;
+             new_argv[n++] = NULL;
+           }
+          }
+#ifdef WINDOWS32
+       else    /* non-Posix shell */
+         {
+            const char *f = line;
+            char *t = line;
+           char *tstart = t;
+           int temp_fd;
+           FILE* batch = NULL;
+           int id = GetCurrentProcessId();
+           PATH_VAR(fbuf);
+
+           /* Generate a file name for the temporary batch file.  */
+           sprintf(fbuf, "make%d", id);
+           *batch_filename = create_batch_file (fbuf, 0, &temp_fd);
+           DB (DB_JOBS, (_("Creating temporary batch file %s\n"),
+                         *batch_filename));
+
+           /* Create a FILE object for the batch file, and write to it the
+              commands to be executed.  Put the batch file in TEXT mode.  */
+           _setmode (temp_fd, _O_TEXT);
+           batch = _fdopen (temp_fd, "wt");
+           fputs ("@echo off\n", batch);
+           DB (DB_JOBS, (_("Batch file contents:\n\t@echo off\n")));
+
+            /* Copy the recipe, removing and ignoring interior prefix chars
+               [@+-]: they're meaningless in .ONESHELL mode.  */
+            while (*f != '\0')
+              {
+                /* This is the start of a new recipe line.
+                   Skip whitespace and prefix characters.  */
+                while (isblank (*f) || *f == '-' || *f == '@' || *f == '+')
+                  ++f;
+
+                /* Copy until we get to the next logical recipe line.  */
+                while (*f != '\0')
+                  {
+                   /* Remove the escaped newlines in the command, and
+                      the whitespace that follows them.  Windows
+                      shells cannot handle escaped newlines.  */
+                   if (*f == '\\' && f[1] == '\n')
+                     {
+                       f += 2;
+                       while (isblank (*f))
+                         ++f;
+                     }
+                    *(t++) = *(f++);
+                   /* On an unescaped newline, we're done with this
+                      line.  */
+                   if (f[-1] == '\n')
+                     break;
+                  }
+               /* Write another line into the batch file.  */
+               if (t > tstart)
+                 {
+                   int c = *t;
+                   *t = '\0';
+                   fputs (tstart, batch);
+                   DB (DB_JOBS, ("\t%s", tstart));
+                   tstart = t;
+                   *t = c;
+                 }
+             }
+           DB (DB_JOBS, ("\n"));
+           fclose (batch);
+
+           /* Create an argv list for the shell command line that
+              will run the batch file.  */
+           new_argv = xmalloc (2 * sizeof (char *));
+           new_argv[0] = xstrdup (*batch_filename);
+           new_argv[1] = NULL;
+         }
+#endif  /* WINDOWS32 */
        return new_argv;
       }
 
diff --git a/read.c b/read.c
index 86b9fc4ed015889210115e9377d0959a35d14787..b74e4a9a5e27b8bcd51f3364a9085a59bb28de1f 100644 (file)
--- a/read.c
+++ b/read.c
@@ -2048,7 +2048,7 @@ record_files (struct nameseq *filenames, const char *pattern,
         }
       else if (streq (name, ".SECONDEXPANSION"))
         second_expansion = 1;
-#if !defined(WINDOWS32) && !defined (__MSDOS__) && !defined (__EMX__)
+#if !defined (__MSDOS__) && !defined (__EMX__)
       else if (streq (name, ".ONESHELL"))
         one_shell = 1;
 #endif