core/make/upstream-fixes-20221116.patch

1214 lines
39 KiB
Diff
Raw Normal View History

diff --git a/src/config.h.W32 b/src/config.h.W32
index 1a03a041..369e897d 100644
--- a/src/config.h.W32
+++ b/src/config.h.W32
@@ -344,6 +344,14 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
/* Define to 1 if you have the `strtoll' function. */
#define HAVE_STRTOLL 1
+#ifdef __TINYC__
+# ifndef strtoll
+# define strtoll _strtoi64
+# endif
+# ifndef strtoull
+# define strtoull _strtoui64
+# endif
+#endif
/* Define to 1 if `d_type' is a member of `struct dirent'. */
/* SV 57152: MinGW64 version of dirent doesn't support d_type. */
diff --git a/src/dir.c b/src/dir.c
index b47e94fe..1e6e7397 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -456,7 +456,7 @@ dirfile_hash_cmp (const void *xv, const void *yv)
#define DIRFILE_BUCKETS 107
#endif
-static int dir_contents_file_exists_p (struct directory_contents *dir,
+static int dir_contents_file_exists_p (struct directory *dir,
const char *filename);
static struct directory *find_directory (const char *name);
@@ -623,7 +623,7 @@ find_directory (const char *name)
if (open_directories == MAX_OPEN_DIRECTORIES)
/* We have too many directories open already.
Read the entire directory and then close it. */
- dir_contents_file_exists_p (dc, 0);
+ dir_contents_file_exists_p (dir, 0);
}
}
@@ -634,17 +634,18 @@ find_directory (const char *name)
FILENAME must contain no slashes. */
static int
-dir_contents_file_exists_p (struct directory_contents *dir,
+dir_contents_file_exists_p (struct directory *dir,
const char *filename)
{
struct dirfile *df;
struct dirent *d;
+ struct directory_contents *dc = dir->contents;
#ifdef WINDOWS32
struct stat st;
int rehash = 0;
#endif
- if (dir == 0 || dir->dirfiles.ht_vec == 0)
+ if (dc == 0 || dc->dirfiles.ht_vec == 0)
/* The directory could not be stat'd or opened. */
return 0;
@@ -671,7 +672,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
}
dirfile_key.name = filename;
dirfile_key.length = strlen (filename);
- df = hash_find_item (&dir->dirfiles, &dirfile_key);
+ df = hash_find_item (&dc->dirfiles, &dirfile_key);
if (df)
return !df->impossible;
}
@@ -679,7 +680,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
/* The file was not found in the hashed list.
Try to read the directory further. */
- if (dir->dirstream == 0)
+ if (dc->dirstream == 0)
{
#ifdef WINDOWS32
/*
@@ -687,17 +688,17 @@ dir_contents_file_exists_p (struct directory_contents *dir,
* filesystems force a rehash always as mtime does not change
* on directories (ugh!).
*/
- if (dir->path_key)
+ if (dc->path_key)
{
- if ((dir->fs_flags & FS_FAT) != 0)
+ if ((dc->fs_flags & FS_FAT) != 0)
{
- dir->mtime = time ((time_t *) 0);
+ dc->mtime = time ((time_t *) 0);
rehash = 1;
}
- else if (stat (dir->path_key, &st) == 0 && st.st_mtime > dir->mtime)
+ else if (stat (dc->path_key, &st) == 0 && st.st_mtime > dc->mtime)
{
/* reset date stamp to show most recent re-process. */
- dir->mtime = st.st_mtime;
+ dc->mtime = st.st_mtime;
rehash = 1;
}
@@ -706,8 +707,8 @@ dir_contents_file_exists_p (struct directory_contents *dir,
return 0;
/* make sure directory can still be opened; if not return. */
- dir->dirstream = opendir (dir->path_key);
- if (!dir->dirstream)
+ dc->dirstream = opendir (dc->path_key);
+ if (!dc->dirstream)
return 0;
}
else
@@ -723,11 +724,11 @@ dir_contents_file_exists_p (struct directory_contents *dir,
struct dirfile dirfile_key;
struct dirfile **dirfile_slot;
- ENULLLOOP (d, readdir (dir->dirstream));
+ ENULLLOOP (d, readdir (dc->dirstream));
if (d == 0)
{
if (errno)
- pfatal_with_name ("INTERNAL: readdir");
+ OSS (fatal, NILF, "readdir %s: %s", dir->name, strerror (errno));
break;
}
@@ -747,7 +748,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
len = NAMLEN (d);
dirfile_key.name = d->d_name;
dirfile_key.length = len;
- dirfile_slot = (struct dirfile **) hash_find_slot (&dir->dirfiles, &dirfile_key);
+ dirfile_slot = (struct dirfile **) hash_find_slot (&dc->dirfiles, &dirfile_key);
#ifdef WINDOWS32
/*
* If re-reading a directory, don't cache files that have
@@ -768,7 +769,7 @@ dir_contents_file_exists_p (struct directory_contents *dir,
#endif
df->length = len;
df->impossible = 0;
- hash_insert_at (&dir->dirfiles, df, dirfile_slot);
+ hash_insert_at (&dc->dirfiles, df, dirfile_slot);
}
/* Check if the name matches the one we're searching for. */
if (filename != 0 && patheq (d->d_name, filename))
@@ -777,12 +778,13 @@ dir_contents_file_exists_p (struct directory_contents *dir,
/* If the directory has been completely read in,
close the stream and reset the pointer to nil. */
- if (d == 0)
+ if (d == NULL)
{
--open_directories;
- closedir (dir->dirstream);
- dir->dirstream = 0;
+ closedir (dc->dirstream);
+ dc->dirstream = NULL;
}
+
return 0;
}
@@ -794,15 +796,10 @@ int
dir_file_exists_p (const char *dirname, const char *filename)
{
#ifdef VMS
- if ((filename != NULL) && (dirname != NULL))
- {
- int want_vmsify;
- want_vmsify = (strpbrk (dirname, ":<[") != NULL);
- if (want_vmsify)
- filename = vmsify (filename, 0);
- }
+ if (filename && dirname && strpbrk (dirname, ":<[") != NULL)
+ filename = vmsify (filename, 0);
#endif
- return dir_contents_file_exists_p (find_directory (dirname)->contents,
+ return dir_contents_file_exists_p (find_directory (dirname),
filename);
}
@@ -1225,7 +1222,7 @@ open_dirstream (const char *directory)
/* Read all the contents of the directory now. There is no benefit
in being lazy, since glob will want to see every file anyway. */
- dir_contents_file_exists_p (dir->contents, 0);
+ dir_contents_file_exists_p (dir, 0);
new = xmalloc (sizeof (struct dirstream));
new->contents = dir->contents;
diff --git a/src/function.c b/src/function.c
index f0ef3434..e4a3af86 100644
--- a/src/function.c
+++ b/src/function.c
@@ -2801,7 +2801,7 @@ define_new_function (const floc *flocp, const char *name,
_("Invalid maximum argument count (%u) for function %s"), max, name);
ent = xmalloc (sizeof (struct function_table_entry));
- ent->name = name;
+ ent->name = strcache_add (name);
ent->len = (unsigned char) len;
ent->minimum_args = (unsigned char) min;
ent->maximum_args = (unsigned char) max;
diff --git a/src/hash.c b/src/hash.c
index 5d7ea81b..d1652f84 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -361,7 +361,7 @@ round_up_2 (unsigned long n)
#define sum_get_unaligned_32(r, p) \
do { \
unsigned int val; \
- memcpy(&val, (p), 4); \
+ memcpy (&val, (p), 4); \
r += val; \
} while(0);
@@ -413,13 +413,16 @@ jhash(unsigned const char *k, int length)
#define UINTSZ sizeof (unsigned int)
#ifdef WORDS_BIGENDIAN
-/* The ifs are ordered from the first byte in memory to the last. */
+/* The ifs are ordered from the first byte in memory to the last.
+ Help the compiler optimize by using static memcpy length. */
#define sum_up_to_nul(r, p, plen, flag) \
do { \
unsigned int val = 0; \
size_t pn = (plen); \
- size_t n = pn < UINTSZ ? pn : UINTSZ; \
- memcpy (&val, (p), n); \
+ if (pn >= UINTSZ) \
+ memcpy (&val, (p), UINTSZ); \
+ else \
+ memcpy (&val, (p), pn); \
if ((val & 0xFF000000) == 0) \
flag = 1; \
else if ((val & 0xFF0000) == 0) \
@@ -432,13 +435,16 @@ jhash(unsigned const char *k, int length)
#else
/* First detect the presence of zeroes. If there is none, we can
sum the 4 bytes directly. Otherwise, the ifs are ordered as in the
- big endian case, from the first byte in memory to the last. */
+ big endian case, from the first byte in memory to the last.
+ Help the compiler optimize by using static memcpy length. */
#define sum_up_to_nul(r, p, plen, flag) \
do { \
unsigned int val = 0; \
size_t pn = (plen); \
- size_t n = pn < UINTSZ ? pn : UINTSZ; \
- memcpy (&val, (p), n); \
+ if (pn >= UINTSZ) \
+ memcpy (&val, (p), UINTSZ); \
+ else \
+ memcpy (&val, (p), pn); \
flag = ((val - 0x01010101) & ~val) & 0x80808080; \
if (!flag) \
r += val; \
diff --git a/src/main.c b/src/main.c
index eec93656..b31ddd4d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1182,11 +1182,6 @@ main (int argc, char **argv, char **envp)
/* Useful for attaching debuggers, etc. */
SPIN ("main-entry");
- /* Don't die if our stdout sends us SIGPIPE. */
-#ifdef SIGPIPE
- bsd_signal (SIGPIPE, SIG_IGN);
-#endif
-
#ifdef HAVE_ATEXIT
if (ANY_SET (check_io_state (), IO_STDOUT_OK))
atexit (close_stdout);
@@ -1264,6 +1259,9 @@ main (int argc, char **argv, char **envp)
#endif
#ifdef SIGQUIT
FATAL_SIG (SIGQUIT);
+#endif
+#ifdef SIGPIPE
+ FATAL_SIG (SIGPIPE);
#endif
FATAL_SIG (SIGINT);
FATAL_SIG (SIGTERM);
@@ -1505,7 +1503,7 @@ main (int argc, char **argv, char **envp)
/* If this is MAKE_RESTARTS, check to see if the "already printed
the enter statement" flag is set. */
- if (len == 13 && memcmp (envp[i], STRING_SIZE_TUPLE ("MAKE_RESTARTS")) == 0)
+ if (len == 13 && memcmp (envp[i], "MAKE_RESTARTS", CSTRLEN ("MAKE_RESTARTS")) == 0)
{
if (*ep == '-')
{
@@ -1930,6 +1928,9 @@ main (int argc, char **argv, char **envp)
_("Makefile from standard input specified twice"));
outfile = get_tmpfile (&newnm);
+ if (!outfile)
+ O (fatal, NILF,
+ _("cannot store makefile from stdin to a temporary file"));
while (!feof (stdin) && ! ferror (stdin))
{
diff --git a/src/misc.c b/src/misc.c
index 8264fe9f..00dce749 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -20,8 +20,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
#include "os.h"
#include "debug.h"
-/* GNU make no longer supports pre-ANSI89 environments. */
-
+#include <assert.h>
#include <stdarg.h>
#ifdef WINDOWS32
@@ -650,11 +649,19 @@ get_tmppath ()
# ifdef HAVE_MKTEMP
path = get_tmptemplate ();
if (*mktemp (path) == '\0')
- pfatal_with_name ("mktemp");
+ {
+ OSS (error, NILF,
+ _("cannot generate temp path from %s: %s"), path, strerror (errno));
+ return NULL;
+ }
# else
path = xmalloc (L_tmpnam + 1);
if (tmpnam (path) == NULL)
- pfatal_with_name ("tmpnam");
+ {
+ OS (error, NILF,
+ _("cannot generate temp name: %s"), strerror (errno));
+ return NULL;
+ }
# endif
return path;
@@ -662,7 +669,9 @@ get_tmppath ()
#endif
/* Generate a temporary file and return an fd for it. If name is NULL then
- the temp file is anonymous and will be deleted when the process exits. */
+ the temp file is anonymous and will be deleted when the process exits. If
+ name is not null then *name will point to an allocated buffer, or set to
+ NULL on failure. */
int
get_tmpfd (char **name)
{
@@ -670,9 +679,11 @@ get_tmpfd (char **name)
char *tmpnm;
mode_t mask;
- /* If there's an os-specific way to get an anoymous temp file use it. */
- if (!name)
+ if (name)
+ *name = NULL;
+ else
{
+ /* If there's an os-specific way to get an anoymous temp file use it. */
fd = os_anontmp ();
if (fd >= 0)
return fd;
@@ -689,13 +700,19 @@ get_tmpfd (char **name)
EINTRLOOP (fd, mkstemp (tmpnm));
#else
tmpnm = get_tmppath ();
+ if (!tmpnm)
+ return -1;
/* Can't use mkstemp(), but try to guard against a race condition. */
EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
#endif
if (fd < 0)
- OSS (fatal, NILF,
- _("create temporary file %s: %s"), tmpnm, strerror (errno));
+ {
+ OSS (error, NILF,
+ _("cannot create temporary file %s: %s"), tmpnm, strerror (errno));
+ free (tmpnm);
+ return -1;
+ }
if (name)
*name = tmpnm;
@@ -704,8 +721,8 @@ get_tmpfd (char **name)
int r;
EINTRLOOP (r, unlink (tmpnm));
if (r < 0)
- OSS (fatal, NILF,
- _("unlink temporary file %s: %s"), tmpnm, strerror (errno));
+ OSS (error, NILF,
+ _("cannot unlink temporary file %s: %s"), tmpnm, strerror (errno));
free (tmpnm);
}
@@ -715,8 +732,8 @@ get_tmpfd (char **name)
}
/* Return a FILE* for a temporary file, opened in the safest way possible.
- Set name to point to an allocated buffer containing the name of the file.
- Note, this cannot be NULL! */
+ Set name to point to an allocated buffer containing the name of the file,
+ or NULL on failure. Note, name cannot be NULL! */
FILE *
get_tmpfile (char **name)
{
@@ -725,26 +742,37 @@ get_tmpfile (char **name)
FILE *file;
#if defined(HAVE_FDOPEN)
- int fd = get_tmpfd (name);
+ int fd;
+ assert (name);
+ fd = get_tmpfd (name);
+ if (fd < 0)
+ return NULL;
+ assert (*name);
ENULLLOOP (file, fdopen (fd, tmpfile_mode));
if (file == NULL)
- OSS (fatal, NILF,
+ OSS (error, NILF,
_("fdopen: temporary file %s: %s"), *name, strerror (errno));
#else
/* Preserve the current umask, and set a restrictive one for temp files. */
mode_t mask = umask (0077);
- int err;
+ assert (name);
*name = get_tmppath ();
+ if (!*name)
+ return NULL;
/* Although this fopen is insecure, it is executed only on non-fdopen
platforms, which should be a rarity nowadays. */
ENULLLOOP (file, fopen (*name, tmpfile_mode));
if (file == NULL)
- OSS (fatal, NILF,
- _("fopen: temporary file %s: %s"), *name, strerror (errno));
+ {
+ OSS (error, NILF,
+ _("fopen: temporary file %s: %s"), *name, strerror (errno));
+ free (*name);
+ *name = NULL;
+ }
umask (mask);
#endif
diff --git a/src/output.c b/src/output.c
index 43eb2f06..22387dff 100644
--- a/src/output.c
+++ b/src/output.c
@@ -248,6 +248,9 @@ setup_tmpfile (struct output *out)
/* If we failed to create a temp file, disable output sync going forward. */
error:
+ O (error, NILF,
+ _("cannot open output-sync lock file, suppressing output-sync."));
+
output_close (out);
output_sync = OUTPUT_SYNC_NONE;
osync_clear ();
diff --git a/src/posixos.c b/src/posixos.c
index 44aeb346..78358dd8 100644
--- a/src/posixos.c
+++ b/src/posixos.c
@@ -167,12 +167,12 @@ jobserver_setup (int slots, const char *style)
hang until the write side is open. */
EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY|O_NONBLOCK));
if (job_fds[0] < 0)
- OSS (fatal, NILF, _("Cannot open jobserver %s: %s"),
+ OSS (fatal, NILF, _("cannot open jobserver %s: %s"),
fifo_name, strerror (errno));
EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));
if (job_fds[0] < 0)
- OSS (fatal, NILF, _("Cannot open jobserver %s: %s"),
+ OSS (fatal, NILF, _("cannot open jobserver %s: %s"),
fifo_name, strerror (errno));
js_type = js_fifo;
@@ -183,7 +183,7 @@ jobserver_setup (int slots, const char *style)
if (js_type == js_none)
{
if (style && strcmp (style, "pipe") != 0)
- OS (fatal, NILF, _("Unknown jobserver auth style '%s'"), style);
+ OS (fatal, NILF, _("unknown jobserver auth style '%s'"), style);
EINTRLOOP (r, pipe (job_fds));
if (r < 0)
@@ -229,14 +229,19 @@ jobserver_parse_auth (const char *auth)
EINTRLOOP (job_fds[0], open (fifo_name, O_RDONLY));
if (job_fds[0] < 0)
- OSS (fatal, NILF,
- _("Cannot open jobserver %s: %s"), fifo_name, strerror (errno));
+ {
+ OSS (error, NILF,
+ _("cannot open jobserver %s: %s"), fifo_name, strerror (errno));
+ return 0;
+ }
EINTRLOOP (job_fds[1], open (fifo_name, O_WRONLY));
- if (job_fds[0] < 0)
- OSS (fatal, NILF,
- _("Cannot open jobserver %s: %s"), fifo_name, strerror (errno));
-
+ if (job_fds[1] < 0)
+ {
+ OSS (error, NILF,
+ _("cannot open jobserver %s: %s"), fifo_name, strerror (errno));
+ return 0;
+ }
js_type = js_fifo;
}
/* If not, it must be a simple pipe. */
@@ -867,12 +872,15 @@ os_anontmp ()
FILE *tfile;
ENULLLOOP (tfile, tmpfile ());
if (!tfile)
- pfatal_with_name ("tmpfile");
+ {
+ OS (error, NILF, "tmpfile: %s", strerror (errno));
+ return -1;
+ }
umask (mask);
EINTRLOOP (fd, dup (fileno (tfile)));
if (fd < 0)
- pfatal_with_name ("dup");
+ OS (error, NILF, "dup: %s", strerror (errno));
fclose (tfile);
}
#endif
diff --git a/src/read.c b/src/read.c
index 07431240..15f58ecf 100644
--- a/src/read.c
+++ b/src/read.c
@@ -1140,20 +1140,29 @@ eval (struct ebuffer *ebuf, int set_default)
p2 = next_token (variable_buffer);
- /* If the word we're looking at is EOL, see if there's _anything_
- on the line. If not, a variable expanded to nothing, so ignore
- it. If so, we can't parse this line so punt. */
+ /* If we're at EOL we didn't find a separator so we don't know what
+ kind of line this is. */
if (wtype == w_eol)
{
+ /* Ignore an empty line. */
if (*p2 == '\0')
continue;
- /* There's no need to be ivory-tower about this: check for
- one of the most common bugs found in makefiles... */
+ /* Check for spaces instead of TAB. */
if (cmd_prefix == '\t' && strneq (line, " ", 8))
O (fatal, fstart, _("missing separator (did you mean TAB instead of 8 spaces?)"));
- else
- O (fatal, fstart, _("missing separator"));
+
+ /* Check for conditionals without whitespace afterward.
+ We don't check ifdef/ifndef because there's no real way to miss
+ whitespace there. */
+ p2 = next_token (line);
+ if (strneq (p2, "if", 2) &&
+ ((strneq (&p2[2], "neq", 3) && !STOP_SET (p2[5], MAP_BLANK))
+ || (strneq (&p2[2], "eq", 2) && !STOP_SET (p2[4], MAP_BLANK))))
+ O (fatal, fstart, _("missing separator (ifeq/ifneq must be followed by whitespace)"));
+
+ /* No idea... */
+ O (fatal, fstart, _("missing separator"));
}
{
diff --git a/src/w32/w32os.c b/src/w32/w32os.c
index 9c5dec24..213bbf12 100644
--- a/src/w32/w32os.c
+++ b/src/w32/w32os.c
@@ -216,12 +216,12 @@ jobserver_setup (int slots, const char *style)
/* sub_proc.c is limited in the number of objects it can wait for. */
if (style && strcmp (style, "sem") != 0)
- OS (fatal, NILF, _("Unknown jobserver auth style '%s'"), style);
+ OS (fatal, NILF, _("unknown jobserver auth style '%s'"), style);
if (slots > process_table_usable_size())
{
slots = process_table_usable_size();
- DB (DB_JOBS, (_("Jobserver slots limited to %d\n"), slots));
+ DB (DB_JOBS, (_("jobserver slots limited to %d\n"), slots));
}
sprintf (jobserver_semaphore_name, "gmake_semaphore_%d", _getpid ());
@@ -255,10 +255,12 @@ jobserver_parse_auth (const char *auth)
{
DWORD err = GetLastError ();
const char *estr = map_windows32_error_to_string (err);
- fatal (NILF, strlen (auth) + INTSTR_LENGTH + strlen (estr),
- _("internal error: unable to open jobserver semaphore '%s': (Error %ld: %s)"),
+ error (NILF, strlen (auth) + INTSTR_LENGTH + strlen (estr),
+ _("unable to open jobserver semaphore '%s': (Error %ld: %s)"),
auth, err, estr);
+ return 0;
}
+
DB (DB_JOBS, (_("Jobserver client (semaphore %s)\n"), auth));
return 1;
diff --git a/tests/run_make_tests.pl b/tests/run_make_tests.pl
index 70dd1821..5fc37595 100644
--- a/tests/run_make_tests.pl
+++ b/tests/run_make_tests.pl
@@ -185,7 +185,6 @@ sub subst_make_string
s/#PERL#/$perl_name/g;
s/#PWD#/$cwdpath/g;
s/#WORK#/$workdir/g;
- # If we're using a shell
s/#HELPER#/$perl_name $helptool/g;
return $_;
}
diff --git a/tests/scripts/features/jobserver b/tests/scripts/features/jobserver
index 8ecbe345..e12facf0 100644
--- a/tests/scripts/features/jobserver
+++ b/tests/scripts/features/jobserver
@@ -14,6 +14,7 @@ if (!$parallel_jobs) {
# Shorthand
my $np = '--no-print-directory';
+my $j1err = "warning: jobserver unavailable: using -j1. Add '+' to parent make rule.";
# Simple test of MAKEFLAGS settings
run_make_test(q!
@@ -90,7 +91,7 @@ if ($port_type ne 'W32') {
default: ; @ #MAKEPATH# -f Makefile2
!,
"--jobserver-style=pipe -j2 $np",
-"#MAKE#[1]: warning: jobserver unavailable: using -j1. Add '+' to parent make rule.
+"#MAKE#[1]: $j1err
#MAKE#[1]: Nothing to be done for 'foo'.");
rmfiles('Makefile2');
@@ -98,15 +99,15 @@ default: ; @ #MAKEPATH# -f Makefile2
# For Windows and named pipes, we don't need to worry about recursion
if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) {
- create_file('Makefile2', "vpath %.c ../\n", "foo:\n");
+ create_file('Makefile2', "vpath %.c ../\n", "foo:\n");
- run_make_test(q!
+ run_make_test(q!
default: ; @ #MAKEPATH# -f Makefile2
!,
"-j2 $np",
"#MAKE#[1]: Nothing to be done for 'foo'.");
- rmfiles('Makefile2');
+ rmfiles('Makefile2');
}
# Ensure enter/leave directory messages appear before jobserver warnings
@@ -129,17 +130,17 @@ all: a
all a: ; @echo $@
!,
'--jobserver-style=foo -j8',
- "#MAKE#: *** Unknown jobserver auth style 'foo'. Stop.", 512);
-
-# sv 62908.
-# Test that when mkfifo fails, make switches to pipe and succeeds.
-# Force mkfifo to fail by attempting to create a fifo in a non existent
-# directory.
-# run_make_test does not allow matching a multiline pattern, therefore run the
-# test twice.
-# First time look for /$ERR_no_such_file/ to ensure mkfifo failed.
-# Second time look for /Nothing to be done/ to ensure make succeeded.
+ "#MAKE#: *** unknown jobserver auth style 'foo'. Stop.", 512);
+
if (exists $FEATURES{'jobserver-fifo'}) {
+ # sv 62908.
+ # Test that when mkfifo fails, make switches to pipe and succeeds.
+ # Force mkfifo to fail by attempting to create a fifo in a non existent
+ # directory.
+ # run_make_test does not allow matching a multiline pattern, therefore run
+ # the test twice.
+ # First time look for /$ERR_no_such_file/ to ensure mkfifo failed.
+ # Second time look for /Nothing to be done/ to ensure make succeeded.
$ENV{TMPDIR} = "nosuchdir";
run_make_test("all:\n", '-j2', "/$ERR_no_such_file/");
@@ -155,6 +156,10 @@ recurse: ; @$(MAKE) -f #MAKEFILE# all
all:;@echo "$$MAKEFLAGS"
!,
"-j2 --no-print-directory", "/--jobserver-auth=fifo:\\./");
+
+ # Verify we fall back to -j1 but continue, of the auth is bad.
+ $ENV{MAKEFLAGS} = '-j2 --jobserver-auth=fifo:nosuchfile';
+ run_make_test(q!all:;@echo hi!, "", "#MAKE#: cannot open jobserver nosuchfile: $ERR_no_such_file\n#MAKE#: $j1err\nhi\n");
}
1;
diff --git a/tests/scripts/features/output-sync b/tests/scripts/features/output-sync
index 13a54ca0..18c85c0a 100644
--- a/tests/scripts/features/output-sync
+++ b/tests/scripts/features/output-sync
@@ -360,11 +360,27 @@ use POSIX ();
# file.
run_make_test(q!
pid:=$(shell echo $$PPID)
-all:; @kill -TERM $(pid) && sleep 16
+all:; @#HELPER# term $(pid) sleep 10
!, '-O -j2', '/#MAKE#: \*\*\* \[#MAKEFILE#:3: all] Terminated/', POSIX::SIGTERM);
}
-
unlink($fout);
+
+# SV 63333. Test that make continues to run without output sync when we
+# cannot create a temporary file.
+# Create a non-writable temporary directory.
+# Run the test twice, because run_make_test cannot match a regex againt a
+# multiline input.
+my $tdir = 'test_tmp_dir';
+mkdir($tdir, 0500);
+$ENV{'TMPDIR'} = $tdir;
+
+run_make_test(q!
+all:; $(info hello, world)
+!, '-Orecurse', "/suppressing output-sync/");
+
+run_make_test(undef, '-Orecurse', "/#MAKE#: 'all' is up to date./");
+
+rmdir($tdir);
}
# This tells the test driver that the perl test script executed properly.
diff --git a/tests/scripts/features/temp_stdin b/tests/scripts/features/temp_stdin
index b06df53e..3bd53e02 100644
--- a/tests/scripts/features/temp_stdin
+++ b/tests/scripts/features/temp_stdin
@@ -71,7 +71,7 @@ run_make_test(q!
include bye.mk
pid:=$(shell echo $$PPID)
all:;
-bye.mk: force; @kill -TERM $(pid) && sleep 16
+bye.mk: force; @#HELPER# term $(pid) sleep 10
force:
!, '-f-', '/#MAKE#: \*\*\* \[#MAKEFILE#:5: bye.mk] Terminated/', POSIX::SIGTERM);
}
@@ -109,6 +109,21 @@ force:
@make_command = @make_orig;
unlink($makecopy);
rmdir($tmakedir);
+
+# SV 63333. Test that make exits with an error message if we cannot store a
+# makefile from stdin to a temporary file.
+# Create a non-writable temporary directory.
+
+my $tdir = 'test_tmp_dir';
+mkdir($tdir, 0500);
+$ENV{'TMPDIR'} = $tdir;
+close(STDIN);
+open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
+
+run_make_test(q!
+all:; $(info hello, world)
+!, '-f-', '/cannot store makefile from stdin to a temporary file. Stop./', 512);
+rmdir($tdir);
}
close(STDIN);
diff --git a/tests/scripts/misc/failure b/tests/scripts/misc/failure
new file mode 100644
index 00000000..edd90fbb
--- /dev/null
+++ b/tests/scripts/misc/failure
@@ -0,0 +1,49 @@
+# -*-perl-*-
+
+$description = "Test miscellaneous failures.";
+
+
+# Test that the "did you mean TAB" message is printed properly
+
+run_make_test(q!
+$x.
+!,
+ '', '#MAKEFILE#:2: *** missing separator. Stop.', 512);
+
+run_make_test(q!
+foo:
+ bar
+!,
+ '', '#MAKEFILE#:3: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.', 512);
+
+run_make_test(q!
+.RECIPEPREFIX = :
+foo:
+ bar
+!,
+ '', '#MAKEFILE#:4: *** missing separator. Stop.', 512);
+
+for my $kw ('eq', 'neq') {
+run_make_test(qq!
+if$kw(foo,bar)
+\$(error ouch)
+endif
+!,
+ '', '#MAKEFILE#:2: *** missing separator (ifeq/ifneq must be followed by whitespace). Stop.', 512);
+
+run_make_test(qq!
+if$kw
+\$(error ouch)
+endif
+!,
+ '', '#MAKEFILE#:2: *** invalid syntax in conditional. Stop.', 512);
+
+run_make_test(qq!
+if$kw blah
+\$(error ouch)
+endif
+!,
+ '', '#MAKEFILE#:2: *** invalid syntax in conditional. Stop.', 512);
+}
+
+1;
diff --git a/tests/scripts/variables/special b/tests/scripts/variables/special
index 68f3128c..abe9fc0c 100644
--- a/tests/scripts/variables/special
+++ b/tests/scripts/variables/special
@@ -122,26 +122,6 @@ reset-four \
: foo-three
: foo-four');
-# Test that the "did you mean TAB" message is printed properly
-
-run_make_test(q!
-$x.
-!,
- '', '#MAKEFILE#:2: *** missing separator. Stop.', 512);
-
-run_make_test(q!
-foo:
- bar
-!,
- '', '#MAKEFILE#:3: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.', 512);
-
-run_make_test(q!
-.RECIPEPREFIX = :
-foo:
- bar
-!,
- '', '#MAKEFILE#:4: *** missing separator. Stop.', 512);
-
1;
### Local Variables:
diff --git a/tests/test_driver.pl b/tests/test_driver.pl
index b64fffb6..efe4981d 100644
--- a/tests/test_driver.pl
+++ b/tests/test_driver.pl
@@ -806,12 +806,135 @@ sub error
die "$caller: $message";
}
+sub compare_answer_vms
+{
+ my ($kgo, $log) = @_;
+
+ # VMS has extra blank lines in output sometimes.
+ # Ticket #41760
+ $log =~ s/\n\n+/\n/gm;
+ $log =~ s/\A\n+//g;
+ return 1 if ($kgo eq $log);
+
+ # VMS adding a "Waiting for unfinished jobs..."
+ # Remove it for now to see what else is going on.
+ $log =~ s/^.+\*\*\* Waiting for unfinished jobs.+$//m;
+ $log =~ s/\n\n/\n/gm;
+ $log =~ s/^\n+//gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS wants target device to exist or generates an error,
+ # Some test tagets look like VMS devices and trip this.
+ $log =~ s/^.+\: no such device or address.*$//gim;
+ $log =~ s/\n\n/\n/gm;
+ $log =~ s/^\n+//gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS error message has a different case
+ $log =~ s/no such file /No such file /gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS is putting comas instead of spaces in output
+ $log =~ s/,/ /gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS Is sometimes adding extra leading spaces to output?
+ {
+ (my $mlog = $log) =~ s/^ +//gm;
+ return 1 if ($mlog eq $kgo);
+ }
+
+ # VMS port not handling POSIX encoded child status
+ # Translate error case it for now.
+ $log =~ s/0x1035a00a/1/gim;
+ return 1 if ($log =~ /\Q$kgo\E/i);
+
+ $log =~ s/0x1035a012/2/gim;
+ return 1 if ($log eq $kgo);
+
+ # Tests are using a UNIX null command, temp hack
+ # until this can be handled by the VMS port.
+ # ticket # 41761
+ $log =~ s/^.+DCL-W-NOCOMD.*$//gim;
+ $log =~ s/\n\n+/\n/gm;
+ $log =~ s/^\n+//gm;
+ return 1 if ($log eq $kgo);
+
+ # Tests are using exit 0;
+ # this generates a warning that should stop the make, but does not
+ $log =~ s/^.+NONAME-W-NOMSG.*$//gim;
+ $log =~ s/\n\n+/\n/gm;
+ $log =~ s/^\n+//gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS is sometimes adding single quotes to output?
+ $log =~ s/\'//gm;
+ return 1 if ($log eq $kgo);
+
+ # And missing an extra space in output
+ $kgo =~ s/\h\h+/ /gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS adding ; to end of some lines.
+ $log =~ s/;\n/\n/gm;
+ return 1 if ($log eq $kgo);
+
+ # VMS adding trailing space to end of some quoted lines.
+ $log =~ s/\h+\n/\n/gm;
+ return 1 if ($log eq $kgo);
+
+ # And VMS missing leading blank line
+ $kgo =~ s/\A\n//g;
+ return 1 if ($log eq $kgo);
+
+ # Unix double quotes showing up as single quotes on VMS.
+ $kgo =~ s/\"//g;
+ return 1 if ($log eq $kgo);
+
+ return 0;
+}
+
+sub compare_answer
+{
+ my ($kgo, $log) = @_;
+ my ($mkgo, $mlog);
+
+ # For make, get rid of any time skew error before comparing--too bad this
+ # has to go into the "generic" driver code :-/
+ $log =~ s/^.*modification time .*in the future.*\n//gm;
+ $log =~ s/^.*Clock skew detected.*\n//gm;
+ return 1 if ($log eq $kgo);
+
+ # Get rid of newline differences, forever
+ $kgo =~ s,\r\n,\n,gs;
+ $log =~ s,\r\n,\n,gs;
+ return 1 if ($log eq $kgo);
+
+ # See if it is a backslash problem (only on W32?)
+ ($mkgo = $kgo) =~ tr,\\,/,;
+ ($mlog = $log) =~ tr,\\,/,;
+ return 1 if ($log eq $kgo);
+
+ # VMS is a whole thing...
+ return 1 if ($^O eq 'VMS' && compare_answer_vms($mkgo, $mlog));
+
+ # See if the answer might be a regex.
+ if ($kgo =~ m,^/(.+)/$,) {
+ return 1 if ($log =~ /$1/);
+
+ # We can't test with backslashes converted to forward slashes, because
+ # backslashes could be escaping RE special characters!
+ }
+
+ return 0;
+}
+
my %old_tempfiles = ();
sub compare_output
{
my ($answer, $logfile) = @_;
- my ($slurp, $answer_matched, $extra) = ('', 0, 0);
+ my ($slurp, $matched, $extra) = ('', 0, 0);
++$tests_run;
@@ -831,169 +954,25 @@ sub compare_output
if (! defined $answer) {
print "Ignoring output ........ " if $debug;
- $answer_matched = 1;
+ $matched = 1;
} else {
print "Comparing output ........ " if $debug;
- $slurp = &read_file_into_string ($logfile);
-
- # For make, get rid of any time skew error before comparing--too bad this
- # has to go into the "generic" driver code :-/
- $slurp =~ s/^.*modification time .*in the future.*\n//gm;
- $slurp =~ s/^.*Clock skew detected.*\n//gm;
-
- if ($slurp eq $answer) {
- $answer_matched = 1;
- } else {
- # See if it is a slash or CRLF problem
- my ($answer_mod, $slurp_mod) = ($answer, $slurp);
-
- $answer_mod =~ tr,\\,/,;
- $answer_mod =~ s,\r\n,\n,gs;
-
- $slurp_mod =~ tr,\\,/,;
- $slurp_mod =~ s,\r\n,\n,gs;
-
- $answer_matched = ($slurp_mod eq $answer_mod);
-
- if (!$answer_matched && $^O eq 'VMS') {
-
- # VMS has extra blank lines in output sometimes.
- # Ticket #41760
- if (!$answer_matched) {
- $slurp_mod =~ s/\n\n+/\n/gm;
- $slurp_mod =~ s/\A\n+//g;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS adding a "Waiting for unfinished jobs..."
- # Remove it for now to see what else is going on.
- if (!$answer_matched) {
- $slurp_mod =~ s/^.+\*\*\* Waiting for unfinished jobs.+$//m;
- $slurp_mod =~ s/\n\n/\n/gm;
- $slurp_mod =~ s/^\n+//gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS wants target device to exist or generates an error,
- # Some test tagets look like VMS devices and trip this.
- if (!$answer_matched) {
- $slurp_mod =~ s/^.+\: no such device or address.*$//gim;
- $slurp_mod =~ s/\n\n/\n/gm;
- $slurp_mod =~ s/^\n+//gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS error message has a different case
- if (!$answer_matched) {
- $slurp_mod =~ s/no such file /No such file /gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS is putting comas instead of spaces in output
- if (!$answer_matched) {
- $slurp_mod =~ s/,/ /gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS Is sometimes adding extra leading spaces to output?
- if (!$answer_matched) {
- my $slurp_mod = $slurp_mod;
- $slurp_mod =~ s/^ +//gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS port not handling POSIX encoded child status
- # Translate error case it for now.
- if (!$answer_matched) {
- $slurp_mod =~ s/0x1035a00a/1/gim;
- $answer_matched = 1 if $slurp_mod =~ /\Q$answer_mod\E/i;
-
- }
- if (!$answer_matched) {
- $slurp_mod =~ s/0x1035a012/2/gim;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # Tests are using a UNIX null command, temp hack
- # until this can be handled by the VMS port.
- # ticket # 41761
- if (!$answer_matched) {
- $slurp_mod =~ s/^.+DCL-W-NOCOMD.*$//gim;
- $slurp_mod =~ s/\n\n+/\n/gm;
- $slurp_mod =~ s/^\n+//gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
- # Tests are using exit 0;
- # this generates a warning that should stop the make, but does not
- if (!$answer_matched) {
- $slurp_mod =~ s/^.+NONAME-W-NOMSG.*$//gim;
- $slurp_mod =~ s/\n\n+/\n/gm;
- $slurp_mod =~ s/^\n+//gm;
- $answer_matched = ($slurp_mod eq $answer_mod);
- }
-
- # VMS is sometimes adding single quotes to output?
- if (!$answer_matched) {
- my $noq_slurp_mod = $slurp_mod;
- $noq_slurp_mod =~ s/\'//gm;
- $answer_matched = ($noq_slurp_mod eq $answer_mod);
-
- # And missing an extra space in output
- if (!$answer_matched) {
- $noq_answer_mod = $answer_mod;
- $noq_answer_mod =~ s/\h\h+/ /gm;
- $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
- }
-
- # VMS adding ; to end of some lines.
- if (!$answer_matched) {
- $noq_slurp_mod =~ s/;\n/\n/gm;
- $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
- }
-
- # VMS adding trailing space to end of some quoted lines.
- if (!$answer_matched) {
- $noq_slurp_mod =~ s/\h+\n/\n/gm;
- $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
- }
-
- # And VMS missing leading blank line
- if (!$answer_matched) {
- $noq_answer_mod =~ s/\A\n//g;
- $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
- }
-
- # Unix double quotes showing up as single quotes on VMS.
- if (!$answer_matched) {
- $noq_answer_mod =~ s/\"//g;
- $answer_matched = ($noq_slurp_mod eq $noq_answer_mod);
- }
- }
- }
-
- # If it still doesn't match, see if the answer might be a regex.
- if (!$answer_matched && $answer =~ m,^/(.+)/$,) {
- $answer_matched = ($slurp =~ /$1/);
- if (!$answer_matched && $answer_mod =~ m,^/(.+)/$,) {
- $answer_matched = ($slurp_mod =~ /$1/);
- }
- }
- }
+ $matched = compare_answer($answer, &read_file_into_string ($logfile));
}
- if ($keep || ! $answer_matched) {
+ if ($keep || ! $matched) {
&create_file(&get_basefile, $answer);
&create_file(&get_runfile, $command_string);
}
- if ($answer_matched && $test_passed && !$extra) {
+ if ($matched && $test_passed && !$extra) {
print "ok\n" if $debug;
++$tests_passed;
return 1;
}
- if (! $answer_matched) {
+ if (! $matched) {
print "DIFFERENT OUTPUT\n" if $debug;
print "\nCreating Difference File ...\n" if $debug;
@@ -1001,10 +980,11 @@ sub compare_output
# Create the difference file
my $base = get_basefile();
if ($diff_name) {
- my $command = "$diff_name -c $base $logfile";
- &run_command_with_output(get_difffile(), $command);
+ &run_command_with_output(get_difffile(),
+ "$diff_name -c $base $logfile");
} else {
- create_file(get_difffile(), "Log file $logfile differs from base file $base\n");
+ create_file(get_difffile(),
+ "Log file $logfile differs from base file $base\n");
}
}
diff --git a/tests/thelp.pl b/tests/thelp.pl
index 993339cb..c243bcb8 100755
--- a/tests/thelp.pl
+++ b/tests/thelp.pl
@@ -16,6 +16,7 @@
# wait <word> : wait for a file named <word> to exist
# tmout <secs> : Change the timeout for waiting. Default is 4 seconds.
# sleep <secs> : Sleep for <secs> seconds then echo <secs>
+# term <pid> : send SIGTERM to PID <pid>
# fail <err> : echo <err> to stdout then exit with error code err
#
# If given -q only the "out" command generates output.
@@ -95,6 +96,12 @@ sub op {
return 1;
}
+ if ($op eq 'term') {
+ print "term $nm\n";
+ kill('TERM', $nm);
+ return 1;
+ }
+
if ($op eq 'fail') {
print "fail $nm\n";
exit($nm);