From e56aad40611fb5c014487c242e7393c84135d88f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 27 Apr 2013 19:12:01 +0300 Subject: Support .ONESHELL on MS-Windows, for default Windows shells. 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 | 7 ++++ job.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ read.c | 2 +- 3 files changed, 107 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 93fa286..ad9b9d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2013-04-27 Eli Zaretskii + + * 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 * job.c: Fix compilation error on GNU/Linux due to "label at end diff --git a/job.c b/job.c index 4d0120e..61568f9 100644 --- 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 86b9fc4..b74e4a9 100644 --- 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 -- cgit v1.2.3