summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrea Corallo <akrl@sdf.org>2020-12-27 17:54:57 +0100
committerAndrea Corallo <akrl@sdf.org>2020-12-27 17:54:57 +0100
commit8fb94630136700aa4e74c7fc212b019d2db380ae (patch)
tree69b3938a89f450509a7001f45ba3acca057fb40d /lib
parent271fb8a269aff924070b188f23355d0c368356dd (diff)
parentdf882c9701755e2ae063f05d3381de14ae09951e (diff)
downloademacs-8fb94630136700aa4e74c7fc212b019d2db380ae.tar.gz
Merge remote-tracking branch 'savannah/master' into HEAD
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.in6
-rw-r--r--lib/attribute.h23
-rw-r--r--lib/c++defs.h8
-rw-r--r--lib/canonicalize-lgpl.c508
-rw-r--r--lib/careadlinkat.c30
-rw-r--r--lib/cdefs.h4
-rw-r--r--lib/eloop-threshold.h83
-rw-r--r--lib/euidaccess.c9
-rw-r--r--lib/faccessat.c14
-rw-r--r--lib/fcntl.c4
-rw-r--r--lib/fcntl.in.h37
-rw-r--r--lib/filemode.c14
-rw-r--r--lib/fpending.c7
-rw-r--r--lib/free.c33
-rw-r--r--lib/gnulib.mk.in103
-rw-r--r--lib/idx.h113
-rw-r--r--lib/intprops.h50
-rw-r--r--lib/malloc/scratch_buffer.h135
-rw-r--r--lib/malloc/scratch_buffer_grow.c56
-rw-r--r--lib/malloc/scratch_buffer_grow_preserve.c67
-rw-r--r--lib/malloc/scratch_buffer_set_array_size.c64
-rw-r--r--lib/mini-gmp.c58
-rw-r--r--lib/mini-gmp.h5
-rw-r--r--lib/rawmemchr.c136
-rw-r--r--lib/rawmemchr.valgrind28
-rw-r--r--lib/readlink.c48
-rw-r--r--lib/readlinkat.c47
-rw-r--r--lib/regex_internal.c19
-rw-r--r--lib/regex_internal.h8
-rw-r--r--lib/scratch_buffer.h29
-rw-r--r--lib/signal.in.h6
-rw-r--r--lib/stdint.in.h5
-rw-r--r--lib/stdio-impl.h2
-rw-r--r--lib/stdio.in.h183
-rw-r--r--lib/stdlib.in.h169
-rw-r--r--lib/string.in.h36
-rw-r--r--lib/symlink.c2
-rw-r--r--lib/sys_select.in.h9
-rw-r--r--lib/sys_stat.in.h32
-rw-r--r--lib/tempname.c49
-rw-r--r--lib/time.in.h23
-rw-r--r--lib/time_rz.c16
-rw-r--r--lib/unistd.in.h386
-rw-r--r--lib/xalloc-oversized.h2
44 files changed, 2102 insertions, 564 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 8d97d3bcfbb..d8dc5488f07 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -98,7 +98,7 @@ libegnu_a_OBJECTS = $(patsubst %.o,e-%.o,$(for_emacs_OBJECTS))
$(libegnu_a_OBJECTS) $(libgnu_a_OBJECTS): $(BUILT_SOURCES)
.c.o:
- $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
+ $(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
e-%.o: %.c
$(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -Demacs -o $@ $<
@@ -124,7 +124,7 @@ TAGS: $(ETAGS) $(tagsfiles)
.PHONY: $(ETAGS) tags
clean:
- rm -f ./*.[ao] ./*-t \#* $(DEPDIR)/*
+ rm -f ./*.[ao] ./*/*.o ./*-t \#* $(DEPDIR)/*.d $(DEPDIR)/*/*.d
mostlyclean: clean
rm -f $(filter-out %-t,$(MOSTLYCLEANFILES))
distclean bootstrap-clean: mostlyclean
@@ -133,7 +133,7 @@ distclean bootstrap-clean: mostlyclean
maintainer-clean: distclean
rm -f TAGS gnulib.mk
extraclean: distclean
- -rmdir sys 2>/dev/null
+ -rmdir malloc sys 2>/dev/null
.PHONY: mostlyclean clean distclean bootstrap-clean maintainer-clean
diff --git a/lib/attribute.h b/lib/attribute.h
index 2836b99dad0..5afcb8e81f2 100644
--- a/lib/attribute.h
+++ b/lib/attribute.h
@@ -80,7 +80,7 @@
/* Attributes for variadic functions. */
/* The variadic function expects a trailing NULL argument.
- ATTRIBUTE_SENTINEL () - The last argument is NULL.
+ ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99).
ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */
/* Applies to: functions. */
#define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos)
@@ -170,18 +170,21 @@
/* Applies to: function. */
#define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE
-/* The function does not affect observable state, and always returns a value.
- Compilers can omit duplicate calls with the same arguments if
- observable state is not changed between calls. (This attribute is
- looser than ATTRIBUTE_CONST.) */
+/* It is OK for a compiler to omit duplicate calls with the same arguments.
+ This attribute is safe for a function that neither depends on
+ nor affects observable state, and always returns exactly once -
+ e.g., does not loop forever, and does not call longjmp.
+ (This attribute is stricter than ATTRIBUTE_PURE.) */
/* Applies to: functions. */
-#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE
+#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
-/* The function neither depends on nor affects observable state,
- and always returns a value. Compilers can omit duplicate calls with
- the same arguments. (This attribute is stricter than ATTRIBUTE_PURE.) */
+/* It is OK for a compiler to omit duplicate calls with the same
+ arguments if observable state is not changed between calls.
+ This attribute is safe for a function that does not affect
+ observable state, and always returns exactly once.
+ (This attribute is looser than ATTRIBUTE_CONST.) */
/* Applies to: functions. */
-#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
+#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE
/* The function is rarely executed. */
/* Applies to: functions. */
diff --git a/lib/c++defs.h b/lib/c++defs.h
index 6a9bf295eb5..01ef8140cad 100644
--- a/lib/c++defs.h
+++ b/lib/c++defs.h
@@ -181,6 +181,14 @@
_GL_EXTERN_C int _gl_cxxalias_dummy
#endif
+/* _GL_CXXALIAS_MDA_CAST (func, rettype, parameters);
+ is like _GL_CXXALIAS_MDA (func, rettype, parameters);
+ except that the C function func may have a slightly different declaration.
+ A cast is used to silence the "invalid conversion" error that would
+ otherwise occur. */
+#define _GL_CXXALIAS_MDA_CAST(func,rettype,parameters) \
+ _GL_CXXALIAS_RPL_CAST_1 (func, _##func, rettype, parameters)
+
/* _GL_CXXALIAS_SYS (func, rettype, parameters);
declares a C++ alias called GNULIB_NAMESPACE::func
that redirects to the system provided function func, if GNULIB_NAMESPACE
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index 0b89d2a1842..650d510f2d0 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -2,18 +2,19 @@
Copyright (C) 1996-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR 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 <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
#ifndef _LIBC
/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
@@ -21,37 +22,41 @@
# define _GL_ARG_NONNULL(params)
# define _GL_USE_STDLIB_ALLOC 1
-# include <config.h>
+# include <libc-config.h>
#endif
-#if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC
-
/* Specification. */
#include <stdlib.h>
-#include <alloca.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-#if HAVE_SYS_PARAM_H || defined _LIBC
-# include <sys/param.h>
-#endif
-#include <sys/stat.h>
#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdbool.h>
#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <eloop-threshold.h>
+#include <filename.h>
+#include <idx.h>
+#include <scratch_buffer.h>
#ifdef _LIBC
# include <shlib-compat.h>
+# include <sysdep.h>
+# ifdef __ASSUME_FACCESSAT2
+# define FACCESSAT_NEVER_EOVERFLOWS __ASSUME_FACCESSAT2
+# else
+# define FACCESSAT_NEVER_EOVERFLOWS true
+# endif
+# define GCC_LINT 1
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
#else
-# define SHLIB_COMPAT(lib, introduced, obsoleted) 0
-# define versioned_symbol(lib, local, symbol, version) extern int dummy
-# define compat_symbol(lib, local, symbol, version)
-# define weak_alias(local, symbol)
# define __canonicalize_file_name canonicalize_file_name
# define __realpath realpath
# include "pathmax.h"
-# include "malloca.h"
-# include "filename.h"
+# define __faccessat faccessat
# if defined _WIN32 && !defined __CYGWIN__
# define __getcwd _getcwd
# elif HAVE_GETCWD
@@ -72,57 +77,143 @@
# else
# define __getcwd(buf, max) getwd (buf)
# endif
+# define __mempcpy mempcpy
+# define __pathconf pathconf
+# define __rawmemchr rawmemchr
# define __readlink readlink
-# define __set_errno(e) errno = (e)
-# ifndef MAXSYMLINKS
-# ifdef SYMLOOP_MAX
-# define MAXSYMLINKS SYMLOOP_MAX
-# else
-# define MAXSYMLINKS 20
-# endif
-# endif
+# define __stat stat
#endif
-#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
-# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
+/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
+#if defined GCC_LINT || defined lint
+# define IF_LINT(Code) Code
+#else
+# define IF_LINT(Code) /* empty */
#endif
-/* Define this independently so that stdint.h is not a prerequisite. */
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t) -1)
+#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
+# define DOUBLE_SLASH_IS_DISTINCT_ROOT false
+#endif
+#ifndef FACCESSAT_NEVER_EOVERFLOWS
+# define FACCESSAT_NEVER_EOVERFLOWS false
#endif
#if !FUNC_REALPATH_WORKS || defined _LIBC
-static void
-alloc_failed (void)
+/* Return true if FILE's existence can be shown, false (setting errno)
+ otherwise. Follow symbolic links. */
+static bool
+file_accessible (char const *file)
+{
+# if defined _LIBC || HAVE_FACCESSAT
+ int r = __faccessat (AT_FDCWD, file, F_OK, AT_EACCESS);
+# else
+ struct stat st;
+ int r = __stat (file, &st);
+# endif
+
+ return ((!FACCESSAT_NEVER_EOVERFLOWS && r < 0 && errno == EOVERFLOW)
+ || r == 0);
+}
+
+/* True if concatenating END as a suffix to a file name means that the
+ code needs to check that the file name is that of a searchable
+ directory, since the canonicalize_filename_mode_stk code won't
+ check this later anyway when it checks an ordinary file name
+ component within END. END must either be empty, or start with a
+ slash. */
+
+static bool _GL_ATTRIBUTE_PURE
+suffix_requires_dir_check (char const *end)
{
-#if defined _WIN32 && ! defined __CYGWIN__
- /* Avoid errno problem without using the malloc or realloc modules; see:
- https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html */
- errno = ENOMEM;
+ /* If END does not start with a slash, the suffix is OK. */
+ while (ISSLASH (*end))
+ {
+ /* Two or more slashes act like a single slash. */
+ do
+ end++;
+ while (ISSLASH (*end));
+
+ switch (*end++)
+ {
+ default: return false; /* An ordinary file name component is OK. */
+ case '\0': return true; /* Trailing "/" is trouble. */
+ case '.': break; /* Possibly "." or "..". */
+ }
+ /* Trailing "/.", or "/.." even if not trailing, is trouble. */
+ if (!*end || (*end == '.' && (!end[1] || ISSLASH (end[1]))))
+ return true;
+ }
+
+ return false;
+}
+
+/* Append this to a file name to test whether it is a searchable directory.
+ On POSIX platforms "/" suffices, but "/./" is sometimes needed on
+ macOS 10.13 <https://bugs.gnu.org/30350>, and should also work on
+ platforms like AIX 7.2 that need at least "/.". */
+
+#if defined _LIBC || defined LSTAT_FOLLOWS_SLASHED_SYMLINK
+static char const dir_suffix[] = "/";
+#else
+static char const dir_suffix[] = "/./";
#endif
+
+/* Return true if DIR is a searchable dir, false (setting errno) otherwise.
+ DIREND points to the NUL byte at the end of the DIR string.
+ Store garbage into DIREND[0 .. strlen (dir_suffix)]. */
+
+static bool
+dir_check (char *dir, char *dirend)
+{
+ strcpy (dirend, dir_suffix);
+ return file_accessible (dir);
}
-/* Return the canonical absolute name of file NAME. A canonical name
- does not contain any ".", ".." components nor any repeated path
- separators ('/') or symlinks. All path components must exist. If
- RESOLVED is null, the result is malloc'd; otherwise, if the
- canonical name is PATH_MAX chars or more, returns null with 'errno'
- set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
- returns the name in RESOLVED. If the name cannot be resolved and
- RESOLVED is non-NULL, it contains the path of the first component
- that cannot be resolved. If the path can be resolved, RESOLVED
- holds the same value as the value returned. */
+static idx_t
+get_path_max (void)
+{
+# ifdef PATH_MAX
+ long int path_max = PATH_MAX;
+# else
+ /* The caller invoked realpath with a null RESOLVED, even though
+ PATH_MAX is not defined as a constant. The glibc manual says
+ programs should not do this, and POSIX says the behavior is undefined.
+ Historically, glibc here used the result of pathconf, or 1024 if that
+ failed; stay consistent with this (dubious) historical practice. */
+ int err = errno;
+ long int path_max = __pathconf ("/", _PC_PATH_MAX);
+ __set_errno (err);
+# endif
+ return path_max < 0 ? 1024 : path_max <= IDX_MAX ? path_max : IDX_MAX;
+}
-char *
-__realpath (const char *name, char *resolved)
+/* Act like __realpath (see below), with an additional argument
+ rname_buf that can be used as temporary storage.
+
+ If GCC_LINT is defined, do not inline this function with GCC 10.1
+ and later, to avoid creating a pointer to the stack that GCC
+ -Wreturn-local-addr incorrectly complains about. See:
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644
+ Although the noinline attribute can hurt performance a bit, no better way
+ to pacify GCC is known; even an explicit #pragma does not pacify GCC.
+ When the GCC bug is fixed this workaround should be limited to the
+ broken GCC versions. */
+#if __GNUC_PREREQ (10, 1)
+# if defined GCC_LINT || defined lint
+__attribute__ ((__noinline__))
+# elif __OPTIMIZE__ && !__NO_INLINE__
+# define GCC_BOGUS_WRETURN_LOCAL_ADDR
+# endif
+#endif
+static char *
+realpath_stk (const char *name, char *resolved,
+ struct scratch_buffer *rname_buf)
{
- char *rpath, *dest, *extra_buf = NULL;
- const char *start, *end, *rpath_limit;
- long int path_max;
+ char *dest;
+ char const *start;
+ char const *end;
int num_links = 0;
- size_t prefix_len;
if (name == NULL)
{
@@ -142,205 +233,143 @@ __realpath (const char *name, char *resolved)
return NULL;
}
-#ifdef PATH_MAX
- path_max = PATH_MAX;
-#else
- path_max = pathconf (name, _PC_PATH_MAX);
- if (path_max <= 0)
- path_max = 8192;
-#endif
-
- if (resolved == NULL)
- {
- rpath = malloc (path_max);
- if (rpath == NULL)
- {
- alloc_failed ();
- return NULL;
- }
- }
- else
- rpath = resolved;
- rpath_limit = rpath + path_max;
+ struct scratch_buffer extra_buffer, link_buffer;
+ scratch_buffer_init (&extra_buffer);
+ scratch_buffer_init (&link_buffer);
+ scratch_buffer_init (rname_buf);
+ char *rname_on_stack = rname_buf->data;
+ char *rname = rname_on_stack;
+ bool end_in_extra_buffer = false;
+ bool failed = true;
/* This is always zero for Posix hosts, but can be 2 for MS-Windows
and MS-DOS X:/foo/bar file names. */
- prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
+ idx_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
if (!IS_ABSOLUTE_FILE_NAME (name))
{
- if (!__getcwd (rpath, path_max))
+ while (!__getcwd (rname, rname_buf->length))
{
- rpath[0] = '\0';
- goto error;
+ if (errno != ERANGE)
+ {
+ dest = rname;
+ goto error;
+ }
+ if (!scratch_buffer_grow (rname_buf))
+ goto error_nomem;
+ rname = rname_buf->data;
}
- dest = strchr (rpath, '\0');
+ dest = __rawmemchr (rname, '\0');
start = name;
- prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath);
+ prefix_len = FILE_SYSTEM_PREFIX_LEN (rname);
}
else
{
- dest = rpath;
- if (prefix_len)
- {
- memcpy (rpath, name, prefix_len);
- dest += prefix_len;
- }
+ dest = __mempcpy (rname, name, prefix_len);
*dest++ = '/';
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
- if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
+ if (prefix_len == 0 /* implies ISSLASH (name[0]) */
+ && ISSLASH (name[1]) && !ISSLASH (name[2]))
*dest++ = '/';
*dest = '\0';
}
start = name + prefix_len;
}
- for (end = start; *start; start = end)
+ for ( ; *start; start = end)
{
-#ifdef _LIBC
- struct stat64 st;
-#else
- struct stat st;
-#endif
-
- /* Skip sequence of multiple path-separators. */
+ /* Skip sequence of multiple file name separators. */
while (ISSLASH (*start))
++start;
- /* Find end of path component. */
+ /* Find end of component. */
for (end = start; *end && !ISSLASH (*end); ++end)
/* Nothing. */;
- if (end - start == 0)
+ /* Length of this file name component; it can be zero if a file
+ name ends in '/'. */
+ idx_t startlen = end - start;
+
+ if (startlen == 0)
break;
- else if (end - start == 1 && start[0] == '.')
+ else if (startlen == 1 && start[0] == '.')
/* nothing */;
- else if (end - start == 2 && start[0] == '.' && start[1] == '.')
+ else if (startlen == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
- if (dest > rpath + prefix_len + 1)
- for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
+ if (dest > rname + prefix_len + 1)
+ for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT
- && dest == rpath + 1 && !prefix_len
+ && dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
}
else
{
- size_t new_size;
-
if (!ISSLASH (dest[-1]))
*dest++ = '/';
- if (dest + (end - start) >= rpath_limit)
+ while (rname + rname_buf->length - dest
+ < startlen + sizeof dir_suffix)
{
- ptrdiff_t dest_offset = dest - rpath;
- char *new_rpath;
-
- if (resolved)
- {
- __set_errno (ENAMETOOLONG);
- if (dest > rpath + prefix_len + 1)
- dest--;
- *dest = '\0';
- goto error;
- }
- new_size = rpath_limit - rpath;
- if (end - start + 1 > path_max)
- new_size += end - start + 1;
- else
- new_size += path_max;
- new_rpath = (char *) realloc (rpath, new_size);
- if (new_rpath == NULL)
- {
- alloc_failed ();
- goto error;
- }
- rpath = new_rpath;
- rpath_limit = rpath + new_size;
-
- dest = rpath + dest_offset;
+ idx_t dest_offset = dest - rname;
+ if (!scratch_buffer_grow_preserve (rname_buf))
+ goto error_nomem;
+ rname = rname_buf->data;
+ dest = rname + dest_offset;
}
-#ifdef _LIBC
- dest = __mempcpy (dest, start, end - start);
-#else
- memcpy (dest, start, end - start);
- dest += end - start;
-#endif
+ dest = __mempcpy (dest, start, startlen);
*dest = '\0';
- /* FIXME: if lstat fails with errno == EOVERFLOW,
- the entry exists. */
-#ifdef _LIBC
- if (__lxstat64 (_STAT_VER, rpath, &st) < 0)
-#else
- if (lstat (rpath, &st) < 0)
-#endif
- goto error;
-
- if (S_ISLNK (st.st_mode))
+ char *buf;
+ ssize_t n;
+ while (true)
{
- char *buf;
- size_t len;
- ssize_t n;
-
- if (++num_links > MAXSYMLINKS)
+ buf = link_buffer.data;
+ idx_t bufsize = link_buffer.length;
+ n = __readlink (rname, buf, bufsize - 1);
+ if (n < bufsize - 1)
+ break;
+ if (!scratch_buffer_grow (&link_buffer))
+ goto error_nomem;
+ }
+ if (0 <= n)
+ {
+ if (++num_links > __eloop_threshold ())
{
__set_errno (ELOOP);
goto error;
}
- buf = malloca (path_max);
- if (!buf)
- {
- __set_errno (ENOMEM);
- goto error;
- }
-
- n = __readlink (rpath, buf, path_max - 1);
- if (n < 0)
- {
- int saved_errno = errno;
- freea (buf);
- __set_errno (saved_errno);
- goto error;
- }
buf[n] = '\0';
- if (!extra_buf)
- {
- extra_buf = malloca (path_max);
- if (!extra_buf)
- {
- freea (buf);
- __set_errno (ENOMEM);
- goto error;
- }
- }
-
- len = strlen (end);
- /* Check that n + len + 1 doesn't overflow and is <= path_max. */
- if (n >= SIZE_MAX - len || n + len >= path_max)
+ char *extra_buf = extra_buffer.data;
+ idx_t end_idx IF_LINT (= 0);
+ if (end_in_extra_buffer)
+ end_idx = end - extra_buf;
+ idx_t len = strlen (end);
+ while (extra_buffer.length <= len + n)
{
- freea (buf);
- __set_errno (ENAMETOOLONG);
- goto error;
+ if (!scratch_buffer_grow_preserve (&extra_buffer))
+ goto error_nomem;
+ extra_buf = extra_buffer.data;
}
+ if (end_in_extra_buffer)
+ end = extra_buf + end_idx;
/* Careful here, end may be a pointer into extra_buf... */
memmove (&extra_buf[n], end, len + 1);
name = end = memcpy (extra_buf, buf, n);
+ end_in_extra_buffer = true;
if (IS_ABSOLUTE_FILE_NAME (buf))
{
- size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
+ idx_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf);
- if (pfxlen)
- memcpy (rpath, buf, pfxlen);
- dest = rpath + pfxlen;
+ dest = __mempcpy (rname, buf, pfxlen);
*dest++ = '/'; /* It's an absolute symlink */
if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
{
@@ -355,44 +384,77 @@ __realpath (const char *name, char *resolved)
{
/* Back up to previous component, ignore if at root
already: */
- if (dest > rpath + prefix_len + 1)
- for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest)
+ if (dest > rname + prefix_len + 1)
+ for (--dest; dest > rname && !ISSLASH (dest[-1]); --dest)
continue;
- if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1
&& ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len)
dest++;
}
}
- else if (!S_ISDIR (st.st_mode) && *end != '\0')
- {
- __set_errno (ENOTDIR);
- goto error;
- }
+ else if (! (suffix_requires_dir_check (end)
+ ? dir_check (rname, dest)
+ : errno == EINVAL))
+ goto error;
}
}
- if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1]))
+ if (dest > rname + prefix_len + 1 && ISSLASH (dest[-1]))
--dest;
- if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len
+ if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rname + 1 && !prefix_len
&& ISSLASH (*dest) && !ISSLASH (dest[1]))
dest++;
- *dest = '\0';
+ failed = false;
- if (extra_buf)
- freea (extra_buf);
+error:
+ *dest++ = '\0';
+ if (resolved != NULL && dest - rname <= get_path_max ())
+ rname = strcpy (resolved, rname);
+
+error_nomem:
+ scratch_buffer_free (&extra_buffer);
+ scratch_buffer_free (&link_buffer);
+ if (failed || rname == resolved)
+ scratch_buffer_free (rname_buf);
+
+ if (failed)
+ return NULL;
+
+ if (rname == resolved)
+ return rname;
+ idx_t rname_size = dest - rname;
+ if (rname == rname_on_stack)
+ {
+ rname = malloc (rname_size);
+ if (rname == NULL)
+ return NULL;
+ return memcpy (rname, rname_on_stack, rname_size);
+ }
+ char *result = realloc (rname, rname_size);
+ return result != NULL ? result : rname;
+}
- return rpath;
+/* Return the canonical absolute name of file NAME. A canonical name
+ does not contain any ".", ".." components nor any repeated file name
+ separators ('/') or symlinks. All file name components must exist. If
+ RESOLVED is null, the result is malloc'd; otherwise, if the
+ canonical name is PATH_MAX chars or more, returns null with 'errno'
+ set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars,
+ returns the name in RESOLVED. If the name cannot be resolved and
+ RESOLVED is non-NULL, it contains the name of the first component
+ that cannot be resolved. If the name can be resolved, RESOLVED
+ holds the same value as the value returned. */
-error:
- {
- int saved_errno = errno;
- if (extra_buf)
- freea (extra_buf);
- if (resolved == NULL)
- free (rpath);
- __set_errno (saved_errno);
- }
- return NULL;
+char *
+__realpath (const char *name, char *resolved)
+{
+ #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
+ #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
+ #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
+ #endif
+ struct scratch_buffer rname_buffer;
+ return realpath_stk (name, resolved, &rname_buffer);
}
+libc_hidden_def (__realpath)
versioned_symbol (libc, __realpath, realpath, GLIBC_2_3);
#endif /* !FUNC_REALPATH_WORKS || defined _LIBC */
@@ -420,11 +482,3 @@ __canonicalize_file_name (const char *name)
return __realpath (name, NULL);
}
weak_alias (__canonicalize_file_name, canonicalize_file_name)
-
-#else
-
-/* This declaration is solely to ensure that after preprocessing
- this file is never empty. */
-typedef int dummy;
-
-#endif
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c
index e43aa42d5c4..6aaa712b9be 100644
--- a/lib/careadlinkat.c
+++ b/lib/careadlinkat.c
@@ -51,8 +51,12 @@ enum { STACK_BUF_SIZE = 1024 };
to pacify GCC is known; even an explicit #pragma does not pacify GCC.
When the GCC bug is fixed this workaround should be limited to the
broken GCC versions. */
-#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1)
+#if _GL_GNUC_PREREQ (10, 1)
+# if defined GCC_LINT || defined lint
__attribute__ ((__noinline__))
+# elif __OPTIMIZE__ && !__NO_INLINE__
+# define GCC_BOGUS_WRETURN_LOCAL_ADDR
+# endif
#endif
static char *
readlink_stk (int fd, char const *filename,
@@ -85,18 +89,13 @@ readlink_stk (int fd, char const *filename,
size_t link_size;
if (link_length < 0)
{
- /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
- with errno == ERANGE if the buffer is too small. */
- int readlinkat_errno = errno;
- if (readlinkat_errno != ERANGE)
+ if (buf != buffer)
{
- if (buf != buffer)
- {
- alloc->free (buf);
- errno = readlinkat_errno;
- }
- return NULL;
+ int readlinkat_errno = errno;
+ alloc->free (buf);
+ errno = readlinkat_errno;
}
+ return NULL;
}
link_size = link_length;
@@ -180,10 +179,11 @@ careadlinkat (int fd, char const *filename,
/* Allocate the initial buffer on the stack. This way, in the
common case of a symlink of small size, we get away with a
single small malloc instead of a big malloc followed by a
- shrinking realloc.
-
- If GCC -Wreturn-local-addr warns about this buffer, the warning
- is bogus; see readlink_stk. */
+ shrinking realloc. */
+ #ifdef GCC_BOGUS_WRETURN_LOCAL_ADDR
+ #warning "GCC might issue a bogus -Wreturn-local-addr warning here."
+ #warning "See <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644>."
+ #endif
char stack_buf[STACK_BUF_SIZE];
return readlink_stk (fd, filename, buffer, buffer_size, alloc,
preadlinkat, stack_buf);
diff --git a/lib/cdefs.h b/lib/cdefs.h
index ff7c628a264..1a2805d7259 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -75,11 +75,11 @@
/* GCC can always grok prototypes. For C++ programs we add throw()
to help it optimize the function calls. But this works only with
- gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions
+ gcc 2.8.x and egcs. For gcc 3.4 and up we even mark C functions
as non-throwing using a function attribute since programs can use
the -fexceptions options for C code as well. */
# if !defined __cplusplus \
- && (__GNUC_PREREQ (3, 3) || __glibc_clang_has_attribute (__nothrow__))
+ && (__GNUC_PREREQ (3, 4) || __glibc_clang_has_attribute (__nothrow__))
# define __THROW __attribute__ ((__nothrow__ __LEAF))
# define __THROWNL __attribute__ ((__nothrow__))
# define __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
diff --git a/lib/eloop-threshold.h b/lib/eloop-threshold.h
new file mode 100644
index 00000000000..5953a4cc065
--- /dev/null
+++ b/lib/eloop-threshold.h
@@ -0,0 +1,83 @@
+/* Threshold at which to diagnose ELOOP. Generic version.
+ Copyright (C) 2012-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _ELOOP_THRESHOLD_H
+#define _ELOOP_THRESHOLD_H 1
+
+#include <limits.h>
+#ifdef _LIBC
+# include <sys/param.h>
+# define _GL_ATTRIBUTE_CONST __attribute__ ((const))
+#else
+# include <unistd.h>
+# include "minmax.h"
+# define __sysconf sysconf
+# if (!defined SYMLOOP_MAX \
+ && ! (defined _SC_SYMLOOP_MAX && defined _POSIX_SYMLOOP_MAX))
+# define SYMLOOP_MAX 8
+# endif
+#endif
+
+/* POSIX specifies SYMLOOP_MAX as the "Maximum number of symbolic
+ links that can be reliably traversed in the resolution of a
+ pathname in the absence of a loop." This makes it a minimum that
+ we should certainly accept. But it leaves open the possibility
+ that more might sometimes work--just not "reliably".
+
+ For example, Linux implements a complex policy whereby there is a
+ small limit on the number of direct symlink traversals (a symlink
+ to a symlink to a symlink), but larger limit on the total number of
+ symlink traversals overall. Hence the SYMLOOP_MAX number should be
+ the small one, but the limit library functions enforce on users
+ should be the larger one.
+
+ So, we use the larger of the reported SYMLOOP_MAX (if any) and our
+ own constant MIN_ELOOP_THRESHOLD, below. This constant should be
+ large enough that it never rules out a file name and directory tree
+ that the underlying system (i.e. calls to 'open' et al) would
+ resolve successfully. It should be small enough that actual loops
+ are detected without a huge number of iterations. */
+
+#ifndef MIN_ELOOP_THRESHOLD
+# define MIN_ELOOP_THRESHOLD 40
+#endif
+
+/* Return the maximum number of symlink traversals to permit
+ before diagnosing ELOOP. */
+static inline unsigned int _GL_ATTRIBUTE_CONST
+__eloop_threshold (void)
+{
+#ifdef SYMLOOP_MAX
+ const int symloop_max = SYMLOOP_MAX;
+#else
+ /* The function is marked 'const' even though we use memory and
+ call a function, because sysconf is required to return the
+ same value in every call and so it must always be safe to
+ call __eloop_threshold exactly once and reuse the value. */
+ static long int sysconf_symloop_max;
+ if (sysconf_symloop_max == 0)
+ sysconf_symloop_max = __sysconf (_SC_SYMLOOP_MAX);
+ const unsigned int symloop_max = (sysconf_symloop_max <= 0
+ ? _POSIX_SYMLOOP_MAX
+ : sysconf_symloop_max);
+#endif
+
+ return MAX (symloop_max, MIN_ELOOP_THRESHOLD);
+}
+
+#endif /* eloop-threshold.h */
diff --git a/lib/euidaccess.c b/lib/euidaccess.c
index b352123ae18..a32e3366eb8 100644
--- a/lib/euidaccess.c
+++ b/lib/euidaccess.c
@@ -107,7 +107,10 @@ euidaccess (const char *file, int mode)
safe. */
if (mode == F_OK)
- return stat (file, &stats);
+ {
+ int result = stat (file, &stats);
+ return result != 0 && errno == EOVERFLOW ? 0 : result;
+ }
else
{
int result;
@@ -142,8 +145,8 @@ euidaccess (const char *file, int mode)
/* If we are not set-uid or set-gid, access does the same. */
return access (file, mode);
- if (stat (file, &stats) != 0)
- return -1;
+ if (stat (file, &stats) == -1)
+ return mode == F_OK && errno == EOVERFLOW ? 0 : -1;
/* The super-user can read and write any file, and execute any file
that anyone can execute. */
diff --git a/lib/faccessat.c b/lib/faccessat.c
index 9f6a11bf6e3..330c54a0be2 100644
--- a/lib/faccessat.c
+++ b/lib/faccessat.c
@@ -32,6 +32,13 @@
#include <sys/stat.h>
#undef _GL_INCLUDING_UNISTD_H
+#ifndef FACCESSAT_NEVER_EOVERFLOWS
+# define FACCESSAT_NEVER_EOVERFLOWS 0
+#endif
+#ifndef LSTAT_FOLLOWS_SLASHED_SYMLINK
+# define LSTAT_FOLLOWS_SLASHED_SYMLINK 0
+#endif
+
#if HAVE_FACCESSAT
static int
orig_faccessat (int fd, char const *name, int mode, int flag)
@@ -59,7 +66,12 @@ rpl_faccessat (int fd, char const *file, int mode, int flag)
{
int result = orig_faccessat (fd, file, mode, flag);
- if (result == 0 && file[strlen (file) - 1] == '/')
+ if (result != 0)
+ {
+ if (!FACCESSAT_NEVER_EOVERFLOWS && mode == F_OK && errno == EOVERFLOW)
+ return 0;
+ }
+ else if (!LSTAT_FOLLOWS_SLASHED_SYMLINK && file[strlen (file) - 1] == '/')
{
struct stat st;
result = fstatat (fd, file, &st, 0);
diff --git a/lib/fcntl.c b/lib/fcntl.c
index 8cd1531527d..59bb3ca91ea 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -491,7 +491,9 @@ rpl_fcntl_DUPFD_CLOEXEC (int fd, int target)
#if !HAVE_FCNTL
result = dupfd (fd, target, O_CLOEXEC);
#else /* HAVE_FCNTL */
-# if defined __HAIKU__
+# if defined __NetBSD__ || defined __HAIKU__
+ /* On NetBSD 9.0, the system fcntl (fd, F_DUPFD_CLOEXEC, target)
+ has only the same effect as fcntl (fd, F_DUPFD, target). */
/* On Haiku, the system fcntl (fd, F_DUPFD_CLOEXEC, target) sets
the FD_CLOEXEC flag on fd, not on target. Therefore avoid the
system fcntl in this case. */
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index 6f16bc66921..11c9aae9bcc 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -112,9 +112,21 @@ _GL_CXXALIASWARN (creat);
/* Assume creat is always declared. */
_GL_WARN_ON_USE (creat, "creat is not always POSIX compliant - "
"use gnulib module creat for portability");
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef creat
-# define creat _creat
+#else
+/* On native Windows, map 'creat' to '_creat', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::creat always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef creat
+# define creat _creat
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (creat, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (creat);
#endif
#if @GNULIB_FCNTL@
@@ -174,9 +186,22 @@ _GL_CXXALIASWARN (open);
/* Assume open is always declared. */
_GL_WARN_ON_USE (open, "open is not always POSIX compliant - "
"use gnulib module open for portability");
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef open
-# define open _open
+#else
+/* On native Windows, map 'open' to '_open', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::open always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef open
+# define open _open
+# endif
+_GL_CXXALIAS_MDA (open, int, (const char *filename, int flags, ...));
+# else
+_GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
+# endif
+# if !defined __hpux
+_GL_CXXALIASWARN (open);
+# endif
#endif
#if @GNULIB_OPENAT@
diff --git a/lib/filemode.c b/lib/filemode.c
index e1b069093f8..15e3551368b 100644
--- a/lib/filemode.c
+++ b/lib/filemode.c
@@ -20,17 +20,6 @@
#include "filemode.h"
-/* The following is for Cray DMF (Data Migration Facility), which is a
- HSM file system. A migrated file has a 'st_dm_mode' that is
- different from the normal 'st_mode', so any tests for migrated
- files should use the former. */
-#if HAVE_ST_DM_MODE
-# define IS_MIGRATED_FILE(statp) \
- (S_ISOFD (statp->st_dm_mode) || S_ISOFL (statp->st_dm_mode))
-#else
-# define IS_MIGRATED_FILE(statp) 0
-#endif
-
#if ! HAVE_DECL_STRMODE
/* Return a character indicating the type of file described by
@@ -126,7 +115,6 @@ strmode (mode_t mode, char *str)
for files whose type cannot be determined solely from st_mode:
'F' semaphore
- 'M' migrated file (Cray DMF)
'Q' message queue
'S' shared memory object
'T' typed memory object
@@ -169,8 +157,6 @@ filemodestring (struct stat const *statp, char *str)
if (S_TYPEISSEM (statp))
str[0] = 'F';
- else if (IS_MIGRATED_FILE (statp))
- str[0] = 'M';
else if (S_TYPEISMQ (statp))
str[0] = 'Q';
else if (S_TYPEISSHM (statp))
diff --git a/lib/fpending.c b/lib/fpending.c
index 802ebcba654..836a3a988bf 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -25,7 +25,8 @@
#include "stdio-impl.h"
/* This file is not used on systems that already have the __fpending function,
- namely glibc >= 2.2, Solaris >= 7, Android API >= 23. */
+ namely glibc >= 2.2, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.34,
+ Android API >= 23. */
/* Return the number of pending (aka buffered, unflushed)
bytes on the stream, FP, that is open for writing. */
@@ -39,13 +40,13 @@ __fpending (FILE *fp)
/* GNU libc, BeOS, Haiku, Linux libc5 */
return fp->_IO_write_ptr - fp->_IO_write_base;
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
- /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */
+ /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */
return fp->_p - fp->_bf._base;
#elif defined __EMX__ /* emx+gcc */
return fp->_ptr - fp->_buffer;
#elif defined __minix /* Minix */
return fp_->_ptr - fp_->_buf;
-#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel, OpenVMS */
+#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */
return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0);
#elif defined __UCLIBC__ /* uClibc */
return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0);
diff --git a/lib/free.c b/lib/free.c
new file mode 100644
index 00000000000..2f689a7ea32
--- /dev/null
+++ b/lib/free.c
@@ -0,0 +1,33 @@
+/* Make free() preserve errno.
+
+ Copyright (C) 2003, 2006, 2009-2020 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 <https://www.gnu.org/licenses/>. */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <errno.h>
+
+void
+rpl_free (void *p)
+#undef free
+{
+ int err = errno;
+ free (p);
+ errno = err;
+}
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 9953198fb31..a37f9278a31 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -103,6 +103,7 @@
# filevercmp \
# flexmember \
# fpieee \
+# free-posix \
# fstatat \
# fsusage \
# fsync \
@@ -257,6 +258,7 @@ GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@
GMALLOC_OBJ = @GMALLOC_OBJ@
GMP_H = @GMP_H@
GNULIB_ACCESS = @GNULIB_ACCESS@
+GNULIB_ALIGNED_ALLOC = @GNULIB_ALIGNED_ALLOC@
GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
GNULIB_ATOLL = @GNULIB_ATOLL@
GNULIB_CALLOC_POSIX = @GNULIB_CALLOC_POSIX@
@@ -297,6 +299,7 @@ GNULIB_FPURGE = @GNULIB_FPURGE@
GNULIB_FPUTC = @GNULIB_FPUTC@
GNULIB_FPUTS = @GNULIB_FPUTS@
GNULIB_FREAD = @GNULIB_FREAD@
+GNULIB_FREE_POSIX = @GNULIB_FREE_POSIX@
GNULIB_FREOPEN = @GNULIB_FREOPEN@
GNULIB_FSCANF = @GNULIB_FSCANF@
GNULIB_FSEEK = @GNULIB_FSEEK@
@@ -388,6 +391,7 @@ GNULIB_PERROR = @GNULIB_PERROR@
GNULIB_PIPE = @GNULIB_PIPE@
GNULIB_PIPE2 = @GNULIB_PIPE2@
GNULIB_POPEN = @GNULIB_POPEN@
+GNULIB_POSIX_MEMALIGN = @GNULIB_POSIX_MEMALIGN@
GNULIB_POSIX_OPENPT = @GNULIB_POSIX_OPENPT@
GNULIB_PREAD = @GNULIB_PREAD@
GNULIB_PRINTF = @GNULIB_PRINTF@
@@ -506,6 +510,7 @@ GTK_OBJ = @GTK_OBJ@
GZIP_PROG = @GZIP_PROG@
HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@
HARFBUZZ_LIBS = @HARFBUZZ_LIBS@
+HAVE_ALIGNED_ALLOC = @HAVE_ALIGNED_ALLOC@
HAVE_ALLOCA_H = @HAVE_ALLOCA_H@
HAVE_ALPHASORT = @HAVE_ALPHASORT@
HAVE_ATOLL = @HAVE_ATOLL@
@@ -515,13 +520,18 @@ HAVE_CHOWN = @HAVE_CHOWN@
HAVE_CLOSEDIR = @HAVE_CLOSEDIR@
HAVE_COPY_FILE_RANGE = @HAVE_COPY_FILE_RANGE@
HAVE_DECL_DIRFD = @HAVE_DECL_DIRFD@
+HAVE_DECL_ECVT = @HAVE_DECL_ECVT@
HAVE_DECL_ENVIRON = @HAVE_DECL_ENVIRON@
+HAVE_DECL_EXECVPE = @HAVE_DECL_EXECVPE@
HAVE_DECL_FCHDIR = @HAVE_DECL_FCHDIR@
+HAVE_DECL_FCLOSEALL = @HAVE_DECL_FCLOSEALL@
+HAVE_DECL_FCVT = @HAVE_DECL_FCVT@
HAVE_DECL_FDATASYNC = @HAVE_DECL_FDATASYNC@
HAVE_DECL_FDOPENDIR = @HAVE_DECL_FDOPENDIR@
HAVE_DECL_FPURGE = @HAVE_DECL_FPURGE@
HAVE_DECL_FSEEKO = @HAVE_DECL_FSEEKO@
HAVE_DECL_FTELLO = @HAVE_DECL_FTELLO@
+HAVE_DECL_GCVT = @HAVE_DECL_GCVT@
HAVE_DECL_GETDELIM = @HAVE_DECL_GETDELIM@
HAVE_DECL_GETDOMAINNAME = @HAVE_DECL_GETDOMAINNAME@
HAVE_DECL_GETLINE = @HAVE_DECL_GETLINE@
@@ -621,6 +631,7 @@ HAVE_PDUMPER = @HAVE_PDUMPER@
HAVE_PIPE = @HAVE_PIPE@
HAVE_PIPE2 = @HAVE_PIPE2@
HAVE_POPEN = @HAVE_POPEN@
+HAVE_POSIX_MEMALIGN = @HAVE_POSIX_MEMALIGN@
HAVE_POSIX_OPENPT = @HAVE_POSIX_OPENPT@
HAVE_POSIX_SIGNALBLOCKING = @HAVE_POSIX_SIGNALBLOCKING@
HAVE_PREAD = @HAVE_PREAD@
@@ -863,6 +874,7 @@ PTRDIFF_T_SUFFIX = @PTRDIFF_T_SUFFIX@
RALLOC_OBJ = @RALLOC_OBJ@
RANLIB = @RANLIB@
REPLACE_ACCESS = @REPLACE_ACCESS@
+REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@
REPLACE_CALLOC = @REPLACE_CALLOC@
REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@
REPLACE_CHOWN = @REPLACE_CHOWN@
@@ -885,6 +897,7 @@ REPLACE_FFLUSH = @REPLACE_FFLUSH@
REPLACE_FOPEN = @REPLACE_FOPEN@
REPLACE_FPRINTF = @REPLACE_FPRINTF@
REPLACE_FPURGE = @REPLACE_FPURGE@
+REPLACE_FREE = @REPLACE_FREE@
REPLACE_FREOPEN = @REPLACE_FREOPEN@
REPLACE_FSEEK = @REPLACE_FSEEK@
REPLACE_FSEEKO = @REPLACE_FSEEKO@
@@ -932,6 +945,7 @@ REPLACE_OPENAT = @REPLACE_OPENAT@
REPLACE_OPENDIR = @REPLACE_OPENDIR@
REPLACE_PERROR = @REPLACE_PERROR@
REPLACE_POPEN = @REPLACE_POPEN@
+REPLACE_POSIX_MEMALIGN = @REPLACE_POSIX_MEMALIGN@
REPLACE_PREAD = @REPLACE_PREAD@
REPLACE_PRINTF = @REPLACE_PRINTF@
REPLACE_PSELECT = @REPLACE_PSELECT@
@@ -1101,12 +1115,15 @@ gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1 = @gl_GNULIB_ENABLED_a9786850
gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36 = @gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36@
gl_GNULIB_ENABLED_cloexec = @gl_GNULIB_ENABLED_cloexec@
gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@
+gl_GNULIB_ENABLED_ef07dc4b3077c11ea9cef586db4e5955 = @gl_GNULIB_ENABLED_ef07dc4b3077c11ea9cef586db4e5955@
gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@
gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
+gl_GNULIB_ENABLED_idx = @gl_GNULIB_ENABLED_idx@
gl_GNULIB_ENABLED_lchmod = @gl_GNULIB_ENABLED_lchmod@
-gl_GNULIB_ENABLED_malloca = @gl_GNULIB_ENABLED_malloca@
gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@
+gl_GNULIB_ENABLED_rawmemchr = @gl_GNULIB_ENABLED_rawmemchr@
+gl_GNULIB_ENABLED_scratch_buffer = @gl_GNULIB_ENABLED_scratch_buffer@
gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
gl_GNULIB_ENABLED_utimens = @gl_GNULIB_ENABLED_utimens@
gl_LIBOBJS = @gl_LIBOBJS@
@@ -1512,6 +1529,17 @@ EXTRA_libgnu_a_SOURCES += dup2.c
endif
## end gnulib module dup2
+## begin gnulib module eloop-threshold
+ifeq (,$(OMIT_GNULIB_MODULE_eloop-threshold))
+
+ifneq (,$(gl_GNULIB_ENABLED_925677f0343de64b89a9f0c790b4104c))
+
+endif
+EXTRA_DIST += eloop-threshold.h
+
+endif
+## end gnulib module eloop-threshold
+
## begin gnulib module errno
ifeq (,$(OMIT_GNULIB_MODULE_errno))
@@ -1731,6 +1759,17 @@ EXTRA_libgnu_a_SOURCES += fpending.c
endif
## end gnulib module fpending
+## begin gnulib module free-posix
+ifeq (,$(OMIT_GNULIB_MODULE_free-posix))
+
+
+EXTRA_DIST += free.c
+
+EXTRA_libgnu_a_SOURCES += free.c
+
+endif
+## end gnulib module free-posix
+
## begin gnulib module fstatat
ifeq (,$(OMIT_GNULIB_MODULE_fstatat))
@@ -1912,6 +1951,16 @@ EXTRA_libgnu_a_SOURCES += group-member.c
endif
## end gnulib module group-member
+## begin gnulib module idx
+ifeq (,$(OMIT_GNULIB_MODULE_idx))
+
+ifneq (,$(gl_GNULIB_ENABLED_idx))
+libgnu_a_SOURCES += idx.h
+
+endif
+endif
+## end gnulib module idx
+
## begin gnulib module ieee754-h
ifeq (,$(OMIT_GNULIB_MODULE_ieee754-h))
@@ -2094,18 +2143,6 @@ EXTRA_libgnu_a_SOURCES += lstat.c
endif
## end gnulib module lstat
-## begin gnulib module malloca
-ifeq (,$(OMIT_GNULIB_MODULE_malloca))
-
-ifneq (,$(gl_GNULIB_ENABLED_malloca))
-libgnu_a_SOURCES += malloca.c
-
-endif
-EXTRA_DIST += malloca.h
-
-endif
-## end gnulib module malloca
-
## begin gnulib module memmem-simple
ifeq (,$(OMIT_GNULIB_MODULE_memmem-simple))
@@ -2263,6 +2300,19 @@ libgnu_a_SOURCES += qcopy-acl.c
endif
## end gnulib module qcopy-acl
+## begin gnulib module rawmemchr
+ifeq (,$(OMIT_GNULIB_MODULE_rawmemchr))
+
+ifneq (,$(gl_GNULIB_ENABLED_rawmemchr))
+
+endif
+EXTRA_DIST += rawmemchr.c rawmemchr.valgrind
+
+EXTRA_libgnu_a_SOURCES += rawmemchr.c
+
+endif
+## end gnulib module rawmemchr
+
## begin gnulib module readlink
ifeq (,$(OMIT_GNULIB_MODULE_readlink))
@@ -2307,6 +2357,18 @@ EXTRA_DIST += root-uid.h
endif
## end gnulib module root-uid
+## begin gnulib module scratch_buffer
+ifeq (,$(OMIT_GNULIB_MODULE_scratch_buffer))
+
+ifneq (,$(gl_GNULIB_ENABLED_scratch_buffer))
+libgnu_a_SOURCES += malloc/scratch_buffer_grow.c malloc/scratch_buffer_grow_preserve.c malloc/scratch_buffer_set_array_size.c
+
+endif
+EXTRA_DIST += malloc/scratch_buffer.h scratch_buffer.h
+
+endif
+## end gnulib module scratch_buffer
+
## begin gnulib module sig2str
ifeq (,$(OMIT_GNULIB_MODULE_sig2str))
@@ -2618,7 +2680,8 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
-e 's/@''GNULIB_VSNPRINTF''@/$(GNULIB_VSNPRINTF)/g' \
-e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GNULIB_VSPRINTF_POSIX)/g' \
< $(srcdir)/stdio.in.h | \
- sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \
+ sed -e 's|@''HAVE_DECL_FCLOSEALL''@|$(HAVE_DECL_FCLOSEALL)|g' \
+ -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \
-e 's|@''HAVE_DECL_FSEEKO''@|$(HAVE_DECL_FSEEKO)|g' \
-e 's|@''HAVE_DECL_FTELLO''@|$(HAVE_DECL_FTELLO)|g' \
-e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \
@@ -2696,9 +2759,11 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
-e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \
-e 's/@''GNULIB__EXIT''@/$(GNULIB__EXIT)/g' \
+ -e 's/@''GNULIB_ALIGNED_ALLOC''@/$(GNULIB_ALIGNED_ALLOC)/g' \
-e 's/@''GNULIB_ATOLL''@/$(GNULIB_ATOLL)/g' \
-e 's/@''GNULIB_CALLOC_POSIX''@/$(GNULIB_CALLOC_POSIX)/g' \
-e 's/@''GNULIB_CANONICALIZE_FILE_NAME''@/$(GNULIB_CANONICALIZE_FILE_NAME)/g' \
+ -e 's/@''GNULIB_FREE_POSIX''@/$(GNULIB_FREE_POSIX)/g' \
-e 's/@''GNULIB_GETLOADAVG''@/$(GNULIB_GETLOADAVG)/g' \
-e 's/@''GNULIB_GETSUBOPT''@/$(GNULIB_GETSUBOPT)/g' \
-e 's/@''GNULIB_GRANTPT''@/$(GNULIB_GRANTPT)/g' \
@@ -2709,6 +2774,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's/@''GNULIB_MKOSTEMPS''@/$(GNULIB_MKOSTEMPS)/g' \
-e 's/@''GNULIB_MKSTEMP''@/$(GNULIB_MKSTEMP)/g' \
-e 's/@''GNULIB_MKSTEMPS''@/$(GNULIB_MKSTEMPS)/g' \
+ -e 's/@''GNULIB_POSIX_MEMALIGN''@/$(GNULIB_POSIX_MEMALIGN)/g' \
-e 's/@''GNULIB_POSIX_OPENPT''@/$(GNULIB_POSIX_OPENPT)/g' \
-e 's/@''GNULIB_PTSNAME''@/$(GNULIB_PTSNAME)/g' \
-e 's/@''GNULIB_PTSNAME_R''@/$(GNULIB_PTSNAME_R)/g' \
@@ -2732,8 +2798,12 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's/@''GNULIB_WCTOMB''@/$(GNULIB_WCTOMB)/g' \
< $(srcdir)/stdlib.in.h | \
sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \
+ -e 's|@''HAVE_ALIGNED_ALLOC''@|$(HAVE_ALIGNED_ALLOC)|g' \
-e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \
-e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \
+ -e 's|@''HAVE_DECL_ECVT''@|$(HAVE_DECL_ECVT)|g' \
+ -e 's|@''HAVE_DECL_FCVT''@|$(HAVE_DECL_FCVT)|g' \
+ -e 's|@''HAVE_DECL_GCVT''@|$(HAVE_DECL_GCVT)|g' \
-e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
-e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
-e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \
@@ -2745,6 +2815,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \
-e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \
-e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \
+ -e 's|@''HAVE_POSIX_MEMALIGN''@|$(HAVE_POSIX_MEMALIGN)|g' \
-e 's|@''HAVE_POSIX_OPENPT''@|$(HAVE_POSIX_OPENPT)|g' \
-e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \
-e 's|@''HAVE_PTSNAME_R''@|$(HAVE_PTSNAME_R)|g' \
@@ -2767,12 +2838,15 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
-e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \
-e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \
+ -e 's|@''REPLACE_ALIGNED_ALLOC''@|$(REPLACE_ALIGNED_ALLOC)|g' \
-e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
-e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
+ -e 's|@''REPLACE_FREE''@|$(REPLACE_FREE)|g' \
-e 's|@''REPLACE_INITSTATE''@|$(REPLACE_INITSTATE)|g' \
-e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \
-e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \
-e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
+ -e 's|@''REPLACE_POSIX_MEMALIGN''@|$(REPLACE_POSIX_MEMALIGN)|g' \
-e 's|@''REPLACE_PTSNAME''@|$(REPLACE_PTSNAME)|g' \
-e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \
-e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
@@ -3412,6 +3486,7 @@ unistd.h: unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \
-e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \
-e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \
+ -e 's|@''HAVE_DECL_EXECVPE''@|$(HAVE_DECL_EXECVPE)|g' \
-e 's|@''HAVE_DECL_FCHDIR''@|$(HAVE_DECL_FCHDIR)|g' \
-e 's|@''HAVE_DECL_FDATASYNC''@|$(HAVE_DECL_FDATASYNC)|g' \
-e 's|@''HAVE_DECL_GETDOMAINNAME''@|$(HAVE_DECL_GETDOMAINNAME)|g' \
diff --git a/lib/idx.h b/lib/idx.h
new file mode 100644
index 00000000000..6a7739fa9c7
--- /dev/null
+++ b/lib/idx.h
@@ -0,0 +1,113 @@
+/* A type for indices and sizes.
+
+ Copyright (C) 2020 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 <https://www.gnu.org/licenses/>. */
+
+#ifndef _IDX_H
+#define _IDX_H
+
+/* Get ptrdiff_t. */
+#include <stddef.h>
+
+/* Get PTRDIFF_MAX. */
+#include <stdint.h>
+
+/* The type 'idx_t' holds an (array) index or an (object) size.
+ Its implementation promotes to a signed integer type,
+ which can hold the values
+ 0..2^63-1 (on 64-bit platforms) or
+ 0..2^31-1 (on 32-bit platforms).
+
+ Why a signed integer type?
+
+ * Security: Signed types can be checked for overflow via
+ '-fsanitize=undefined', but unsigned types cannot.
+
+ * Comparisons without surprises: ISO C99 § 6.3.1.8 specifies a few
+ surprising results for comparisons, such as
+
+ (int) -3 < (unsigned long) 7 => false
+ (int) -3 < (unsigned int) 7 => false
+ and on 32-bit machines:
+ (long) -3 < (unsigned int) 7 => false
+
+ This is surprising because the natural comparison order is by
+ value in the realm of infinite-precision signed integers (ℤ).
+
+ The best way to get rid of such surprises is to use signed types
+ for numerical integer values, and use unsigned types only for
+ bit masks and enums.
+
+ Why not use 'size_t' directly?
+
+ * Because 'size_t' is an unsigned type, and a signed type is better.
+ See above.
+
+ Why not use 'ptrdiff_t' directly?
+
+ * Maintainability: When reading and modifying code, it helps to know that
+ a certain variable cannot have negative values. For example, when you
+ have a loop
+
+ int n = ...;
+ for (int i = 0; i < n; i++) ...
+
+ or
+
+ ptrdiff_t n = ...;
+ for (ptrdiff_t i = 0; i < n; i++) ...
+
+ you have to ask yourself "what if n < 0?". Whereas in
+
+ idx_t n = ...;
+ for (idx_t i = 0; i < n; i++) ...
+
+ you know that this case cannot happen.
+
+ Similarly, when a programmer writes
+
+ idx_t = ptr2 - ptr1;
+
+ there is an implied assertion that ptr1 and ptr2 point into the same
+ object and that ptr1 <= ptr2.
+
+ * Being future-proof: In the future, range types (integers which are
+ constrained to a certain range of values) may be added to C compilers
+ or to the C standard. Several programming languages (Ada, Haskell,
+ Common Lisp, Pascal) already have range types. Such range types may
+ help producing good code and good warnings. The type 'idx_t' could
+ then be typedef'ed to a range type that is signed after promotion. */
+
+/* In the future, idx_t could be typedef'ed to a signed range type.
+ The clang "extended integer types", supported in Clang 11 or newer
+ <https://clang.llvm.org/docs/LanguageExtensions.html#extended-integer-types>,
+ are a special case of range types. However, these types don't support binary
+ operators with plain integer types (e.g. expressions such as x > 1).
+ Therefore, they don't behave like signed types (and not like unsigned types
+ either). So, we cannot use them here. */
+
+/* Use the signed type 'ptrdiff_t'. */
+/* Note: ISO C does not mandate that 'size_t' and 'ptrdiff_t' have the same
+ size, but it is so on all platforms we have seen since 1990. */
+typedef ptrdiff_t idx_t;
+
+/* IDX_MAX is the maximum value of an idx_t. */
+#define IDX_MAX PTRDIFF_MAX
+
+/* So far no need has been found for an IDX_WIDTH macro.
+ Perhaps there should be another macro IDX_VALUE_BITS that does not
+ count the sign bit and is therefore one less than PTRDIFF_WIDTH. */
+
+#endif /* _IDX_H */
diff --git a/lib/intprops.h b/lib/intprops.h
index b27f2eea056..bc2107c9295 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -226,7 +226,9 @@
/* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
(A, B, P) work when P is non-null. */
-#if 5 <= __GNUC__ && !defined __ICC
+/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
+ see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>. */
+#if 7 <= __GNUC__ && !defined __ICC
# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
#elif defined __has_builtin
# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
@@ -244,7 +246,17 @@
/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
__builtin_sub_overflow_p and __builtin_mul_overflow_p. */
-#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+#if defined __clang__ || defined __ICC
+/* Clang 11 lacks __builtin_mul_overflow_p, and even if it did it
+ would presumably run afoul of Clang bug 16404. ICC 2021.1's
+ __builtin_add_overflow_p etc. are not treated as integral constant
+ expressions even when all arguments are. */
+# define _GL_HAS_BUILTIN_OVERFLOW_P 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p)
+#else
+# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
+#endif
/* The _GL*_OVERFLOW macros have the same restrictions as the
*_RANGE_OVERFLOW macros, except that they do not assume that operands
@@ -377,8 +389,9 @@
_GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
#endif
#if _GL_HAS_BUILTIN_MUL_OVERFLOW
-# if (9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
- || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__))
+# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
+ || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \
+ && !defined __ICC)
# define INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
# else
/* Work around GCC bug 91450. */
@@ -585,4 +598,33 @@
: (tmin) / (a) < (b)) \
: (tmax) / (b) < (a)))
+/* The following macros compute A + B, A - B, and A * B, respectively.
+ If no overflow occurs, they set *R to the result and return 1;
+ otherwise, they return 0 and may modify *R.
+
+ Example usage:
+
+ long int result;
+ if (INT_ADD_OK (a, b, &result))
+ printf ("result is %ld\n", result);
+ else
+ printf ("overflow\n");
+
+ A, B, and *R should be integers; they need not be the same type,
+ and they need not be all signed or all unsigned.
+
+ These macros work correctly on all known practical hosts, and do not rely
+ on undefined behavior due to signed arithmetic overflow.
+
+ These macros are not constant expressions.
+
+ These macros may evaluate their arguments zero or multiple times, so the
+ arguments should not have side effects.
+
+ These macros are tuned for B being a constant. */
+
+#define INT_ADD_OK(a, b, r) ! INT_ADD_WRAPV (a, b, r)
+#define INT_SUBTRACT_OK(a, b, r) ! INT_SUBTRACT_WRAPV (a, b, r)
+#define INT_MULTIPLY_OK(a, b, r) ! INT_MULTIPLY_WRAPV (a, b, r)
+
#endif /* _GL_INTPROPS_H */
diff --git a/lib/malloc/scratch_buffer.h b/lib/malloc/scratch_buffer.h
new file mode 100644
index 00000000000..b40478637c8
--- /dev/null
+++ b/lib/malloc/scratch_buffer.h
@@ -0,0 +1,135 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _SCRATCH_BUFFER_H
+#define _SCRATCH_BUFFER_H
+
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer {
+ void *data; /* Pointer to the beginning of the scratch area. */
+ size_t length; /* Allocated space at the data pointer, in bytes. */
+ union { max_align_t __align; char __c[1024]; } __space;
+};
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+static inline void
+scratch_buffer_init (struct scratch_buffer *buffer)
+{
+ buffer->data = buffer->__space.__c;
+ buffer->length = sizeof (buffer->__space);
+}
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+static inline void
+scratch_buffer_free (struct scratch_buffer *buffer)
+{
+ if (buffer->data != buffer->__space.__c)
+ free (buffer->data);
+}
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+bool __libc_scratch_buffer_grow (struct scratch_buffer *buffer);
+libc_hidden_proto (__libc_scratch_buffer_grow)
+
+/* Alias for __libc_scratch_buffer_grow. */
+static __always_inline bool
+scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+ return __glibc_likely (__libc_scratch_buffer_grow (buffer));
+}
+
+/* Like __libc_scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+bool __libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+libc_hidden_proto (__libc_scratch_buffer_grow_preserve)
+
+/* Alias for __libc_scratch_buffer_grow_preserve. */
+static __always_inline bool
+scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+ return __glibc_likely (__libc_scratch_buffer_grow_preserve (buffer));
+}
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+bool __libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+libc_hidden_proto (__libc_scratch_buffer_set_array_size)
+
+/* Alias for __libc_scratch_set_array_size. */
+static __always_inline bool
+scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size)
+{
+ return __glibc_likely (__libc_scratch_buffer_set_array_size
+ (buffer, nelem, size));
+}
+
+#endif /* _SCRATCH_BUFFER_H */
diff --git a/lib/malloc/scratch_buffer_grow.c b/lib/malloc/scratch_buffer_grow.c
new file mode 100644
index 00000000000..41befe3d65f
--- /dev/null
+++ b/lib/malloc/scratch_buffer_grow.c
@@ -0,0 +1,56 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+
+bool
+__libc_scratch_buffer_grow (struct scratch_buffer *buffer)
+{
+ void *new_ptr;
+ size_t new_length = buffer->length * 2;
+
+ /* Discard old buffer. */
+ scratch_buffer_free (buffer);
+
+ /* Check for overflow. */
+ if (__glibc_likely (new_length >= buffer->length))
+ new_ptr = malloc (new_length);
+ else
+ {
+ __set_errno (ENOMEM);
+ new_ptr = NULL;
+ }
+
+ if (__glibc_unlikely (new_ptr == NULL))
+ {
+ /* Buffer must remain valid to free. */
+ scratch_buffer_init (buffer);
+ return false;
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow)
diff --git a/lib/malloc/scratch_buffer_grow_preserve.c b/lib/malloc/scratch_buffer_grow_preserve.c
new file mode 100644
index 00000000000..aef232938d5
--- /dev/null
+++ b/lib/malloc/scratch_buffer_grow_preserve.c
@@ -0,0 +1,67 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+#include <string.h>
+
+bool
+__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer)
+{
+ size_t new_length = 2 * buffer->length;
+ void *new_ptr;
+
+ if (buffer->data == buffer->__space.__c)
+ {
+ /* Move buffer to the heap. No overflow is possible because
+ buffer->length describes a small buffer on the stack. */
+ new_ptr = malloc (new_length);
+ if (new_ptr == NULL)
+ return false;
+ memcpy (new_ptr, buffer->__space.__c, buffer->length);
+ }
+ else
+ {
+ /* Buffer was already on the heap. Check for overflow. */
+ if (__glibc_likely (new_length >= buffer->length))
+ new_ptr = realloc (buffer->data, new_length);
+ else
+ {
+ __set_errno (ENOMEM);
+ new_ptr = NULL;
+ }
+
+ if (__glibc_unlikely (new_ptr == NULL))
+ {
+ /* Deallocate, but buffer must remain valid to free. */
+ free (buffer->data);
+ scratch_buffer_init (buffer);
+ return false;
+ }
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_grow_preserve)
diff --git a/lib/malloc/scratch_buffer_set_array_size.c b/lib/malloc/scratch_buffer_set_array_size.c
new file mode 100644
index 00000000000..5f5e4c24f5a
--- /dev/null
+++ b/lib/malloc/scratch_buffer_set_array_size.c
@@ -0,0 +1,64 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2015-2020 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
+#include <scratch_buffer.h>
+#include <errno.h>
+#include <limits.h>
+
+bool
+__libc_scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size)
+{
+ size_t new_length = nelem * size;
+
+ /* Avoid overflow check if both values are small. */
+ if ((nelem | size) >> (sizeof (size_t) * CHAR_BIT / 2) != 0
+ && nelem != 0 && size != new_length / nelem)
+ {
+ /* Overflow. Discard the old buffer, but it must remain valid
+ to free. */
+ scratch_buffer_free (buffer);
+ scratch_buffer_init (buffer);
+ __set_errno (ENOMEM);
+ return false;
+ }
+
+ if (new_length <= buffer->length)
+ return true;
+
+ /* Discard old buffer. */
+ scratch_buffer_free (buffer);
+
+ char *new_ptr = malloc (new_length);
+ if (new_ptr == NULL)
+ {
+ /* Buffer must remain valid to free. */
+ scratch_buffer_init (buffer);
+ return false;
+ }
+
+ /* Install new heap-based buffer. */
+ buffer->data = new_ptr;
+ buffer->length = new_length;
+ return true;
+}
+libc_hidden_def (__libc_scratch_buffer_set_array_size)
diff --git a/lib/mini-gmp.c b/lib/mini-gmp.c
index 2e0301b0081..d34fe525e4c 100644
--- a/lib/mini-gmp.c
+++ b/lib/mini-gmp.c
@@ -32,7 +32,7 @@ see https://www.gnu.org/licenses/. */
/* NOTE: All functions in this file which are not declared in
mini-gmp.h are internal, and are not intended to be compatible
- neither with GMP nor with future versions of mini-gmp. */
+ with GMP or with future versions of mini-gmp. */
/* Much of the material copied from GMP files, including: gmp-impl.h,
longlong.h, mpn/generic/add_n.c, mpn/generic/addmul_1.c,
@@ -1331,29 +1331,26 @@ mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
unsigned bits)
{
mp_size_t rn;
- size_t j;
+ mp_limb_t limb;
unsigned shift;
- for (j = sn, rn = 0, shift = 0; j-- > 0; )
+ for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
{
- if (shift == 0)
- {
- rp[rn++] = sp[j];
- shift += bits;
- }
- else
+ limb |= (mp_limb_t) sp[sn] << shift;
+ shift += bits;
+ if (shift >= GMP_LIMB_BITS)
{
- rp[rn-1] |= (mp_limb_t) sp[j] << shift;
- shift += bits;
- if (shift >= GMP_LIMB_BITS)
- {
- shift -= GMP_LIMB_BITS;
- if (shift > 0)
- rp[rn++] = (mp_limb_t) sp[j] >> (bits - shift);
- }
+ shift -= GMP_LIMB_BITS;
+ rp[rn++] = limb;
+ /* Next line is correct also if shift == 0,
+ bits == 8, and mp_limb_t == unsigned char. */
+ limb = (unsigned int) sp[sn] >> (bits - shift);
}
}
- rn = mpn_normalized_size (rp, rn);
+ if (limb != 0)
+ rp[rn++] = limb;
+ else
+ rn = mpn_normalized_size (rp, rn);
return rn;
}
@@ -2723,7 +2720,7 @@ mpz_make_odd (mpz_t r)
assert (r->_mp_size > 0);
/* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
- shift = mpn_common_scan (r->_mp_d[0], 0, r->_mp_d, 0, 0);
+ shift = mpn_scan1 (r->_mp_d, 0);
mpz_tdiv_q_2exp (r, r, shift);
return shift;
@@ -2780,9 +2777,13 @@ mpz_gcd (mpz_t g, const mpz_t u, const mpz_t v)
if (tv->_mp_size == 1)
{
- mp_limb_t vl = tv->_mp_d[0];
- mp_limb_t ul = mpz_tdiv_ui (tu, vl);
- mpz_set_ui (g, mpn_gcd_11 (ul, vl));
+ mp_limb_t *gp;
+
+ mpz_tdiv_r (tu, tu, tv);
+ gp = MPZ_REALLOC (g, 1); /* gp = mpz_limbs_modify (g, 1); */
+ *gp = mpn_gcd_11 (tu->_mp_d[0], tv->_mp_d[0]);
+
+ g->_mp_size = *gp != 0; /* mpz_limbs_finish (g, 1); */
break;
}
mpz_sub (tu, tu, tv);
@@ -2871,7 +2872,6 @@ mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v)
* s0 = 0, s1 = 2^vz
*/
- mpz_setbit (t0, uz);
mpz_tdiv_qr (t1, tu, tu, tv);
mpz_mul_2exp (t1, t1, uz);
@@ -2882,8 +2882,7 @@ mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v)
{
mp_bitcnt_t shift;
shift = mpz_make_odd (tu);
- mpz_mul_2exp (t0, t0, shift);
- mpz_mul_2exp (s0, s0, shift);
+ mpz_setbit (t0, uz + shift);
power += shift;
for (;;)
@@ -2921,6 +2920,8 @@ mpz_gcdext (mpz_t g, mpz_t s, mpz_t t, const mpz_t u, const mpz_t v)
power += shift;
}
}
+ else
+ mpz_setbit (t0, uz);
/* Now tv = odd part of gcd, and -s0 and t0 are corresponding
cofactors. */
@@ -3604,7 +3605,8 @@ mpz_probab_prime_p (const mpz_t n, int reps)
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
mpz_abs (nm1, n);
nm1->_mp_d[0] -= 1;
- k = mpz_scan1 (nm1, 0);
+ /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
+ k = mpn_scan1 (nm1->_mp_d, 0);
mpz_tdiv_q_2exp (q, nm1, k);
/* BPSW test */
@@ -4301,7 +4303,7 @@ mpz_get_str (char *sp, int base, const mpz_t u)
ret:
sp[sn] = '\0';
if (osn && osn != sn + 1)
- sp = gmp_realloc(sp, osn, sn + 1);
+ sp = (char*) gmp_realloc (sp, osn, sn + 1);
return sp;
}
@@ -4425,6 +4427,8 @@ mpz_out_str (FILE *stream, int base, const mpz_t x)
size_t len, n;
str = mpz_get_str (NULL, base, x);
+ if (!str)
+ return 0;
len = strlen (str);
n = fwrite (str, 1, len, stream);
gmp_free (str, len + 1);
diff --git a/lib/mini-gmp.h b/lib/mini-gmp.h
index c00568c2568..59a37e64947 100644
--- a/lib/mini-gmp.h
+++ b/lib/mini-gmp.h
@@ -1,6 +1,6 @@
/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
-Copyright 2011-2015, 2017, 2019 Free Software Foundation, Inc.
+Copyright 2011-2015, 2017, 2019-2020 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -295,7 +295,8 @@ int mpz_init_set_str (mpz_t, const char *, int);
|| defined (_MSL_STDIO_H) /* Metrowerks */ \
|| defined (_STDIO_H_INCLUDED) /* QNX4 */ \
|| defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
- || defined (__STDIO_LOADED) /* VMS */
+ || defined (__STDIO_LOADED) /* VMS */ \
+ || defined (__DEFINED_FILE) /* musl */
size_t mpz_out_str (FILE *, int, const mpz_t);
#endif
diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c
new file mode 100644
index 00000000000..04bf08415c6
--- /dev/null
+++ b/lib/rawmemchr.c
@@ -0,0 +1,136 @@
+/* Searching in a string.
+ Copyright (C) 2008-2020 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <string.h>
+
+/* Find the first occurrence of C in S. */
+void *
+rawmemchr (const void *s, int c_in)
+{
+ /* On 32-bit hardware, choosing longword to be a 32-bit unsigned
+ long instead of a 64-bit uintmax_t tends to give better
+ performance. On 64-bit hardware, unsigned long is generally 64
+ bits already. Change this typedef to experiment with
+ performance. */
+ typedef unsigned long int longword;
+
+ const unsigned char *char_ptr;
+ const longword *longword_ptr;
+ longword repeated_one;
+ longword repeated_c;
+ unsigned char c;
+
+ c = (unsigned char) c_in;
+
+ /* Handle the first few bytes by reading one byte at a time.
+ Do this until CHAR_PTR is aligned on a longword boundary. */
+ for (char_ptr = (const unsigned char *) s;
+ (size_t) char_ptr % sizeof (longword) != 0;
+ ++char_ptr)
+ if (*char_ptr == c)
+ return (void *) char_ptr;
+
+ longword_ptr = (const longword *) char_ptr;
+
+ /* All these elucidatory comments refer to 4-byte longwords,
+ but the theory applies equally well to any size longwords. */
+
+ /* Compute auxiliary longword values:
+ repeated_one is a value which has a 1 in every byte.
+ repeated_c has c in every byte. */
+ repeated_one = 0x01010101;
+ repeated_c = c | (c << 8);
+ repeated_c |= repeated_c << 16;
+ if (0xffffffffU < (longword) -1)
+ {
+ repeated_one |= repeated_one << 31 << 1;
+ repeated_c |= repeated_c << 31 << 1;
+ if (8 < sizeof (longword))
+ {
+ size_t i;
+
+ for (i = 64; i < sizeof (longword) * 8; i *= 2)
+ {
+ repeated_one |= repeated_one << i;
+ repeated_c |= repeated_c << i;
+ }
+ }
+ }
+
+ /* Instead of the traditional loop which tests each byte, we will
+ test a longword at a time. The tricky part is testing if *any of
+ the four* bytes in the longword in question are equal to NUL or
+ c. We first use an xor with repeated_c. This reduces the task
+ to testing whether *any of the four* bytes in longword1 is zero.
+
+ We compute tmp =
+ ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7).
+ That is, we perform the following operations:
+ 1. Subtract repeated_one.
+ 2. & ~longword1.
+ 3. & a mask consisting of 0x80 in every byte.
+ Consider what happens in each byte:
+ - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff,
+ and step 3 transforms it into 0x80. A carry can also be propagated
+ to more significant bytes.
+ - If a byte of longword1 is nonzero, let its lowest 1 bit be at
+ position k (0 <= k <= 7); so the lowest k bits are 0. After step 1,
+ the byte ends in a single bit of value 0 and k bits of value 1.
+ After step 2, the result is just k bits of value 1: 2^k - 1. After
+ step 3, the result is 0. And no carry is produced.
+ So, if longword1 has only non-zero bytes, tmp is zero.
+ Whereas if longword1 has a zero byte, call j the position of the least
+ significant zero byte. Then the result has a zero at positions 0, ...,
+ j-1 and a 0x80 at position j. We cannot predict the result at the more
+ significant bytes (positions j+1..3), but it does not matter since we
+ already have a non-zero bit at position 8*j+7.
+
+ The test whether any byte in longword1 is zero is equivalent
+ to testing whether tmp is nonzero.
+
+ This test can read beyond the end of a string, depending on where
+ C_IN is encountered. However, this is considered safe since the
+ initialization phase ensured that the read will be aligned,
+ therefore, the read will not cross page boundaries and will not
+ cause a fault. */
+
+ while (1)
+ {
+ longword longword1 = *longword_ptr ^ repeated_c;
+
+ if ((((longword1 - repeated_one) & ~longword1)
+ & (repeated_one << 7)) != 0)
+ break;
+ longword_ptr++;
+ }
+
+ char_ptr = (const unsigned char *) longword_ptr;
+
+ /* At this point, we know that one of the sizeof (longword) bytes
+ starting at char_ptr is == c. On little-endian machines, we
+ could determine the first such byte without any further memory
+ accesses, just by looking at the tmp result from the last loop
+ iteration. But this does not work on big-endian machines.
+ Choose code that works in both cases. */
+
+ char_ptr = (unsigned char *) longword_ptr;
+ while (*char_ptr != c)
+ char_ptr++;
+ return (void *) char_ptr;
+}
diff --git a/lib/rawmemchr.valgrind b/lib/rawmemchr.valgrind
new file mode 100644
index 00000000000..53c5b317d5f
--- /dev/null
+++ b/lib/rawmemchr.valgrind
@@ -0,0 +1,28 @@
+# Suppress a valgrind message about use of uninitialized memory in rawmemchr().
+
+# Copyright (C) 2008-2020 Free Software Foundation, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR 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 <https://www.gnu.org/licenses/>.
+
+# This use is OK because it provides only a speedup.
+{
+ rawmemchr-value4
+ Memcheck:Value4
+ fun:rawmemchr
+}
+{
+ rawmemchr-value8
+ Memcheck:Value8
+ fun:rawmemchr
+}
diff --git a/lib/readlink.c b/lib/readlink.c
index 4d392ef6995..531913eba3e 100644
--- a/lib/readlink.c
+++ b/lib/readlink.c
@@ -1,4 +1,4 @@
-/* Stub for readlink().
+/* Read the contents of a symbolic link.
Copyright (C) 2003-2007, 2009-2020 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
@@ -29,7 +29,7 @@
such as DJGPP 2.03 and mingw32. */
ssize_t
-readlink (const char *name, char *buf _GL_UNUSED,
+readlink (char const *file, char *buf _GL_UNUSED,
size_t bufsize _GL_UNUSED)
{
struct stat statbuf;
@@ -37,7 +37,7 @@ readlink (const char *name, char *buf _GL_UNUSED,
/* In general we should use lstat() here, not stat(). But on platforms
without symbolic links, lstat() - if it exists - would be equivalent to
stat(), therefore we can use stat(). This saves us a configure check. */
- if (stat (name, &statbuf) >= 0)
+ if (stat (file, &statbuf) >= 0)
errno = EINVAL;
return -1;
}
@@ -51,24 +51,54 @@ readlink (const char *name, char *buf _GL_UNUSED,
for Solaris 9. */
ssize_t
-rpl_readlink (const char *name, char *buf, size_t bufsize)
+rpl_readlink (char const *file, char *buf, size_t bufsize)
{
# if READLINK_TRAILING_SLASH_BUG
- size_t len = strlen (name);
- if (len && name[len - 1] == '/')
+ size_t file_len = strlen (file);
+ if (file_len && file[file_len - 1] == '/')
{
- /* Even if name without the slash is a symlink to a directory,
+ /* Even if FILE without the slash is a symlink to a directory,
both lstat() and stat() must resolve the trailing slash to
the directory rather than the symlink. We can therefore
safely use stat() to distinguish between EINVAL and
ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */
struct stat st;
- if (stat (name, &st) == 0)
+ if (stat (file, &st) == 0 || errno == EOVERFLOW)
errno = EINVAL;
return -1;
}
# endif /* READLINK_TRAILING_SLASH_BUG */
- return readlink (name, buf, bufsize);
+
+ ssize_t r = readlink (file, buf, bufsize);
+
+# if READLINK_TRUNCATE_BUG
+ if (r < 0 && errno == ERANGE)
+ {
+ /* Try again with a bigger buffer. This is just for test cases;
+ real code invariably discards short reads. */
+ char stackbuf[4032];
+ r = readlink (file, stackbuf, sizeof stackbuf);
+ if (r < 0)
+ {
+ if (errno == ERANGE)
+ {
+ /* Clear the buffer, which is good enough for real code.
+ Thankfully, no test cases try short reads of enormous
+ symlinks and what would be the point anyway? */
+ r = bufsize;
+ memset (buf, 0, r);
+ }
+ }
+ else
+ {
+ if (bufsize < r)
+ r = bufsize;
+ memcpy (buf, stackbuf, r);
+ }
+ }
+# endif
+
+ return r;
}
#endif /* HAVE_READLINK */
diff --git a/lib/readlinkat.c b/lib/readlinkat.c
index 68ec65ebfc5..7a41208ebfd 100644
--- a/lib/readlinkat.c
+++ b/lib/readlinkat.c
@@ -28,10 +28,11 @@
#if HAVE_READLINKAT
+# undef fstatat
# undef readlinkat
ssize_t
-rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
+rpl_readlinkat (int fd, char const *file, char *buf, size_t bufsize)
{
# if READLINK_TRAILING_SLASH_BUG
size_t file_len = strlen (file);
@@ -40,15 +41,45 @@ rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
/* Even if FILE without the slash is a symlink to a directory,
both lstat() and stat() must resolve the trailing slash to
the directory rather than the symlink. We can therefore
- safely use stat() to distinguish between EINVAL and
- ENOTDIR/ENOENT, avoiding extra overhead of rpl_lstat(). */
+ safely use fstatat(..., 0) to distinguish between EINVAL and
+ ENOTDIR/ENOENT, avoiding extra overhead of rpl_fstatat(). */
struct stat st;
- if (stat (file, &st) == 0)
+ if (fstatat (fd, file, &st, 0) == 0 || errno == EOVERFLOW)
errno = EINVAL;
return -1;
}
# endif /* READLINK_TRAILING_SLASH_BUG */
- return readlinkat (fd, file, buf, len);
+
+ ssize_t r = readlinkat (fd, file, buf, bufsize);
+
+# if READLINK_TRUNCATE_BUG
+ if (r < 0 && errno == ERANGE)
+ {
+ /* Try again with a bigger buffer. This is just for test cases;
+ real code invariably discards short reads. */
+ char stackbuf[4032];
+ r = readlinkat (fd, file, stackbuf, sizeof stackbuf);
+ if (r < 0)
+ {
+ if (errno == ERANGE)
+ {
+ /* Clear the buffer, which is good enough for real code.
+ Thankfully, no test cases try short reads of enormous
+ symlinks and what would be the point anyway? */
+ r = bufsize;
+ memset (buf, 0, r);
+ }
+ }
+ else
+ {
+ if (bufsize < r)
+ r = bufsize;
+ memcpy (buf, stackbuf, r);
+ }
+ }
+# endif
+
+ return r;
}
#else
@@ -61,7 +92,7 @@ rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
readlinkat worthless since readlink does not guarantee a
NUL-terminated buffer. Assume this was a bug in POSIX. */
-/* Read the contents of symlink FILE into buffer BUF of size LEN, in the
+/* Read the contents of symlink FILE into buffer BUF of size BUFSIZE, in the
directory open on descriptor FD. If possible, do it without changing
the working directory. Otherwise, resort to using save_cwd/fchdir,
then readlink/restore_cwd. If either the save_cwd or the restore_cwd
@@ -69,8 +100,8 @@ rpl_readlinkat (int fd, char const *file, char *buf, size_t len)
# define AT_FUNC_NAME readlinkat
# define AT_FUNC_F1 readlink
-# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len
-# define AT_FUNC_POST_FILE_ARGS , buf, len
+# define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t bufsize
+# define AT_FUNC_POST_FILE_ARGS , buf, bufsize
# define AT_FUNC_RESULT ssize_t
# include "at-func.c"
# undef AT_FUNC_NAME
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index 2e217291468..bf9439e53fd 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -300,18 +300,20 @@ build_wcs_upper_buffer (re_string_t *pstr)
while (byte_idx < end_idx)
{
wchar_t wc;
+ unsigned char ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
- if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
- && mbsinit (&pstr->cur_state))
+ if (isascii (ch) && mbsinit (&pstr->cur_state))
{
- /* In case of a singlebyte character. */
- pstr->mbs[byte_idx]
- = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
/* The next step uses the assumption that wchar_t is encoded
ASCII-safe: all ASCII values can be converted like this. */
- pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
- ++byte_idx;
- continue;
+ wchar_t wcu = __towupper (ch);
+ if (isascii (wcu))
+ {
+ pstr->mbs[byte_idx] = wcu;
+ pstr->wcs[byte_idx] = wcu;
+ byte_idx++;
+ continue;
+ }
}
remain_len = end_idx - byte_idx;
@@ -348,7 +350,6 @@ build_wcs_upper_buffer (re_string_t *pstr)
{
/* It is an invalid character, an incomplete character
at the end of the string, or '\0'. Just use the byte. */
- int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
pstr->mbs[byte_idx] = ch;
/* And also cast it to wide char. */
pstr->wcs[byte_idx++] = (wchar_t) ch;
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index 0c72e3f7b01..7b50b478114 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -77,6 +77,14 @@
# define isblank(ch) ((ch) == ' ' || (ch) == '\t')
#endif
+/* regex code assumes isascii has its usual numeric meaning,
+ even if the portable character set uses EBCDIC encoding,
+ and even if wint_t is wider than int. */
+#ifndef _LIBC
+# undef isascii
+# define isascii(c) (((c) & ~0x7f) == 0)
+#endif
+
#ifdef _LIBC
# ifndef _RE_DEFINE_LOCALE_FUNCTIONS
# define _RE_DEFINE_LOCALE_FUNCTIONS 1
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
new file mode 100644
index 00000000000..0b45f92c105
--- /dev/null
+++ b/lib/scratch_buffer.h
@@ -0,0 +1,29 @@
+/* Variable-sized buffer with on-stack default allocation.
+ Copyright (C) 2017-2020 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR 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 <https://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert, 2017. */
+
+#ifndef _GL_SCRATCH_BUFFER_H
+#define _GL_SCRATCH_BUFFER_H
+
+#include <libc-config.h>
+
+#define __libc_scratch_buffer_grow gl_scratch_buffer_grow
+#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve
+#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size
+#include <malloc/scratch_buffer.h>
+
+#endif /* _GL_SCRATCH_BUFFER_H */
diff --git a/lib/signal.in.h b/lib/signal.in.h
index c94b053d6af..70a2d4af6ca 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -55,13 +55,13 @@
#ifndef _@GUARD_PREFIX@_SIGNAL_H
#define _@GUARD_PREFIX@_SIGNAL_H
-/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android
- declare pthread_sigmask in <pthread.h>, not in <signal.h>.
+/* Mac OS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6, Android,
+ OS/2 kLIBC declare pthread_sigmask in <pthread.h>, not in <signal.h>.
But avoid namespace pollution on glibc systems.*/
#if (@GNULIB_PTHREAD_SIGMASK@ || defined GNULIB_POSIXCHECK) \
&& ((defined __APPLE__ && defined __MACH__) \
|| defined __FreeBSD__ || defined __OpenBSD__ || defined __osf__ \
- || defined __sun || defined __ANDROID__) \
+ || defined __sun || defined __ANDROID__ || defined __KLIBC__) \
&& ! defined __GLIBC__
# include <pthread.h>
#endif
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index 63fa1aa628f..6f2235a750a 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -579,11 +579,6 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
<wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter includes
<stdint.h> and assumes its types are already defined. */
# if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX)
- /* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
- included before <wchar.h>. */
-# include <stddef.h>
-# include <stdio.h>
-# include <time.h>
# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
# include <wchar.h>
# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 067b95ebd64..15066aa59f8 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -175,7 +175,7 @@
# define fp_ fp
# endif
-# if defined _SCO_DS /* OpenServer */
+# if defined _SCO_DS || (defined __SCO_VERSION__ || defined __sysv5__) /* OpenServer 5, OpenServer 6, UnixWare 7 */
# define _cnt __cnt
# define _ptr __ptr
# define _base __base
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 6d12cd826de..458036b3441 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -70,30 +70,44 @@
# endif
#endif
-/* _GL_ATTRIBUTE_FORMAT_PRINTF
- indicates to GCC that the function takes a format string and arguments,
- where the format string directives are the ones standardized by ISO C99
- and POSIX. */
+/* An __attribute__ __format__ specifier for a function that takes a format
+ string and arguments, where the format string directives are the ones
+ standardized by ISO C99 and POSIX.
+ _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD */
+/* __gnu_printf__ is supported in GCC >= 4.4. */
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
-# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT ((__gnu_printf__, formatstring_parameter, first_argument))
+# define _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD __gnu_printf__
#else
-# define _GL_ATTRIBUTE_FORMAT_PRINTF(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument))
+# define _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD __printf__
#endif
-/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF,
- except that it indicates to GCC that the supported format string directives
- are the ones of the system printf(), rather than the ones standardized by
- ISO C99 and POSIX. */
+/* An __attribute__ __format__ specifier for a function that takes a format
+ string and arguments, where the format string directives are the ones of the
+ system printf(), rather than the ones standardized by ISO C99 and POSIX.
+ _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM */
+/* On mingw, Gnulib sets __USE_MINGW_ANSI_STDIO in order to get closer to
+ the standards. The macro GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU indicates
+ whether this change is effective. On older mingw, it is not. */
#if GNULIB_PRINTF_ATTRIBUTE_FLAVOR_GNU
-# define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT_PRINTF (formatstring_parameter, first_argument)
+# define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD
#else
-# define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \
- _GL_ATTRIBUTE_FORMAT ((__printf__, formatstring_parameter, first_argument))
+# define _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM __printf__
#endif
+/* _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD
+ indicates to GCC that the function takes a format string and arguments,
+ where the format string directives are the ones standardized by ISO C99
+ and POSIX. */
+#define _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD(formatstring_parameter, first_argument) \
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, formatstring_parameter, first_argument))
+
+/* _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM is like _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD,
+ except that it indicates to GCC that the supported format string directives
+ are the ones of the system printf(), rather than the ones standardized by
+ ISO C99 and POSIX. */
+#define _GL_ATTRIBUTE_FORMAT_PRINTF_SYSTEM(formatstring_parameter, first_argument) \
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM, formatstring_parameter, first_argument))
+
/* _GL_ATTRIBUTE_FORMAT_SCANF
indicates to GCC that the function takes a format string and arguments,
where the format string directives are the ones standardized by ISO C99
@@ -174,13 +188,13 @@
# define dprintf rpl_dprintf
# endif
_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *restrict format, ...));
# else
# if !@HAVE_DPRINTF@
_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((2)));
# endif
_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *restrict format, ...));
@@ -215,9 +229,27 @@ _GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - "
"use gnulib module fclose for portable POSIX compliance");
#endif
+/* On native Windows, map 'fcloseall' to '_fcloseall', so that -loldnames is
+ not required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fcloseall on all platforms that have
+ it. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef fcloseall
-# define fcloseall _fcloseall
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fcloseall
+# define fcloseall _fcloseall
+# endif
+_GL_CXXALIAS_MDA (fcloseall, int, (void));
+#else
+# if @HAVE_DECL_FCLOSEALL@
+# if defined __FreeBSD__
+_GL_CXXALIAS_SYS (fcloseall, void, (void));
+# else
+_GL_CXXALIAS_SYS (fcloseall, int, (void));
+# endif
+# endif
+#endif
+#if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_FCLOSEALL@
+_GL_CXXALIASWARN (fcloseall);
#endif
#if @GNULIB_FDOPEN@
@@ -244,9 +276,20 @@ _GL_CXXALIASWARN (fdopen);
/* Assume fdopen is always declared. */
_GL_WARN_ON_USE (fdopen, "fdopen on native Windows platforms is not POSIX compliant - "
"use gnulib module fdopen for portability");
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef fdopen
-# define fdopen _fdopen
+#else
+/* On native Windows, map 'fdopen' to '_fdopen', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fdopen always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fdopen
+# define fdopen _fdopen
+# endif
+_GL_CXXALIAS_MDA (fdopen, FILE *, (int fd, const char *mode));
+# else
+_GL_CXXALIAS_SYS (fdopen, FILE *, (int fd, const char *mode));
+# endif
+_GL_CXXALIASWARN (fdopen);
#endif
#if @GNULIB_FFLUSH@
@@ -311,10 +354,19 @@ _GL_CXXALIASWARN (fgets);
# endif
#endif
+/* On native Windows, map 'fileno' to '_fileno', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fileno always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef fileno
-# define fileno _fileno
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fileno
+# define fileno _fileno
+# endif
+_GL_CXXALIAS_MDA (fileno, int, (FILE *restrict stream));
+#else
+_GL_CXXALIAS_SYS (fileno, int, (FILE *restrict stream));
#endif
+_GL_CXXALIASWARN (fileno);
#if @GNULIB_FOPEN@
# if @REPLACE_FOPEN@
@@ -351,7 +403,7 @@ _GL_WARN_ON_USE (fopen, "fopen on native Windows platforms is not POSIX complian
# if @GNULIB_FPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
_GL_FUNCDECL_RPL (fprintf, int,
(FILE *restrict fp, const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
# else
_GL_FUNCDECL_RPL (fprintf, int,
@@ -843,10 +895,19 @@ _GL_WARN_ON_USE (getline, "getline is unportable - "
_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
#endif
+/* On native Windows, map 'getw' to '_getw', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::getw always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef getw
-# define getw _getw
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getw
+# define getw _getw
+# endif
+_GL_CXXALIAS_MDA (getw, int, (FILE *restrict stream));
+#else
+_GL_CXXALIAS_SYS (getw, int, (FILE *restrict stream));
#endif
+_GL_CXXALIASWARN (getw);
#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@
struct obstack;
@@ -861,7 +922,7 @@ struct obstack;
# endif
_GL_FUNCDECL_RPL (obstack_printf, int,
(struct obstack *obs, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (obstack_printf, int,
(struct obstack *obs, const char *format, ...));
@@ -869,7 +930,7 @@ _GL_CXXALIAS_RPL (obstack_printf, int,
# if !@HAVE_DECL_OBSTACK_PRINTF@
_GL_FUNCDECL_SYS (obstack_printf, int,
(struct obstack *obs, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (obstack_printf, int,
@@ -882,7 +943,7 @@ _GL_CXXALIASWARN (obstack_printf);
# endif
_GL_FUNCDECL_RPL (obstack_vprintf, int,
(struct obstack *obs, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (obstack_vprintf, int,
(struct obstack *obs, const char *format, va_list args));
@@ -890,7 +951,7 @@ _GL_CXXALIAS_RPL (obstack_vprintf, int,
# if !@HAVE_DECL_OBSTACK_PRINTF@
_GL_FUNCDECL_SYS (obstack_vprintf, int,
(struct obstack *obs, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (obstack_vprintf, int,
@@ -974,7 +1035,7 @@ _GL_FUNCDECL_RPL_1 (__printf__, int,
(const char *restrict format, ...)
__asm__ (@ASM_SYMBOL_PREFIX@
_GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf))
- _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2)
_GL_ARG_NONNULL ((1)));
# else
_GL_FUNCDECL_RPL_1 (__printf__, int,
@@ -991,7 +1052,7 @@ _GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...));
# endif
_GL_FUNCDECL_RPL (printf, int,
(const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 2)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (printf, int, (const char *restrict format, ...));
# endif
@@ -1061,10 +1122,19 @@ _GL_CXXALIASWARN (puts);
# endif
#endif
+/* On native Windows, map 'putw' to '_putw', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::putw always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef putw
-# define putw _putw
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef putw
+# define putw _putw
+# endif
+_GL_CXXALIAS_MDA (putw, int, (int w, FILE *restrict stream));
+#else
+_GL_CXXALIAS_SYS (putw, int, (int w, FILE *restrict stream));
#endif
+_GL_CXXALIASWARN (putw);
#if @GNULIB_REMOVE@
# if @REPLACE_REMOVE@
@@ -1182,7 +1252,7 @@ _GL_CXXALIASWARN (scanf);
_GL_FUNCDECL_RPL (snprintf, int,
(char *restrict str, size_t size,
const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4)
_GL_ARG_NONNULL ((3)));
_GL_CXXALIAS_RPL (snprintf, int,
(char *restrict str, size_t size,
@@ -1192,7 +1262,7 @@ _GL_CXXALIAS_RPL (snprintf, int,
_GL_FUNCDECL_SYS (snprintf, int,
(char *restrict str, size_t size,
const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 4)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4)
_GL_ARG_NONNULL ((3)));
# endif
_GL_CXXALIAS_SYS (snprintf, int,
@@ -1226,7 +1296,7 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - "
# endif
_GL_FUNCDECL_RPL (sprintf, int,
(char *restrict str, const char *restrict format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (sprintf, int,
(char *restrict str, const char *restrict format, ...));
@@ -1245,10 +1315,19 @@ _GL_WARN_ON_USE (sprintf, "sprintf is not always POSIX compliant - "
"POSIX compliance");
#endif
+/* On native Windows, map 'tempnam' to '_tempnam', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::tempnam always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef tempnam
-# define tempnam _tempnam
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef tempnam
+# define tempnam _tempnam
+# endif
+_GL_CXXALIAS_MDA (tempnam, char *, (const char *dir, const char *prefix));
+#else
+_GL_CXXALIAS_SYS (tempnam, char *, (const char *dir, const char *prefix));
#endif
+_GL_CXXALIASWARN (tempnam);
#if @GNULIB_TMPFILE@
# if @REPLACE_TMPFILE@
@@ -1282,7 +1361,7 @@ _GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - "
# endif
_GL_FUNCDECL_RPL (asprintf, int,
(char **result, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (asprintf, int,
(char **result, const char *format, ...));
@@ -1290,7 +1369,7 @@ _GL_CXXALIAS_RPL (asprintf, int,
# if !@HAVE_VASPRINTF@
_GL_FUNCDECL_SYS (asprintf, int,
(char **result, const char *format, ...)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 3)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (asprintf, int,
@@ -1303,7 +1382,7 @@ _GL_CXXALIASWARN (asprintf);
# endif
_GL_FUNCDECL_RPL (vasprintf, int,
(char **result, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (vasprintf, int,
(char **result, const char *format, va_list args));
@@ -1311,7 +1390,7 @@ _GL_CXXALIAS_RPL (vasprintf, int,
# if !@HAVE_VASPRINTF@
_GL_FUNCDECL_SYS (vasprintf, int,
(char **result, const char *format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
# endif
_GL_CXXALIAS_SYS (vasprintf, int,
@@ -1327,7 +1406,7 @@ _GL_CXXALIASWARN (vasprintf);
# endif
_GL_FUNCDECL_RPL (vdprintf, int,
(int fd, const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_RPL (vdprintf, int,
(int fd, const char *restrict format, va_list args));
@@ -1335,7 +1414,7 @@ _GL_CXXALIAS_RPL (vdprintf, int,
# if !@HAVE_VDPRINTF@
_GL_FUNCDECL_SYS (vdprintf, int,
(int fd, const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((2)));
# endif
/* Need to cast, because on Solaris, the third parameter will likely be
@@ -1365,7 +1444,7 @@ _GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - "
_GL_FUNCDECL_RPL (vfprintf, int,
(FILE *restrict fp,
const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
# else
_GL_FUNCDECL_RPL (vfprintf, int,
@@ -1432,7 +1511,7 @@ _GL_CXXALIASWARN (vfscanf);
# define GNULIB_overrides_vprintf 1
# if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VFPRINTF_POSIX@
_GL_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (1, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (1, 0)
_GL_ARG_NONNULL ((1)));
# else
_GL_FUNCDECL_RPL (vprintf, int, (const char *restrict format, va_list args)
@@ -1487,7 +1566,7 @@ _GL_CXXALIASWARN (vscanf);
_GL_FUNCDECL_RPL (vsnprintf, int,
(char *restrict str, size_t size,
const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0)
_GL_ARG_NONNULL ((3)));
_GL_CXXALIAS_RPL (vsnprintf, int,
(char *restrict str, size_t size,
@@ -1497,7 +1576,7 @@ _GL_CXXALIAS_RPL (vsnprintf, int,
_GL_FUNCDECL_SYS (vsnprintf, int,
(char *restrict str, size_t size,
const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (3, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0)
_GL_ARG_NONNULL ((3)));
# endif
_GL_CXXALIAS_SYS (vsnprintf, int,
@@ -1523,7 +1602,7 @@ _GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - "
_GL_FUNCDECL_RPL (vsprintf, int,
(char *restrict str,
const char *restrict format, va_list args)
- _GL_ATTRIBUTE_FORMAT_PRINTF (2, 0)
+ _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0)
_GL_ARG_NONNULL ((1, 2)));
_GL_CXXALIAS_RPL (vsprintf, int,
(char *restrict str,
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 47a1309e633..1964443a22f 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -53,8 +53,8 @@
# include <sys/loadavg.h>
#endif
-/* Native Windows platforms declare mktemp() in <io.h>. */
-#if 0 && (defined _WIN32 && ! defined __CYGWIN__)
+/* Native Windows platforms declare _mktemp() in <io.h>. */
+#if defined _WIN32 && !defined __CYGWIN__
# include <io.h>
#endif
@@ -149,6 +149,31 @@ _GL_WARN_ON_USE (_Exit, "_Exit is unportable - "
#endif
+/* Allocate memory with indefinite extent and specified alignment. */
+#if @GNULIB_ALIGNED_ALLOC@
+# if @REPLACE_ALIGNED_ALLOC@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef aligned_alloc
+# define aligned_alloc rpl_aligned_alloc
+# endif
+_GL_FUNCDECL_RPL (aligned_alloc, void *, (size_t alignment, size_t size));
+_GL_CXXALIAS_RPL (aligned_alloc, void *, (size_t alignment, size_t size));
+# else
+# if @HAVE_ALIGNED_ALLOC@
+_GL_CXXALIAS_SYS (aligned_alloc, void *, (size_t alignment, size_t size));
+# endif
+# endif
+# if @HAVE_ALIGNED_ALLOC@
+_GL_CXXALIASWARN (aligned_alloc);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef aligned_alloc
+# if HAVE_RAW_DECL_ALIGNED_ALLOC
+_GL_WARN_ON_USE (aligned_alloc, "aligned_alloc is not portable - "
+ "use gnulib module aligned_alloc for portability");
+# endif
+#endif
+
#if @GNULIB_ATOLL@
/* Parse a signed decimal integer.
Returns the value of the integer. Errors are not detected. */
@@ -217,19 +242,86 @@ _GL_WARN_ON_USE (canonicalize_file_name,
# endif
#endif
+/* On native Windows, map 'ecvt' to '_ecvt', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::ecvt on all platforms that have
+ it. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef ecvt
-# define ecvt _ecvt
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef ecvt
+# define ecvt _ecvt
+# endif
+_GL_CXXALIAS_MDA (ecvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+#else
+# if @HAVE_DECL_ECVT@
+_GL_CXXALIAS_SYS (ecvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+# endif
+#endif
+#if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_ECVT@
+_GL_CXXALIASWARN (ecvt);
#endif
+/* On native Windows, map 'fcvt' to '_fcvt', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::fcvt on all platforms that have
+ it. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef fcvt
-# define fcvt _fcvt
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef fcvt
+# define fcvt _fcvt
+# endif
+_GL_CXXALIAS_MDA (fcvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+#else
+# if @HAVE_DECL_FCVT@
+_GL_CXXALIAS_SYS (fcvt, char *,
+ (double number, int ndigits, int *decptp, int *signp));
+# endif
+#endif
+#if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_FCVT@
+_GL_CXXALIASWARN (fcvt);
+#endif
+
+#if @GNULIB_FREE_POSIX@
+# if @REPLACE_FREE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef free
+# define free rpl_free
+# endif
+_GL_FUNCDECL_RPL (free, void, (void *ptr));
+_GL_CXXALIAS_RPL (free, void, (void *ptr));
+# else
+_GL_CXXALIAS_SYS (free, void, (void *ptr));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (free);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef free
+/* Assume free is always declared. */
+_GL_WARN_ON_USE (free, "free is not future POSIX compliant everywhere - "
+ "use gnulib module free for portability");
#endif
+/* On native Windows, map 'gcvt' to '_gcvt', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::gcvt on all platforms that have
+ it. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef gcvt
-# define gcvt _gcvt
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef gcvt
+# define gcvt _gcvt
+# endif
+_GL_CXXALIAS_MDA (gcvt, char *, (double number, int ndigits, char *buf));
+#else
+# if @HAVE_DECL_GCVT@
+_GL_CXXALIAS_SYS (gcvt, char *, (double number, int ndigits, char *buf));
+# endif
+#endif
+#if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_GCVT@
+_GL_CXXALIASWARN (gcvt);
#endif
#if @GNULIB_GETLOADAVG@
@@ -483,9 +575,47 @@ _GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - "
# endif
#endif
+/* On native Windows, map 'mktemp' to '_mktemp', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::mktemp always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef mktemp
-# define mktemp _mktemp
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef mktemp
+# define mktemp _mktemp
+# endif
+_GL_CXXALIAS_MDA (mktemp, char *, (char * /*template*/));
+#else
+_GL_CXXALIAS_SYS (mktemp, char *, (char * /*template*/));
+#endif
+_GL_CXXALIASWARN (mktemp);
+
+/* Allocate memory with indefinite extent and specified alignment. */
+#if @GNULIB_POSIX_MEMALIGN@
+# if @REPLACE_POSIX_MEMALIGN@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef posix_memalign
+# define posix_memalign rpl_posix_memalign
+# endif
+_GL_FUNCDECL_RPL (posix_memalign, int,
+ (void **memptr, size_t alignment, size_t size)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (posix_memalign, int,
+ (void **memptr, size_t alignment, size_t size));
+# else
+# if @HAVE_POSIX_MEMALIGN@
+_GL_CXXALIAS_SYS (posix_memalign, int,
+ (void **memptr, size_t alignment, size_t size));
+# endif
+# endif
+# if @HAVE_POSIX_MEMALIGN@
+_GL_CXXALIASWARN (posix_memalign);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef posix_memalign
+# if HAVE_RAW_DECL_POSIX_MEMALIGN
+_GL_WARN_ON_USE (posix_memalign, "posix_memalign is not portable - "
+ "use gnulib module posix_memalign for portability");
+# endif
#endif
#if @GNULIB_POSIX_OPENPT@
@@ -576,9 +706,22 @@ _GL_CXXALIAS_MDA (putenv, int, (char *string));
_GL_CXXALIAS_SYS (putenv, int, (char *string));
# endif
_GL_CXXALIASWARN (putenv);
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef putenv
-# define putenv _putenv
+#else
+/* On native Windows, map 'putenv' to '_putenv', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::putenv always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef putenv
+# define putenv _putenv
+# endif
+/* Need to cast, because on mingw, the parameter is either
+ 'const char *string' or 'char *string'. */
+_GL_CXXALIAS_MDA_CAST (putenv, int, (char *string));
+# else
+_GL_CXXALIAS_SYS (putenv, int, (char *string));
+# endif
+_GL_CXXALIASWARN (putenv);
#endif
#if @GNULIB_QSORT_R@
diff --git a/lib/string.in.h b/lib/string.in.h
index 9724addef43..f34bfabfb99 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -123,16 +123,28 @@ _GL_WARN_ON_USE (ffsll, "ffsll is not portable - use the ffsll module");
#endif
+/* On native Windows, map 'memccpy' to '_memccpy', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::memccpy always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef memccpy
-# define memccpy _memccpy
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef memccpy
+# define memccpy _memccpy
+# endif
+_GL_CXXALIAS_MDA (memccpy, void *,
+ (void *dest, const void *src, int c, size_t n));
+#else
+_GL_CXXALIAS_SYS (memccpy, void *,
+ (void *dest, const void *src, int c, size_t n));
#endif
+_GL_CXXALIASWARN (memccpy);
/* Return the first instance of C within N bytes of S, or NULL. */
#if @GNULIB_MEMCHR@
# if @REPLACE_MEMCHR@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef memchr
# define memchr rpl_memchr
# endif
_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n)
@@ -413,9 +425,23 @@ _GL_CXXALIASWARN (strdup);
_GL_WARN_ON_USE (strdup, "strdup is unportable - "
"use gnulib module strdup for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef strdup
-# define strdup _strdup
+#else
+/* On native Windows, map 'creat' to '_creat', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::creat always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef strdup
+# define strdup _strdup
+# endif
+_GL_CXXALIAS_MDA (strdup, char *, (char const *__s));
+# else
+# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup
+# undef strdup
+# endif
+_GL_CXXALIAS_SYS (strdup, char *, (char const *__s));
+# endif
+_GL_CXXALIASWARN (strdup);
#endif
/* Append no more than N characters from SRC onto DEST. */
diff --git a/lib/symlink.c b/lib/symlink.c
index e7dbd184a99..b1196b9ee85 100644
--- a/lib/symlink.c
+++ b/lib/symlink.c
@@ -36,7 +36,7 @@ rpl_symlink (char const *contents, char const *name)
if (len && name[len - 1] == '/')
{
struct stat st;
- if (lstat (name, &st) == 0)
+ if (lstat (name, &st) == 0 || errno == EOVERFLOW)
errno = EEXIST;
return -1;
}
diff --git a/lib/sys_select.in.h b/lib/sys_select.in.h
index 72cb9ba7b0f..ac1e93919b7 100644
--- a/lib/sys_select.in.h
+++ b/lib/sys_select.in.h
@@ -103,9 +103,16 @@
/* Get definition of 'sigset_t'.
But avoid namespace pollution on glibc systems and "unknown type
name" problems on Cygwin.
+ On OS/2 kLIBC, sigset_t is defined in <sys/select.h>, too. In addition,
+ if <sys/param.h> is included, <types.h> -> <sys/types.h> -> <sys/select.h>
+ are included. Then <signal.h> -> <pthread.h> are included by GNULIB. By the
+ way, <pthread.h> requires PAGE_SIZE defined in <sys/param.h>. However,
+ <sys/param.h> has not been processed, yet. As a result, 'PAGE_SIZE'
+ undeclared error occurs in <pthread.h>.
Do this after the include_next (for the sake of OpenBSD 5.0) but before
the split double-inclusion guard (for the sake of Solaris). */
-#if !((defined __GLIBC__ || defined __CYGWIN__) && !defined __UCLIBC__)
+#if !((defined __GLIBC__ || defined __CYGWIN__ || defined __KLIBC__) \
+ && !defined __UCLIBC__)
# include <signal.h>
#endif
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index 3e0e4b27b7e..3ce2a0dcf15 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -375,11 +375,11 @@ struct stat
# define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
#endif
-/* S_IXUGO is a common extension to POSIX. */
+/* Although S_IXUGO and S_IRWXUGO are not specified by POSIX and are
+ not implemented in GNU/Linux, some Gnulib-using apps use the macros. */
#if !S_IXUGO
# define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
#endif
-
#ifndef S_IRWXUGO
# define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
#endif
@@ -391,10 +391,20 @@ struct stat
#endif
+/* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::chmod always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef chmod
-# define chmod _chmod
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chmod
+# define chmod _chmod
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode));
+#else
+_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode));
#endif
+_GL_CXXALIASWARN (chmod);
#if @GNULIB_FCHMODAT@
@@ -808,10 +818,20 @@ _GL_WARN_ON_USE (stat, "stat is unportable - "
#endif
+/* On native Windows, map 'umask' to '_umask', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::umask always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef umask
-# define umask _umask
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef umask
+# define umask _umask
+# endif
+/* Need to cast, because in mingw the last argument is 'int mode'. */
+_GL_CXXALIAS_MDA_CAST (umask, mode_t, (mode_t mask));
+#else
+_GL_CXXALIAS_SYS (umask, mode_t, (mode_t mask));
#endif
+_GL_CXXALIASWARN (umask);
#if @GNULIB_UTIMENSAT@
diff --git a/lib/tempname.c b/lib/tempname.c
index cfb0fc42eca..b9f7cc8703d 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -47,9 +47,11 @@
#include <string.h>
#include <fcntl.h>
+#include <stdalign.h>
#include <stdint.h>
#include <sys/random.h>
#include <sys/stat.h>
+#include <time.h>
#if _LIBC
# define struct_stat64 struct stat64
@@ -60,27 +62,33 @@
# define __mkdir mkdir
# define __open open
# define __lxstat64(version, file, buf) lstat (file, buf)
+# define __getrandom getrandom
+# define __clock_gettime64 clock_gettime
+# define __timespec64 timespec
#endif
-#ifdef _LIBC
-# include <random-bits.h>
-# define RANDOM_BITS(Var) ((Var) = random_bits ())
-typedef uint32_t random_value;
-# define RANDOM_VALUE_MAX UINT32_MAX
-# define BASE_62_DIGITS 5 /* 62**5 < UINT32_MAX */
-# define BASE_62_POWER (62 * 62 * 62 * 62 * 62) /* 2**BASE_62_DIGITS */
-#else
/* Use getrandom if it works, falling back on a 64-bit linear
- congruential generator that starts with whatever Var's value
- happens to be. */
-# define RANDOM_BITS(Var) \
- ((void) (getrandom (&(Var), sizeof (Var), 0) == sizeof (Var) \
- || ((Var) = 2862933555777941757 * (Var) + 3037000493)))
+ congruential generator that starts with Var's value
+ mixed in with a clock's low-order bits if available. */
typedef uint_fast64_t random_value;
-# define RANDOM_VALUE_MAX UINT_FAST64_MAX
-# define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
-# define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
+#define RANDOM_VALUE_MAX UINT_FAST64_MAX
+#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
+#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
+
+static random_value
+random_bits (random_value var)
+{
+ random_value r;
+ if (__getrandom (&r, sizeof r, 0) == sizeof r)
+ return r;
+#if _LIBC || (defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME)
+ /* Add entropy if getrandom is not supported. */
+ struct __timespec64 tv;
+ __clock_gettime64 (CLOCK_MONOTONIC, &tv);
+ var ^= tv.tv_nsec;
#endif
+ return 2862933555777941757 * var + 3037000493;
+}
#if _LIBC
/* Return nonzero if DIR is an existent directory. */
@@ -250,8 +258,11 @@ try_tempname_len (char *tmpl, int suffixlen, void *args,
unsigned int attempts = ATTEMPTS_MIN;
#endif
- /* A random variable. */
- random_value v;
+ /* A random variable. The initial value is used only the for fallback path
+ on 'random_bits' on 'getrandom' failure. Its initial value tries to use
+ some entropy from the ASLR and ignore possible bits from the stack
+ alignment. */
+ random_value v = ((uintptr_t) &v) / alignof (max_align_t);
/* How many random base-62 digits can currently be extracted from V. */
int vdigits = 0;
@@ -279,7 +290,7 @@ try_tempname_len (char *tmpl, int suffixlen, void *args,
if (vdigits == 0)
{
do
- RANDOM_BITS (v);
+ v = random_bits (v);
while (unfair_min <= v);
vdigits = BASE_62_DIGITS;
diff --git a/lib/time.in.h b/lib/time.in.h
index 32e6ec03ef4..1b17c156eba 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -145,9 +145,20 @@ _GL_CXXALIAS_MDA (tzset, void, (void));
_GL_CXXALIAS_SYS (tzset, void, (void));
# endif
_GL_CXXALIASWARN (tzset);
-# elif defined _WIN32 && !defined __CYGWIN__
-# undef tzset
-# define tzset _tzset
+# else
+/* On native Windows, map 'tzset' to '_tzset', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::tzset always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef tzset
+# define tzset _tzset
+# endif
+_GL_CXXALIAS_MDA (tzset, void, (void));
+# else
+_GL_CXXALIAS_SYS (tzset, void, (void));
+# endif
+_GL_CXXALIASWARN (tzset);
# endif
/* Return the 'time_t' representation of TP and normalize TP. */
@@ -356,17 +367,17 @@ _GL_WARN_ON_USE (asctime, "asctime can overrun buffers in some cases - "
# endif
# if defined GNULIB_POSIXCHECK
# undef asctime_r
-_GL_WARN_ON_USE (asctime, "asctime_r can overrun buffers in some cases - "
+_GL_WARN_ON_USE (asctime_r, "asctime_r can overrun buffers in some cases - "
"better use strftime (or even sprintf) instead");
# endif
# if defined GNULIB_POSIXCHECK
# undef ctime
-_GL_WARN_ON_USE (asctime, "ctime can overrun buffers in some cases - "
+_GL_WARN_ON_USE (ctime, "ctime can overrun buffers in some cases - "
"better use strftime (or even sprintf) instead");
# endif
# if defined GNULIB_POSIXCHECK
# undef ctime_r
-_GL_WARN_ON_USE (asctime, "ctime_r can overrun buffers in some cases - "
+_GL_WARN_ON_USE (ctime_r, "ctime_r can overrun buffers in some cases - "
"better use strftime (or even sprintf) instead");
# endif
diff --git a/lib/time_rz.c b/lib/time_rz.c
index 95438cf876e..8992c2e37e0 100644
--- a/lib/time_rz.c
+++ b/lib/time_rz.c
@@ -27,19 +27,15 @@
#include <time.h>
#include <errno.h>
-#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "flexmember.h"
+#include "idx.h"
#include "time-internal.h"
-#ifndef SIZE_MAX
-# define SIZE_MAX ((size_t) -1)
-#endif
-
/* The approximate size to use for small allocation requests. This is
the largest "small" request for the GNU C library malloc. */
enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
@@ -125,14 +121,8 @@ save_abbr (timezone_t tz, struct tm *tm)
{
if (! (*zone_copy || (zone_copy == tz->abbrs && tz->tz_is_set)))
{
- size_t zone_size = strlen (zone) + 1;
- size_t zone_used = zone_copy - tz->abbrs;
- if (SIZE_MAX - zone_used < zone_size)
- {
- errno = ENOMEM;
- return false;
- }
- if (zone_used + zone_size < ABBR_SIZE_MIN)
+ idx_t zone_size = strlen (zone) + 1;
+ if (zone_size < tz->abbrs + ABBR_SIZE_MIN - zone_copy)
extend_abbrs (zone_copy, zone, zone_size);
else
{
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 357a35e3881..4033ffeef72 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -93,20 +93,18 @@
# undef __need_system_stdlib_h
#endif
-/* Native Windows platforms declare chdir, getcwd, rmdir in
+/* Native Windows platforms declare _chdir, _getcwd, _rmdir in
<io.h> and/or <direct.h>, not in <unistd.h>.
- They also declare access(), chmod(), close(), dup(), dup2(), isatty(),
- lseek(), read(), unlink(), write() in <io.h>. */
-#if ((@GNULIB_CHDIR@ || @GNULIB_GETCWD@ || @GNULIB_RMDIR@ \
- || defined GNULIB_POSIXCHECK) \
- && (defined _WIN32 && ! defined __CYGWIN__))
-# include <io.h> /* mingw32, mingw64 */
-# include <direct.h> /* mingw64, MSVC 9 */
-#elif (@GNULIB_CLOSE@ || @GNULIB_DUP@ || @GNULIB_DUP2@ || @GNULIB_ISATTY@ \
- || @GNULIB_LSEEK@ || @GNULIB_READ@ || @GNULIB_UNLINK@ || @GNULIB_WRITE@ \
- || defined GNULIB_POSIXCHECK) \
- && (defined _WIN32 && ! defined __CYGWIN__)
+ They also declare _access(), _chmod(), _close(), _dup(), _dup2(), _isatty(),
+ _lseek(), _read(), _unlink(), _write() in <io.h>. */
+#if defined _WIN32 && !defined __CYGWIN__
# include <io.h>
+# include <direct.h>
+#endif
+
+/* Native Windows platforms declare _execl*, _execv* in <process.h>. */
+#if defined _WIN32 && !defined __CYGWIN__
+# include <process.h>
#endif
/* AIX and OSF/1 5.1 declare getdomainname in <netdb.h>, not in <unistd.h>.
@@ -138,11 +136,8 @@
/* MSVC defines off_t in <sys/types.h>.
May also define off_t to a 64-bit type on native Windows. */
-/* But avoid namespace pollution on glibc systems. */
-#ifndef __GLIBC__
-/* Get off_t, ssize_t. */
-# include <sys/types.h>
-#endif
+/* Get off_t, ssize_t, mode_t. */
+#include <sys/types.h>
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
@@ -292,9 +287,20 @@ _GL_WARN_ON_USE (access, "access does not always support X_OK - "
"also, this function is a security risk - "
"use the gnulib module faccessat instead");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef access
-# define access _access
+#else
+/* On native Windows, map 'access' to '_access', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::access always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef access
+# define access _access
+# endif
+_GL_CXXALIAS_MDA (access, int, (const char *file, int mode));
+# else
+_GL_CXXALIAS_SYS (access, int, (const char *file, int mode));
+# endif
+_GL_CXXALIASWARN (access);
#endif
@@ -315,9 +321,20 @@ _GL_CXXALIASWARN (chdir);
_GL_WARN_ON_USE (chown, "chdir is not always in <unistd.h> - "
"use gnulib module chdir for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef chdir
-# define chdir _chdir
+#else
+/* On native Windows, map 'chdir' to '_chdir', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::chdir always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef chdir
+# define chdir _chdir
+# endif
+_GL_CXXALIAS_MDA (chdir, int, (const char *file));
+# else
+_GL_CXXALIAS_SYS (chdir, int, (const char *file) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIASWARN (chdir);
#endif
@@ -380,9 +397,20 @@ _GL_CXXALIASWARN (close);
/* Assume close is always declared. */
_GL_WARN_ON_USE (close, "close does not portably work on sockets - "
"use gnulib module close for portability");
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef close
-# define close _close
+#else
+/* On native Windows, map 'close' to '_close', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::close always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef close
+# define close _close
+# endif
+_GL_CXXALIAS_MDA (close, int, (int fd));
+# else
+_GL_CXXALIAS_SYS (close, int, (int fd));
+# endif
+_GL_CXXALIASWARN (close);
#endif
@@ -397,10 +425,11 @@ _GL_CXXALIAS_SYS (copy_file_range, ssize_t, (int ifd, off_t *ipos,
# endif
_GL_CXXALIASWARN (copy_file_range);
#elif defined GNULIB_POSIXCHECK
-/* Assume copy_file_range is always declared. */
+# if HAVE_RAW_DECL_COPY_FILE_RANGE
_GL_WARN_ON_USE (copy_file_range,
"copy_file_range is unportable - "
"use gnulib module copy_file_range for portability");
+# endif
#endif
@@ -427,9 +456,20 @@ _GL_CXXALIASWARN (dup);
_GL_WARN_ON_USE (dup, "dup is unportable - "
"use gnulib module dup for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef dup
-# define dup _dup
+#else
+/* On native Windows, map 'dup' to '_dup', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::dup always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef dup
+# define dup _dup
+# endif
+_GL_CXXALIAS_MDA (dup, int, (int oldfd));
+# else
+_GL_CXXALIAS_SYS (dup, int, (int oldfd));
+# endif
+_GL_CXXALIASWARN (dup);
#endif
@@ -461,9 +501,20 @@ _GL_CXXALIASWARN (dup2);
_GL_WARN_ON_USE (dup2, "dup2 is unportable - "
"use gnulib module dup2 for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef dup2
-# define dup2 _dup2
+#else
+/* On native Windows, map 'dup2' to '_dup2', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::dup2 always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef dup2
+# define dup2 _dup2
+# endif
+_GL_CXXALIAS_MDA (dup2, int, (int oldfd, int newfd));
+# else
+_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd));
+# endif
+_GL_CXXALIASWARN (dup2);
#endif
@@ -564,40 +615,116 @@ _GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - "
#endif
+/* On native Windows, map 'execl' to '_execl', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execl always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execl
-# define execl _execl
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execl
+# define execl _execl
+# endif
+_GL_CXXALIAS_MDA (execl, intptr_t, (const char *program, const char *arg, ...));
+#else
+_GL_CXXALIAS_SYS (execl, int, (const char *program, const char *arg, ...));
#endif
+_GL_CXXALIASWARN (execl);
+/* On native Windows, map 'execle' to '_execle', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execle always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execle
-# define execle _execle
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execle
+# define execle _execle
+# endif
+_GL_CXXALIAS_MDA (execle, intptr_t, (const char *program, const char *arg, ...));
+#else
+_GL_CXXALIAS_SYS (execle, int, (const char *program, const char *arg, ...));
#endif
+_GL_CXXALIASWARN (execle);
+/* On native Windows, map 'execlp' to '_execlp', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execlp always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execlp
-# define execlp _execlp
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execlp
+# define execlp _execlp
+# endif
+_GL_CXXALIAS_MDA (execlp, intptr_t, (const char *program, const char *arg, ...));
+#else
+_GL_CXXALIAS_SYS (execlp, int, (const char *program, const char *arg, ...));
#endif
+_GL_CXXALIASWARN (execlp);
+/* On native Windows, map 'execv' to '_execv', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execv always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execv
-# define execv _execv
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execv
+# define execv _execv
+# endif
+_GL_CXXALIAS_MDA (execv, intptr_t,
+ (const char *program, const char * const *argv));
+#else
+_GL_CXXALIAS_SYS (execv, int, (const char *program, char * const *argv));
#endif
+_GL_CXXALIASWARN (execv);
+/* On native Windows, map 'execve' to '_execve', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execve always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execve
-# define execve _execve
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execve
+# define execve _execve
+# endif
+_GL_CXXALIAS_MDA (execve, intptr_t,
+ (const char *program, const char * const *argv,
+ const char * const *env));
+#else
+_GL_CXXALIAS_SYS (execve, int,
+ (const char *program, char * const *argv, char * const *env));
#endif
+_GL_CXXALIASWARN (execve);
+/* On native Windows, map 'execvp' to '_execvp', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execvp always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execvp
-# define execvp _execvp
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execvp
+# define execvp _execvp
+# endif
+_GL_CXXALIAS_MDA (execvp, intptr_t,
+ (const char *program, const char * const *argv));
+#else
+_GL_CXXALIAS_SYS (execvp, int, (const char *program, char * const *argv));
#endif
+_GL_CXXALIASWARN (execvp);
+/* On native Windows, map 'execvpe' to '_execvpe', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::execvpe on all platforms that have
+ it. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef execvpe
-# define execvpe _execvpe
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef execvpe
+# define execvpe _execvpe
+# endif
+_GL_CXXALIAS_MDA (execvpe, intptr_t,
+ (const char *program, const char * const *argv,
+ const char * const *env));
+#else
+# if @HAVE_DECL_EXECVPE@
+_GL_CXXALIAS_SYS (execvpe, int,
+ (const char *program, char * const *argv, char * const *env));
+# endif
+#endif
+#if (defined _WIN32 && !defined __CYGWIN__) || @HAVE_DECL_EXECVPE@
+_GL_CXXALIASWARN (execvpe);
#endif
@@ -794,9 +921,22 @@ _GL_CXXALIASWARN (getcwd);
_GL_WARN_ON_USE (getcwd, "getcwd is unportable - "
"use gnulib module getcwd for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef getcwd
-# define getcwd _getcwd
+#else
+/* On native Windows, map 'getcwd' to '_getcwd', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::getcwd always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getcwd
+# define getcwd _getcwd
+# endif
+/* Need to cast, because on mingw, the second parameter is either
+ 'int size' or 'size_t size'. */
+_GL_CXXALIAS_MDA_CAST (getcwd, char *, (char *buf, size_t size));
+# else
+_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size));
+# endif
+_GL_CXXALIASWARN (getcwd);
#endif
@@ -1131,10 +1271,19 @@ _GL_WARN_ON_USE (getpass, "getpass is unportable - "
#endif
+/* On native Windows, map 'getpid' to '_getpid', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::getpid always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef getpid
-# define getpid _getpid
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef getpid
+# define getpid _getpid
+# endif
+_GL_CXXALIAS_MDA (getpid, int, (void));
+#else
+_GL_CXXALIAS_SYS (getpid, pid_t, (void));
#endif
+_GL_CXXALIASWARN (getpid);
#if @GNULIB_GETUSERSHELL@
@@ -1225,9 +1374,20 @@ _GL_CXXALIASWARN (isatty);
_GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - "
"use gnulib module isatty for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef isatty
-# define isatty _isatty
+#else
+/* On native Windows, map 'isatty' to '_isatty', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::isatty always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef isatty
+# define isatty _isatty
+# endif
+_GL_CXXALIAS_MDA (isatty, int, (int fd));
+# else
+_GL_CXXALIAS_SYS (isatty, int, (int fd));
+# endif
+_GL_CXXALIASWARN (isatty);
#endif
@@ -1355,9 +1515,20 @@ _GL_CXXALIASWARN (lseek);
_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some "
"systems - use gnulib module lseek for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef lseek
-# define lseek _lseek
+#else
+/* On native Windows, map 'lseek' to '_lseek', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::lseek always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef lseek
+# define lseek _lseek
+# endif
+_GL_CXXALIAS_MDA (lseek, long, (int fd, long offset, int whence));
+# else
+_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence));
+# endif
+_GL_CXXALIASWARN (lseek);
#endif
@@ -1497,15 +1668,27 @@ _GL_CXXALIAS_RPL (read, ssize_t, (int fd, void *buf, size_t count));
# endif
_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, size_t count));
# else
-/* Need to cast, because on mingw, the third parameter is
- unsigned int count
- and the return type is 'int'. */
-_GL_CXXALIAS_SYS_CAST (read, ssize_t, (int fd, void *buf, size_t count));
+_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count));
+# endif
+_GL_CXXALIASWARN (read);
+#else
+/* On native Windows, map 'read' to '_read', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::read always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef read
+# define read _read
+# endif
+# ifdef __MINGW32__
+_GL_CXXALIAS_MDA (read, int, (int fd, void *buf, unsigned int count));
+# else
+_GL_CXXALIAS_MDA (read, ssize_t, (int fd, void *buf, unsigned int count));
+# endif
+# else
+_GL_CXXALIAS_SYS (read, ssize_t, (int fd, void *buf, size_t count));
# endif
_GL_CXXALIASWARN (read);
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef read
-# define read _read
#endif
@@ -1604,9 +1787,20 @@ _GL_CXXALIASWARN (rmdir);
_GL_WARN_ON_USE (rmdir, "rmdir is unportable - "
"use gnulib module rmdir for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef rmdir
-# define rmdir _rmdir
+#else
+/* On native Windows, map 'rmdir' to '_rmdir', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::rmdir always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef rmdir
+# define rmdir _rmdir
+# endif
+_GL_CXXALIAS_MDA (rmdir, int, (char const *name));
+# else
+_GL_CXXALIAS_SYS (rmdir, int, (char const *name));
+# endif
+_GL_CXXALIASWARN (rmdir);
#endif
@@ -1665,10 +1859,19 @@ _GL_WARN_ON_USE (sleep, "sleep is unportable - "
#endif
+/* On native Windows, map 'swab' to '_swab', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::creat always. */
#if defined _WIN32 && !defined __CYGWIN__
-# undef swab
-# define swab _swab
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef swab
+# define swab _swab
+# endif
+_GL_CXXALIAS_MDA (swab, void, (char *from, char *to, int n));
+#else
+_GL_CXXALIAS_SYS (swab, void, (const void *from, void *to, ssize_t n));
#endif
+_GL_CXXALIASWARN (swab);
#if @GNULIB_SYMLINK@
@@ -1811,9 +2014,20 @@ _GL_CXXALIASWARN (unlink);
_GL_WARN_ON_USE (unlink, "unlink is not portable - "
"use gnulib module unlink for portability");
# endif
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef unlink
-# define unlink _unlink
+#else
+/* On native Windows, map 'unlink' to '_unlink', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::unlink always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef unlink
+# define unlink _unlink
+# endif
+_GL_CXXALIAS_MDA (unlink, int, (char const *file));
+# else
+_GL_CXXALIAS_SYS (unlink, int, (char const *file));
+# endif
+_GL_CXXALIASWARN (unlink);
#endif
@@ -1892,15 +2106,27 @@ _GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count));
# endif
_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, size_t count));
# else
-/* Need to cast, because on mingw, the third parameter is
- unsigned int count
- and the return type is 'int'. */
-_GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count));
+_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count));
+# endif
+_GL_CXXALIASWARN (write);
+#else
+/* On native Windows, map 'write' to '_write', so that -loldnames is not
+ required. In C++ with GNULIB_NAMESPACE, avoid differences between
+ platforms by defining GNULIB_NAMESPACE::write always. */
+# if defined _WIN32 && !defined __CYGWIN__
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef write
+# define write _write
+# endif
+# ifdef __MINGW32__
+_GL_CXXALIAS_MDA (write, int, (int fd, const void *buf, unsigned int count));
+# else
+_GL_CXXALIAS_MDA (write, ssize_t, (int fd, const void *buf, unsigned int count));
+# endif
+# else
+_GL_CXXALIAS_SYS (write, ssize_t, (int fd, const void *buf, size_t count));
# endif
_GL_CXXALIASWARN (write);
-#elif defined _WIN32 && !defined __CYGWIN__
-# undef write
-# define write _write
#endif
_GL_INLINE_HEADER_END
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 13ee23031a0..7cd4a74f04d 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -41,7 +41,7 @@ typedef size_t __xalloc_count_type;
positive and N must be nonnegative. This is a macro, not a
function, so that it works correctly even when SIZE_MAX < N. */
-#if 7 <= __GNUC__
+#if 7 <= __GNUC__ && !defined __clang__
# define xalloc_oversized(n, s) \
__builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1)
#elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__