summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorClint Adams <clint@debian.org>2021-08-31 08:53:27 -0400
committerClint Adams <clint@debian.org>2021-08-31 08:53:27 -0400
commitf24d9c72cbde1abddef18e427b818e5b6266a5e0 (patch)
treef10e939c9cb7b767cb51dce4a84ec9872f3c61b1 /lib
parentc7cd1604feb9bce8b62e9a5a306b8eeb30a11c97 (diff)
parentc50de48f2ed0b9476c3389fd07a85a5e8be798e2 (diff)
Update upstream source from tag 'upstream/v4.8'
Update to upstream version '4.8' with Debian dir 33bfe3afa4d1f33d660b71d89a5ac3eba646cc82
Diffstat (limited to 'lib')
-rw-r--r--lib/_Noreturn.h32
-rw-r--r--lib/acl-errno-valid.c2
-rw-r--r--lib/acl-internal.c2
-rw-r--r--lib/acl-internal.h2
-rw-r--r--lib/acl.h2
-rw-r--r--lib/acl_entries.c2
-rw-r--r--lib/alignof.h2
-rw-r--r--lib/alloca.c10
-rw-r--r--lib/alloca.in.h8
-rw-r--r--lib/arg-nonnull.h2
-rw-r--r--lib/basename-lgpl.c2
-rw-r--r--lib/binary-io.c18
-rw-r--r--lib/binary-io.h16
-rw-r--r--lib/btowc.c2
-rw-r--r--lib/c++defs.h2
-rw-r--r--lib/c-ctype.h2
-rw-r--r--lib/c-strcase.h2
-rw-r--r--lib/c-strcasecmp.c2
-rw-r--r--lib/c-strcaseeq.h2
-rw-r--r--lib/c-strncasecmp.c2
-rw-r--r--lib/canonicalize-lgpl.c2
-rw-r--r--lib/cdefs.h4
-rw-r--r--lib/close-stream.c2
-rw-r--r--lib/closeout.c2
-rw-r--r--lib/closeout.h2
-rw-r--r--lib/copy-acl.c2
-rw-r--r--lib/ctype.in.h4
-rw-r--r--lib/dfa.c621
-rw-r--r--lib/dfa.h31
-rw-r--r--lib/dirname-lgpl.c2
-rw-r--r--lib/dirname.h2
-rw-r--r--lib/dosname.h2
-rw-r--r--lib/errno.in.h2
-rw-r--r--lib/error.c4
-rw-r--r--lib/error.h2
-rw-r--r--lib/exitfail.c2
-rw-r--r--lib/exitfail.h2
-rw-r--r--lib/fcntl.in.h40
-rw-r--r--lib/filename.h2
-rw-r--r--lib/flexmember.h60
-rw-r--r--lib/fpending.c2
-rw-r--r--lib/fpending.h2
-rw-r--r--lib/fstat.c8
-rw-r--r--lib/fwriting.c2
-rw-r--r--lib/fwriting.h2
-rw-r--r--lib/get-permissions.c4
-rw-r--r--lib/getdelim.c2
-rw-r--r--lib/getfilecon.c2
-rw-r--r--lib/getopt-cdefs.in.h2
-rw-r--r--lib/getopt-core.h2
-rw-r--r--lib/getopt-ext.h2
-rw-r--r--lib/getopt-pfx-core.h2
-rw-r--r--lib/getopt-pfx-ext.h2
-rw-r--r--lib/getopt.c2
-rw-r--r--lib/getopt.in.h2
-rw-r--r--lib/getopt1.c2
-rw-r--r--lib/getopt_int.h2
-rw-r--r--lib/getprogname.c13
-rw-r--r--lib/getprogname.h2
-rw-r--r--lib/gettext.h15
-rw-r--r--lib/gettimeofday.c8
-rw-r--r--lib/glthread/lock.c944
-rw-r--r--lib/glthread/lock.h523
-rw-r--r--lib/glthread/threadlib.c4
-rw-r--r--lib/gnulib.mk140
-rw-r--r--lib/hard-locale.c47
-rw-r--r--lib/hard-locale.h7
-rw-r--r--lib/ignore-value.h2
-rw-r--r--lib/intprops.h221
-rw-r--r--lib/inttypes.in.h1148
-rw-r--r--lib/isblank.c2
-rw-r--r--lib/langinfo.in.h4
-rw-r--r--lib/lc-charset-dispatch.c82
-rw-r--r--lib/lc-charset-dispatch.h40
-rw-r--r--lib/libc-config.h2
-rw-r--r--lib/limits.in.h2
-rw-r--r--lib/local.mk2
-rw-r--r--lib/localcharset.c273
-rw-r--r--lib/localcharset.h31
-rw-r--r--lib/locale.in.h41
-rw-r--r--lib/localeconv.c2
-rw-r--r--lib/localeinfo.c46
-rw-r--r--lib/localeinfo.h8
-rw-r--r--lib/localtime-buffer.c2
-rw-r--r--lib/localtime-buffer.h2
-rw-r--r--lib/lstat.c8
-rw-r--r--lib/malloc.c2
-rw-r--r--lib/malloca.c2
-rw-r--r--lib/malloca.h6
-rw-r--r--lib/mbrlen.c2
-rw-r--r--lib/mbrtowc-impl-utf8.h138
-rw-r--r--lib/mbrtowc-impl.h262
-rw-r--r--lib/mbrtowc.c377
-rw-r--r--lib/mbsinit.c11
-rw-r--r--lib/mbtowc-impl.h2
-rw-r--r--lib/mbtowc-lock.c150
-rw-r--r--lib/mbtowc-lock.h115
-rw-r--r--lib/mbtowc.c2
-rw-r--r--lib/memchr.c2
-rw-r--r--lib/memchr.valgrind16
-rw-r--r--lib/memrchr.c2
-rw-r--r--lib/minmax.h2
-rw-r--r--lib/mkdir.c2
-rw-r--r--lib/mkostemp.c2
-rw-r--r--lib/msvc-inval.c2
-rw-r--r--lib/msvc-inval.h6
-rw-r--r--lib/msvc-nothrow.c2
-rw-r--r--lib/msvc-nothrow.h2
-rw-r--r--lib/nl_langinfo.c118
-rw-r--r--lib/obstack.c2
-rw-r--r--lib/obstack.h2
-rw-r--r--lib/pathmax.h6
-rw-r--r--lib/progname.c2
-rw-r--r--lib/progname.h2
-rw-r--r--lib/qcopy-acl.c2
-rw-r--r--lib/qset-acl.c2
-rw-r--r--lib/quote.h2
-rw-r--r--lib/quotearg.c2
-rw-r--r--lib/quotearg.h2
-rw-r--r--lib/readlink.c2
-rw-r--r--lib/regcomp.c73
-rw-r--r--lib/regex.c6
-rw-r--r--lib/regex.h2
-rw-r--r--lib/regex_internal.c26
-rw-r--r--lib/regex_internal.h54
-rw-r--r--lib/regexec.c120
-rw-r--r--lib/rename.c2
-rw-r--r--lib/rmdir.c2
-rw-r--r--lib/same-inode.h2
-rw-r--r--lib/se-selinux.in.h2
-rw-r--r--lib/set-acl.c2
-rw-r--r--lib/set-permissions.c2
-rw-r--r--lib/setlocale-lock.c150
-rw-r--r--lib/setlocale_null.c411
-rw-r--r--lib/setlocale_null.h82
-rw-r--r--lib/stat-time.h4
-rw-r--r--lib/stat-w32.c70
-rw-r--r--lib/stat-w32.h2
-rw-r--r--lib/stat.c30
-rw-r--r--lib/stdalign.in.h4
-rw-r--r--lib/stdarg.in.h2
-rw-r--r--lib/stdbool.in.h2
-rw-r--r--lib/stddef.in.h33
-rw-r--r--lib/stdint.in.h80
-rw-r--r--lib/stdio-impl.h24
-rw-r--r--lib/stdio.in.h69
-rw-r--r--lib/stdlib.in.h144
-rw-r--r--lib/streq.h2
-rw-r--r--lib/strerror-override.c2
-rw-r--r--lib/strerror-override.h2
-rw-r--r--lib/strerror.c2
-rw-r--r--lib/string.in.h14
-rw-r--r--lib/stripslash.c2
-rw-r--r--lib/strverscmp.c37
-rw-r--r--lib/sys_stat.in.h11
-rw-r--r--lib/sys_time.in.h8
-rw-r--r--lib/sys_types.in.h2
-rw-r--r--lib/tempname.c2
-rw-r--r--lib/tempname.h2
-rw-r--r--lib/time.in.h36
-rw-r--r--lib/unistd.in.h129
-rw-r--r--lib/unlocked-io.h2
-rw-r--r--lib/unused-parameter.h2
-rw-r--r--lib/verify.h124
-rw-r--r--lib/version-etc-fsf.c2
-rw-r--r--lib/version-etc.c28
-rw-r--r--lib/version-etc.h2
-rw-r--r--lib/warn-on-use.h2
-rw-r--r--lib/wchar.in.h107
-rw-r--r--lib/wcrtomb.c33
-rw-r--r--lib/wctob.c2
-rw-r--r--lib/wctomb-impl.h2
-rw-r--r--lib/wctomb.c2
-rw-r--r--lib/wctype.in.h294
-rw-r--r--lib/windows-initguard.h35
-rw-r--r--lib/windows-mutex.c95
-rw-r--r--lib/windows-mutex.h51
-rw-r--r--lib/windows-once.c62
-rw-r--r--lib/windows-once.h47
-rw-r--r--lib/windows-recmutex.c127
-rw-r--r--lib/windows-recmutex.h57
-rw-r--r--lib/windows-rwlock.c373
-rw-r--r--lib/windows-rwlock.h68
-rw-r--r--lib/xalloc-die.c2
-rw-r--r--lib/xalloc-oversized.h2
-rw-r--r--lib/xalloc.h2
-rw-r--r--lib/xmalloc.c8
187 files changed, 6315 insertions, 2685 deletions
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 94fdfaf..0d4b9c2 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,8 +1,34 @@
+/* A C macro for declaring that a function does not return.
+ Copyright (C) 2011-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/>. */
+
#ifndef _Noreturn
-# if 201103 <= (defined __cplusplus ? __cplusplus : 0)
+# if (defined __cplusplus \
+ && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
+ || (defined _MSC_VER && 1900 <= _MSC_VER)) \
+ && 0)
+ /* [[noreturn]] is not practically usable, because with it the syntax
+ extern _Noreturn void func (...);
+ would not be valid; such a declaration would only be valid with 'extern'
+ and '_Noreturn' swapped, or without the 'extern' keyword. However, some
+ AIX system header files and several gnulib header files use precisely
+ this syntax with 'extern'. */
# define _Noreturn [[noreturn]]
-# elif (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
- || 4 < __GNUC__ + (7 <= __GNUC_MINOR__))
+# elif ((!defined __cplusplus || defined __clang__) \
+ && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \
+ || 4 < __GNUC__ + (7 <= __GNUC_MINOR__)))
/* _Noreturn works as-is. */
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C
# define _Noreturn __attribute__ ((__noreturn__))
diff --git a/lib/acl-errno-valid.c b/lib/acl-errno-valid.c
index 96577eb..cafae0b 100644
--- a/lib/acl-errno-valid.c
+++ b/lib/acl-errno-valid.c
@@ -1,6 +1,6 @@
/* Test whether ACLs are well supported on this system.
- Copyright 2013-2018 Free Software Foundation, Inc.
+ Copyright 2013-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
diff --git a/lib/acl-internal.c b/lib/acl-internal.c
index 92e7b9b..1cb77a8 100644
--- a/lib/acl-internal.c
+++ b/lib/acl-internal.c
@@ -1,6 +1,6 @@
/* Test whether a file has a nontrivial ACL. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/acl-internal.h b/lib/acl-internal.h
index 2da7c5a..0e28e1a 100644
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -1,6 +1,6 @@
/* Internal implementation of access control lists. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/acl.h b/lib/acl.h
index d0c122c..374c147 100644
--- a/lib/acl.h
+++ b/lib/acl.h
@@ -1,6 +1,6 @@
/* acl.c - access control lists
- Copyright (C) 2002, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002, 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
diff --git a/lib/acl_entries.c b/lib/acl_entries.c
index ce730d4..14fca5f 100644
--- a/lib/acl_entries.c
+++ b/lib/acl_entries.c
@@ -1,6 +1,6 @@
/* Return the number of entries in an ACL.
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/alignof.h b/lib/alignof.h
index 26d71dd..17a80ff 100644
--- a/lib/alignof.h
+++ b/lib/alignof.h
@@ -1,5 +1,5 @@
/* Determine alignment of types.
- Copyright (C) 2003-2004, 2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2003-2004, 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
diff --git a/lib/alloca.c b/lib/alloca.c
index ee0f018..d0476d5 100644
--- a/lib/alloca.c
+++ b/lib/alloca.c
@@ -350,16 +350,16 @@ i00afunc (long *address)
/* There must be at least one stack segment. Therefore it is
a fatal error if "trailer" is null. */
- if (trailer == 0)
+ if (trailer == NULL)
abort ();
/* Discard segments that do not contain our argument address. */
- while (trailer != 0)
+ while (trailer != NULL)
{
block = (long *) trailer->this_address;
size = trailer->this_size;
- if (block == 0 || size == 0)
+ if (block == NULL || size == 0)
abort ();
trailer = (struct stk_trailer *) trailer->link;
if ((block <= address) && (address < (block + size)))
@@ -371,7 +371,7 @@ i00afunc (long *address)
result = address - block;
- if (trailer == 0)
+ if (trailer == NULL)
{
return result;
}
@@ -383,7 +383,7 @@ i00afunc (long *address)
result += trailer->this_size;
trailer = (struct stk_trailer *) trailer->link;
}
- while (trailer != 0);
+ while (trailer != NULL);
/* We are done. Note that if you present a bogus address (one
not in any segment), you will get a different number back, formed
diff --git a/lib/alloca.in.h b/lib/alloca.in.h
index 5ad8af8..c7187e6 100644
--- a/lib/alloca.in.h
+++ b/lib/alloca.in.h
@@ -1,6 +1,6 @@
/* Memory allocation on the stack.
- Copyright (C) 1995, 1999, 2001-2004, 2006-2018 Free Software Foundation,
+ Copyright (C) 1995, 1999, 2001-2004, 2006-2020 Free Software Foundation,
Inc.
This program is free software; you can redistribute it and/or modify it
@@ -36,6 +36,12 @@
#ifndef alloca
# ifdef __GNUC__
+ /* Some version of mingw have an <alloca.h> that causes trouble when
+ included after 'alloca' gets defined as a macro. As a workaround, include
+ this <alloca.h> first and define 'alloca' as a macro afterwards. */
+# if (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@
+# include_next <alloca.h>
+# endif
# define alloca __builtin_alloca
# elif defined _AIX
# define alloca __alloca
diff --git a/lib/arg-nonnull.h b/lib/arg-nonnull.h
index 5f03408..ac26ca8 100644
--- a/lib/arg-nonnull.h
+++ b/lib/arg-nonnull.h
@@ -1,5 +1,5 @@
/* A C macro for declaring that specific arguments must not be NULL.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
diff --git a/lib/basename-lgpl.c b/lib/basename-lgpl.c
index 33f9994..565469e 100644
--- a/lib/basename-lgpl.c
+++ b/lib/basename-lgpl.c
@@ -1,6 +1,6 @@
/* basename.c -- return the last element in a file name
- Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2018 Free Software
+ Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2020 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/binary-io.c b/lib/binary-io.c
index f9cc4dd..e84e223 100644
--- a/lib/binary-io.c
+++ b/lib/binary-io.c
@@ -1,5 +1,5 @@
/* Binary mode I/O.
- Copyright 2017-2018 Free Software Foundation, Inc.
+ Copyright 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
@@ -20,18 +20,20 @@
#include "binary-io.h"
#if defined __DJGPP__ || defined __EMX__
-# include <errno.h>
# include <unistd.h>
int
-__gl_setmode_check (int fd)
+set_binary_mode (int fd, int mode)
{
if (isatty (fd))
- {
- errno = EINVAL;
- return -1;
- }
+ /* If FD refers to a console (not a pipe, not a regular file),
+ O_TEXT is the only reasonable mode, both on input and on output.
+ Silently ignore the request. If we were to return -1 here,
+ all programs that use xset_binary_mode would fail when run
+ with console input or console output. */
+ return O_TEXT;
else
- return 0;
+ return __gl_setmode (fd, mode);
}
+
#endif
diff --git a/lib/binary-io.h b/lib/binary-io.h
index 1f21fc0..477b4bf 100644
--- a/lib/binary-io.h
+++ b/lib/binary-io.h
@@ -1,5 +1,5 @@
/* Binary mode I/O.
- Copyright (C) 2001, 2003, 2005, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2005, 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
@@ -53,25 +53,21 @@ __gl_setmode (int fd _GL_UNUSED, int mode _GL_UNUSED)
}
#endif
-#if defined __DJGPP__ || defined __EMX__
-extern int __gl_setmode_check (int);
-#else
-BINARY_IO_INLINE int
-__gl_setmode_check (int fd _GL_UNUSED) { return 0; }
-#endif
-
/* Set FD's mode to MODE, which should be either O_TEXT or O_BINARY.
Return the old mode if successful, -1 (setting errno) on failure.
Ordinarily this function would be called 'setmode', since that is
its name on MS-Windows, but it is called 'set_binary_mode' here
to avoid colliding with a BSD function of another name. */
+#if defined __DJGPP__ || defined __EMX__
+extern int set_binary_mode (int fd, int mode);
+#else
BINARY_IO_INLINE int
set_binary_mode (int fd, int mode)
{
- int r = __gl_setmode_check (fd);
- return r != 0 ? r : __gl_setmode (fd, mode);
+ return __gl_setmode (fd, mode);
}
+#endif
/* This macro is obsolescent. */
#define SET_BINARY(fd) ((void) set_binary_mode (fd, O_BINARY))
diff --git a/lib/btowc.c b/lib/btowc.c
index 54124b2..6828b70 100644
--- a/lib/btowc.c
+++ b/lib/btowc.c
@@ -1,5 +1,5 @@
/* Convert unibyte character to wide character.
- Copyright (C) 2008, 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2010-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/c++defs.h b/lib/c++defs.h
index 72ff1ff..7a05763 100644
--- a/lib/c++defs.h
+++ b/lib/c++defs.h
@@ -1,5 +1,5 @@
/* C++ compatible function declaration macros.
- Copyright (C) 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2010-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
diff --git a/lib/c-ctype.h b/lib/c-ctype.h
index d55d4f6..fbd11b3 100644
--- a/lib/c-ctype.h
+++ b/lib/c-ctype.h
@@ -5,7 +5,7 @@
<ctype.h> functions' behaviour depends on the current locale set via
setlocale.
- Copyright (C) 2000-2003, 2006, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2000-2003, 2006, 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
diff --git a/lib/c-strcase.h b/lib/c-strcase.h
index 41f439e..3b711f5 100644
--- a/lib/c-strcase.h
+++ b/lib/c-strcase.h
@@ -1,5 +1,5 @@
/* Case-insensitive string comparison functions in C locale.
- Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2018 Free Software
+ Copyright (C) 1995-1996, 2001, 2003, 2005, 2009-2020 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/lib/c-strcasecmp.c b/lib/c-strcasecmp.c
index 2b1ac99..951220f 100644
--- a/lib/c-strcasecmp.c
+++ b/lib/c-strcasecmp.c
@@ -1,5 +1,5 @@
/* c-strcasecmp.c -- case insensitive string comparator in C locale
- Copyright (C) 1998-1999, 2005-2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-1999, 2005-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
diff --git a/lib/c-strcaseeq.h b/lib/c-strcaseeq.h
index 9bde9de..304c72e 100644
--- a/lib/c-strcaseeq.h
+++ b/lib/c-strcaseeq.h
@@ -1,5 +1,5 @@
/* Optimized case-insensitive string comparison in C locale.
- Copyright (C) 2001-2002, 2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002, 2007, 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
diff --git a/lib/c-strncasecmp.c b/lib/c-strncasecmp.c
index 8151c1a..9ad4919 100644
--- a/lib/c-strncasecmp.c
+++ b/lib/c-strncasecmp.c
@@ -1,5 +1,5 @@
/* c-strncasecmp.c -- case insensitive string comparator in C locale
- Copyright (C) 1998-1999, 2005-2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-1999, 2005-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
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index 7831b3f..7d3c710 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -1,5 +1,5 @@
/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/cdefs.h b/lib/cdefs.h
index 70fb638..d8e4a00 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
+/* Copyright (C) 1992-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
@@ -340,7 +340,7 @@
semantics.
clang++ identifies itself as gcc-4.2, but has support for GNU inlining
- semantics, that can be checked fot by using the __GNUC_STDC_INLINE_ and
+ semantics, that can be checked for by using the __GNUC_STDC_INLINE_ and
__GNUC_GNU_INLINE__ macro definitions. */
#if (!defined __cplusplus || __GNUC_PREREQ (4,3) \
|| (defined __clang__ && (defined __GNUC_STDC_INLINE__ \
diff --git a/lib/close-stream.c b/lib/close-stream.c
index 3d5a52e..04bc800 100644
--- a/lib/close-stream.c
+++ b/lib/close-stream.c
@@ -1,6 +1,6 @@
/* Close a stream, with nicer error checking than fclose's.
- Copyright (C) 1998-2002, 2004, 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-2002, 2004, 2006-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
diff --git a/lib/closeout.c b/lib/closeout.c
index 0672732..8b92ce9 100644
--- a/lib/closeout.c
+++ b/lib/closeout.c
@@ -1,6 +1,6 @@
/* Close standard output and standard error, exiting with a diagnostic on error.
- Copyright (C) 1998-2002, 2004, 2006, 2008-2018 Free Software Foundation,
+ Copyright (C) 1998-2002, 2004, 2006, 2008-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/closeout.h b/lib/closeout.h
index 6629d49..8294c62 100644
--- a/lib/closeout.h
+++ b/lib/closeout.h
@@ -1,6 +1,6 @@
/* Close standard output and standard error.
- Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2018 Free Software
+ Copyright (C) 1998, 2000, 2003-2004, 2006, 2008-2020 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/copy-acl.c b/lib/copy-acl.c
index f5699ef..0eb4caf 100644
--- a/lib/copy-acl.c
+++ b/lib/copy-acl.c
@@ -1,6 +1,6 @@
/* Copy access control list from one file to file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/ctype.in.h b/lib/ctype.in.h
index cfcb118..555677a 100644
--- a/lib/ctype.in.h
+++ b/lib/ctype.in.h
@@ -1,6 +1,6 @@
/* A substitute for ISO C99 <ctype.h>, for platforms on which it is incomplete.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
@@ -19,7 +19,7 @@
/*
* ISO C 99 <ctype.h> for platforms on which it is incomplete.
- * <http://www.opengroup.org/onlinepubs/9699919799/basedefs/ctype.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ctype.h.html>
*/
#ifndef _@GUARD_PREFIX@_CTYPE_H
diff --git a/lib/dfa.c b/lib/dfa.c
index c9be5e8..96ae560 100644
--- a/lib/dfa.c
+++ b/lib/dfa.c
@@ -1,5 +1,5 @@
/* dfa.c - deterministic extended regexp routines for GNU
- Copyright (C) 1988, 1998, 2000, 2002, 2004-2005, 2007-2018 Free Software
+ Copyright (C) 1988, 1998, 2000, 2002, 2004-2005, 2007-2020 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,8 @@
#include "dfa.h"
+#include "flexmember.h"
+
#include <assert.h>
#include <ctype.h>
#include <stdint.h>
@@ -31,7 +33,12 @@
#include <stdlib.h>
#include <limits.h>
#include <string.h>
-#include <locale.h>
+
+/* Another name for ptrdiff_t, for sizes of objects and nonnegative
+ indexes into objects. It is signed to help catch integer overflow.
+ It has its own name because it is for nonnegative values only. */
+typedef ptrdiff_t idx_t;
+static idx_t const IDX_MAX = PTRDIFF_MAX;
static bool
streq (char const *a, char const *b)
@@ -77,28 +84,15 @@ isasciidigit (char c)
/* First integer value that is greater than any character code. */
enum { NOTCHAR = 1 << CHAR_BIT };
+/* Number of bits used in a charclass word. */
+enum { CHARCLASS_WORD_BITS = 64 };
+
/* This represents part of a character class. It must be unsigned and
at least CHARCLASS_WORD_BITS wide. Any excess bits are zero. */
-typedef unsigned long int charclass_word;
-
-/* CHARCLASS_WORD_BITS is the number of bits used in a charclass word.
- CHARCLASS_PAIR (LO, HI) is part of a charclass initializer, and
- represents 64 bits' worth of a charclass, where LO and HI are the
- low and high-order 32 bits of the 64-bit quantity. */
-#if ULONG_MAX >> 31 >> 31 < 3
-enum { CHARCLASS_WORD_BITS = 32 };
-# define CHARCLASS_PAIR(lo, hi) lo, hi
-#else
-enum { CHARCLASS_WORD_BITS = 64 };
-# define CHARCLASS_PAIR(lo, hi) (((charclass_word) (hi) << 32) + (lo))
-#endif
+typedef uint_least64_t charclass_word;
-/* An initializer for a charclass whose 32-bit words are A through H. */
-#define CHARCLASS_INIT(a, b, c, d, e, f, g, h) \
- {{ \
- CHARCLASS_PAIR (a, b), CHARCLASS_PAIR (c, d), \
- CHARCLASS_PAIR (e, f), CHARCLASS_PAIR (g, h) \
- }}
+/* An initializer for a charclass whose 64-bit words are A through D. */
+#define CHARCLASS_INIT(a, b, c, d) {{a, b, c, d}}
/* The maximum useful value of a charclass_word; all used bits are 1. */
static charclass_word const CHARCLASS_WORD_MASK
@@ -214,7 +208,7 @@ enum
codes are returned by the lexical analyzer. */
typedef ptrdiff_t token;
-static ptrdiff_t const TOKEN_MAX = PTRDIFF_MAX;
+static token const TOKEN_MAX = PTRDIFF_MAX;
/* States are indexed by state_num values. These are normally
nonnegative but -1 is used as a special value. */
@@ -325,7 +319,7 @@ enum
a constraint. */
typedef struct
{
- size_t index; /* Index into the parse array. */
+ idx_t index; /* Index into the parse array. */
unsigned int constraint; /* Constraint for matching this position. */
} position;
@@ -333,8 +327,8 @@ typedef struct
typedef struct
{
position *elems; /* Elements of this position set. */
- ptrdiff_t nelem; /* Number of elements in this set. */
- ptrdiff_t alloc; /* Number of elements allocated in ELEMS. */
+ idx_t nelem; /* Number of elements in this set. */
+ idx_t alloc; /* Number of elements allocated in ELEMS. */
} position_set;
/* A state of the dfa consists of a set of positions, some flags,
@@ -366,8 +360,8 @@ struct mb_char_classes
ptrdiff_t cset;
bool invert;
wchar_t *chars; /* Normal characters. */
- ptrdiff_t nchars;
- ptrdiff_t nchars_alloc;
+ idx_t nchars;
+ idx_t nchars_alloc;
};
struct regex_syntax
@@ -407,9 +401,9 @@ struct regex_syntax
struct lexer_state
{
char const *ptr; /* Pointer to next input character. */
- size_t left; /* Number of characters remaining. */
+ idx_t left; /* Number of characters remaining. */
token lasttok; /* Previous token returned; initially END. */
- size_t parens; /* Count of outstanding left parens. */
+ idx_t parens; /* Count of outstanding left parens. */
int minrep, maxrep; /* Repeat counts for {m,n}. */
/* Wide character representation of the current multibyte character,
@@ -417,9 +411,6 @@ struct lexer_state
MB_CUR_MAX > 1. */
wint_t wctok;
- /* Length of the multibyte representation of wctok. */
- int cur_mb_len;
-
/* The most recently analyzed multibyte bracket expression. */
struct mb_char_classes brack;
@@ -432,7 +423,7 @@ struct lexer_state
struct parser_state
{
token tok; /* Lookahead token. */
- size_t depth; /* Current depth of a hypothetical stack
+ idx_t depth; /* Current depth of a hypothetical stack
holding deferred productions. This is
used to determine the depth that will be
required of the real stack later on in
@@ -442,14 +433,11 @@ struct parser_state
/* A compiled regular expression. */
struct dfa
{
- /* Syntax configuration */
- struct regex_syntax syntax;
-
/* Fields filled by the scanner. */
charclass *charclasses; /* Array of character sets for CSET tokens. */
- ptrdiff_t cindex; /* Index for adding new charclasses. */
- ptrdiff_t calloc; /* Number of charclasses allocated. */
- size_t canychar; /* Index of anychar class, or (size_t) -1. */
+ idx_t cindex; /* Index for adding new charclasses. */
+ idx_t calloc; /* Number of charclasses allocated. */
+ ptrdiff_t canychar; /* Index of anychar class, or -1. */
/* Scanner state */
struct lexer_state lex;
@@ -459,16 +447,16 @@ struct dfa
/* Fields filled by the parser. */
token *tokens; /* Postfix parse array. */
- size_t tindex; /* Index for adding new tokens. */
- size_t talloc; /* Number of tokens currently allocated. */
- size_t depth; /* Depth required of an evaluation stack
+ idx_t tindex; /* Index for adding new tokens. */
+ idx_t talloc; /* Number of tokens currently allocated. */
+ idx_t depth; /* Depth required of an evaluation stack
used for depth-first traversal of the
parse tree. */
- size_t nleaves; /* Number of leaves on the parse tree. */
- size_t nregexps; /* Count of parallel regexps being built
+ idx_t nleaves; /* Number of leaves on the parse tree. */
+ idx_t nregexps; /* Count of parallel regexps being built
with dfaparse. */
bool fast; /* The DFA is fast. */
- token utf8_anychar_classes[5]; /* To lower ANYCHAR in UTF-8 locales. */
+ token utf8_anychar_classes[9]; /* To lower ANYCHAR in UTF-8 locales. */
mbstate_t mbs; /* Multibyte conversion state. */
/* The following are valid only if MB_CUR_MAX > 1. */
@@ -495,7 +483,7 @@ struct dfa
/* Fields filled by the state builder. */
dfa_state *states; /* States of the dfa. */
state_num sindex; /* Index for adding new states. */
- ptrdiff_t salloc; /* Number of states currently allocated. */
+ idx_t salloc; /* Number of states currently allocated. */
/* Fields filled by the parse tree->NFA conversion. */
position_set *follows; /* Array of follow sets, indexed by position
@@ -560,18 +548,16 @@ struct dfa
state_num mb_trcount; /* Number of transition tables for states with
ANYCHAR that have actually been built. */
+ /* Syntax configuration. This is near the end so that dfacopysyntax
+ can memset up to here. */
+ struct regex_syntax syntax;
+
/* Information derived from the locale. This is at the end so that
a quick memset need not clear it specially. */
/* dfaexec implementation. */
char *(*dfaexec) (struct dfa *, char const *, char *,
- bool, size_t *, bool *);
-
- /* The locale is simple, like the C locale. These locales can be
- processed more efficiently, as they are single-byte, their native
- character set is in collating-sequence order, and they do not
- have multi-character collating elements. */
- bool simple_locale;
+ bool, ptrdiff_t *, bool *);
/* Other cached information derived from the locale. */
struct localeinfo localeinfo;
@@ -612,7 +598,7 @@ static void regexp (struct dfa *dfa);
* The return value is always in the range 1..N.
* D->mbs is always valid afterwards.
* *PWC is always set to something. */
-static size_t
+static int
mbs_to_wchar (wint_t *pwc, char const *s, size_t n, struct dfa *d)
{
unsigned char uc = s[0];
@@ -791,10 +777,10 @@ emptyset (charclass const *s)
{ free (A); A = xpalloc (NULL, &AITEMS, ...); }. */
static void *
-xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
- ptrdiff_t nitems_max, ptrdiff_t item_size)
+xpalloc (void *pa, idx_t *nitems, idx_t nitems_incr_min,
+ ptrdiff_t nitems_max, idx_t item_size)
{
- ptrdiff_t n0 = *nitems;
+ idx_t n0 = *nitems;
/* The approximate size to use for initial small allocation
requests. This is the largest "small" request for the GNU C
@@ -806,15 +792,15 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
Adjust the growth according to three constraints: NITEMS_INCR_MIN,
NITEMS_MAX, and what the C language can represent safely. */
- ptrdiff_t n, nbytes;
+ idx_t n, nbytes;
if (INT_ADD_WRAPV (n0, n0 >> 1, &n))
- n = PTRDIFF_MAX;
+ n = IDX_MAX;
if (0 <= nitems_max && nitems_max < n)
n = nitems_max;
- ptrdiff_t adjusted_nbytes
+ idx_t adjusted_nbytes
= ((INT_MULTIPLY_WRAPV (n, item_size, &nbytes) || SIZE_MAX < nbytes)
- ? MIN (PTRDIFF_MAX, SIZE_MAX)
+ ? MIN (IDX_MAX, SIZE_MAX)
: nbytes < DEFAULT_MXFAST ? DEFAULT_MXFAST : 0);
if (adjusted_nbytes)
{
@@ -844,8 +830,8 @@ xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min,
ITEM_SIZE is the size of one item; it must be positive.
Avoid O(N**2) behavior on arrays growing linearly. */
static void *
-maybe_realloc (void *pa, ptrdiff_t i, ptrdiff_t *nitems,
- ptrdiff_t nitems_max, ptrdiff_t item_size)
+maybe_realloc (void *pa, idx_t i, idx_t *nitems,
+ ptrdiff_t nitems_max, idx_t item_size)
{
if (i < *nitems)
return pa;
@@ -853,10 +839,10 @@ maybe_realloc (void *pa, ptrdiff_t i, ptrdiff_t *nitems,
}
/* In DFA D, find the index of charclass S, or allocate a new one. */
-static ptrdiff_t
-charclass_index (struct dfa *d, charclass *s)
+static idx_t
+charclass_index (struct dfa *d, charclass const *s)
{
- ptrdiff_t i;
+ idx_t i;
for (i = 0; i < d->cindex; ++i)
if (equal (s, &d->charclasses[i]))
@@ -911,38 +897,6 @@ setbit_case_fold_c (int b, charclass *c)
setbit (i, c);
}
-/* Return true if the locale compatible with the C locale. */
-
-static bool
-using_simple_locale (bool multibyte)
-{
- /* The native character set is known to be compatible with
- the C locale. The following test isn't perfect, but it's good
- enough in practice, as only ASCII and EBCDIC are in common use
- and this test correctly accepts ASCII and rejects EBCDIC. */
- enum { native_c_charset =
- ('\b' == 8 && '\t' == 9 && '\n' == 10 && '\v' == 11 && '\f' == 12
- && '\r' == 13 && ' ' == 32 && '!' == 33 && '"' == 34 && '#' == 35
- && '%' == 37 && '&' == 38 && '\'' == 39 && '(' == 40 && ')' == 41
- && '*' == 42 && '+' == 43 && ',' == 44 && '-' == 45 && '.' == 46
- && '/' == 47 && '0' == 48 && '9' == 57 && ':' == 58 && ';' == 59
- && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63 && 'A' == 65
- && 'Z' == 90 && '[' == 91 && '\\' == 92 && ']' == 93 && '^' == 94
- && '_' == 95 && 'a' == 97 && 'z' == 122 && '{' == 123 && '|' == 124
- && '}' == 125 && '~' == 126)
- };
-
- if (!native_c_charset || multibyte)
- return false;
- else
- {
- /* Treat C and POSIX locales as being compatible. Also, treat
- errors as compatible, as these are invariably from stubs. */
- char const *loc = setlocale (LC_ALL, NULL);
- return !loc || streq (loc, "C") || streq (loc, "POSIX");
- }
-}
-
/* Fetch the next lexical input character from the pattern. There
must at least one byte of pattern input. Set DFA->lex.wctok to the
value of the character or to WEOF depending on whether the input is
@@ -952,9 +906,8 @@ using_simple_locale (bool multibyte)
static int
fetch_wc (struct dfa *dfa)
{
- size_t nbytes = mbs_to_wchar (&dfa->lex.wctok, dfa->lex.ptr, dfa->lex.left,
- dfa);
- dfa->lex.cur_mb_len = nbytes;
+ int nbytes = mbs_to_wchar (&dfa->lex.wctok, dfa->lex.ptr, dfa->lex.left,
+ dfa);
int c = nbytes == 1 ? to_uchar (dfa->lex.ptr[0]) : EOF;
dfa->lex.ptr += nbytes;
dfa->lex.left -= nbytes;
@@ -1003,7 +956,7 @@ static const struct dfa_ctype prednames[] = {
static const struct dfa_ctype *_GL_ATTRIBUTE_PURE
find_pred (const char *str)
{
- for (unsigned int i = 0; prednames[i].name; ++i)
+ for (int i = 0; prednames[i].name; i++)
if (streq (str, prednames[i].name))
return &prednames[i];
return NULL;
@@ -1033,7 +986,7 @@ parse_bracket_exp (struct dfa *dfa)
if (invert)
{
c = bracket_fetch_wc (dfa);
- known_bracket_exp = dfa->simple_locale;
+ known_bracket_exp = dfa->localeinfo.simple;
}
wint_t wc = dfa->lex.wctok;
int c1;
@@ -1058,7 +1011,7 @@ parse_bracket_exp (struct dfa *dfa)
{
enum { MAX_BRACKET_STRING_LEN = 32 };
char str[MAX_BRACKET_STRING_LEN + 1];
- size_t len = 0;
+ int len = 0;
for (;;)
{
c = bracket_fetch_wc (dfa);
@@ -1144,8 +1097,8 @@ parse_bracket_exp (struct dfa *dfa)
{
/* In the case [x-], the - is an ordinary hyphen,
which is left in c1, the lookahead character. */
- dfa->lex.ptr -= dfa->lex.cur_mb_len;
- dfa->lex.left += dfa->lex.cur_mb_len;
+ dfa->lex.ptr--;
+ dfa->lex.left++;
}
else
{
@@ -1163,7 +1116,7 @@ parse_bracket_exp (struct dfa *dfa)
/* Treat [x-y] as a range if x != y. */
if (wc != wc2 || wc == WEOF)
{
- if (dfa->simple_locale
+ if (dfa->localeinfo.simple
|| (isasciidigit (c) & isasciidigit (c2)))
{
for (int ci = c; ci <= c2; ci++)
@@ -1196,11 +1149,11 @@ parse_bracket_exp (struct dfa *dfa)
else
{
wchar_t folded[CASE_FOLDED_BUFSIZE + 1];
- unsigned int n = (dfa->syntax.case_fold
- ? case_folded_counterparts (wc, folded + 1) + 1
- : 1);
+ int n = (dfa->syntax.case_fold
+ ? case_folded_counterparts (wc, folded + 1) + 1
+ : 1);
folded[0] = wc;
- for (unsigned int i = 0; i < n; i++)
+ for (int i = 0; i < n; i++)
if (!setbit_wc (folded[i], &ccl))
{
dfa->lex.brack.chars
@@ -1239,7 +1192,7 @@ parse_bracket_exp (struct dfa *dfa)
struct lexptr
{
char const *ptr;
- size_t left;
+ idx_t left;
};
static void
@@ -1487,7 +1440,7 @@ lex (struct dfa *dfa)
case '.':
if (backslash)
goto normal_char;
- if (dfa->canychar == (size_t) -1)
+ if (dfa->canychar < 0)
{
charclass ccl;
fillset (&ccl);
@@ -1610,8 +1563,8 @@ addtok_mb (struct dfa *dfa, token t, char mbprop)
{
if (dfa->talloc == dfa->tindex)
{
- dfa->tokens = x2nrealloc (dfa->tokens, &dfa->talloc,
- sizeof *dfa->tokens);
+ dfa->tokens = xpalloc (dfa->tokens, &dfa->talloc, 1, -1,
+ sizeof *dfa->tokens);
if (dfa->localeinfo.multibyte)
dfa->multibyte_prop = xnrealloc (dfa->multibyte_prop, dfa->talloc,
sizeof *dfa->multibyte_prop);
@@ -1659,7 +1612,7 @@ addtok (struct dfa *dfa, token t)
/* Extract wide characters into alternations for better performance.
This does not require UTF-8. */
- for (ptrdiff_t i = 0; i < dfa->lex.brack.nchars; i++)
+ for (idx_t i = 0; i < dfa->lex.brack.nchars; i++)
{
addtok_wc (dfa, dfa->lex.brack.chars[i]);
if (need_or)
@@ -1695,21 +1648,22 @@ addtok_wc (struct dfa *dfa, wint_t wc)
unsigned char buf[MB_LEN_MAX];
mbstate_t s = { 0 };
size_t stored_bytes = wcrtomb ((char *) buf, wc, &s);
+ int buflen;
if (stored_bytes != (size_t) -1)
- dfa->lex.cur_mb_len = stored_bytes;
+ buflen = stored_bytes;
else
{
/* This is merely stop-gap. buf[0] is undefined, yet skipping
the addtok_mb call altogether can corrupt the heap. */
- dfa->lex.cur_mb_len = 1;
+ buflen = 1;
buf[0] = 0;
}
- addtok_mb (dfa, buf[0], dfa->lex.cur_mb_len == 1 ? 3 : 1);
- for (int i = 1; i < dfa->lex.cur_mb_len; i++)
+ addtok_mb (dfa, buf[0], buflen == 1 ? 3 : 1);
+ for (int i = 1; i < buflen; i++)
{
- addtok_mb (dfa, buf[i], i == dfa->lex.cur_mb_len - 1 ? 2 : 0);
+ addtok_mb (dfa, buf[i], i == buflen - 1 ? 2 : 0);
addtok (dfa, CAT);
}
}
@@ -1717,55 +1671,111 @@ addtok_wc (struct dfa *dfa, wint_t wc)
static void
add_utf8_anychar (struct dfa *dfa)
{
- static charclass const utf8_classes[5] = {
- /* 80-bf: non-leading bytes. */
- CHARCLASS_INIT (0, 0, 0, 0, 0xffffffff, 0xffffffff, 0, 0),
+ /* Since the Unicode Standard Version 4.0.0 (2003), a well-formed
+ UTF-8 byte sequence has been defined as follows:
- /* 00-7f: 1-byte sequence. */
- CHARCLASS_INIT (0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0, 0, 0, 0),
+ ([\x00-\x7f]
+ |[\xc2-\xdf][\x80-\xbf]
+ |[\xe0][\xa0-\xbf][\x80-\xbf]
+ |[\xe1-\xec\xee-\xef][\x80-\xbf][\x80-\xbf]
+ |[\xed][\x80-\x9f][\x80-\xbf]
+ |[\xf0][\x90-\xbf][\x80-\xbf][\x80-\xbf])
+ |[\xf1-\xf3][\x80-\xbf][\x80-\xbf][\x80-\xbf]
+ |[\xf4][\x80-\x8f][\x80-\xbf][\x80-\xbf])
- /* c2-df: 2-byte sequence. */
- CHARCLASS_INIT (0, 0, 0, 0, 0, 0, 0xfffffffc, 0),
+ which I'll write more concisely "A|BC|DEC|FCC|GHC|IJCC|KCCC|LMCC",
+ where A = [\x00-\x7f], B = [\xc2-\xdf], C = [\x80-\xbf],
+ D = [\xe0], E = [\xa0-\xbf], F = [\xe1-\xec\xee-\xef], G = [\xed],
+ H = [\x80-\x9f], I = [\xf0],
+ J = [\x90-\xbf], K = [\xf1-\xf3], L = [\xf4], M = [\x80-\x8f].
- /* e0-ef: 3-byte sequence. */
- CHARCLASS_INIT (0, 0, 0, 0, 0, 0, 0, 0xffff),
+ This can be refactored to "A|(B|DE|GH|(F|IJ|LM|KC)C)C". */
- /* f0-f7: 4-byte sequence. */
- CHARCLASS_INIT (0, 0, 0, 0, 0, 0, 0, 0xff0000)
- };
- const unsigned int n = sizeof (utf8_classes) / sizeof (utf8_classes[0]);
+ /* Mnemonics for classes containing two or more bytes. */
+ enum { A, B, C, E, F, H, J, K, M };
- /* Define the five character classes that are needed below. */
- if (dfa->utf8_anychar_classes[0] == 0)
- for (unsigned int i = 0; i < n; i++)
- {
- charclass c = utf8_classes[i];
- if (i == 1)
- {
- if (!(dfa->syntax.syntax_bits & RE_DOT_NEWLINE))
- clrbit ('\n', &c);
- if (dfa->syntax.syntax_bits & RE_DOT_NOT_NULL)
- clrbit ('\0', &c);
- }
- dfa->utf8_anychar_classes[i] = CSET + charclass_index (dfa, &c);
- }
+ /* Mnemonics for single-byte tokens. */
+ enum { D_token = 0xe0, G_token = 0xed, I_token = 0xf0, L_token = 0xf4 };
+
+ static charclass const utf8_classes[] = {
+ /* A. 00-7f: 1-byte sequence. */
+ CHARCLASS_INIT (0xffffffffffffffff, 0xffffffffffffffff, 0, 0),
- /* A valid UTF-8 character is
+ /* B. c2-df: 1st byte of a 2-byte sequence. */
+ CHARCLASS_INIT (0, 0, 0, 0x00000000fffffffc),
- ([0x00-0x7f]
- |[0xc2-0xdf][0x80-0xbf]
- |[0xe0-0xef[0x80-0xbf][0x80-0xbf]
- |[0xf0-f7][0x80-0xbf][0x80-0xbf][0x80-0xbf])
+ /* C. 80-bf: non-leading bytes. */
+ CHARCLASS_INIT (0, 0, 0xffffffffffffffff, 0),
- which I'll write more concisely "B|CA|DAA|EAAA". Factor the [0x00-0x7f]
- and you get "B|(C|(D|EA)A)A". And since the token buffer is in reverse
- Polish notation, you get "B C D E A CAT OR A CAT OR A CAT OR". */
- unsigned int i;
- for (i = 1; i < n; i++)
- addtok (dfa, dfa->utf8_anychar_classes[i]);
- while (--i > 1)
+ /* D. e0 (just a token). */
+
+ /* E. a0-bf: 2nd byte of a "DEC" sequence. */
+ CHARCLASS_INIT (0, 0, 0xffffffff00000000, 0),
+
+ /* F. e1-ec + ee-ef: 1st byte of an "FCC" sequence. */
+ CHARCLASS_INIT (0, 0, 0, 0x0000dffe00000000),
+
+ /* G. ed (just a token). */
+
+ /* H. 80-9f: 2nd byte of a "GHC" sequence. */
+ CHARCLASS_INIT (0, 0, 0x000000000000ffff, 0),
+
+ /* I. f0 (just a token). */
+
+ /* J. 90-bf: 2nd byte of an "IJCC" sequence. */
+ CHARCLASS_INIT (0, 0, 0xffffffffffff0000, 0),
+
+ /* K. f1-f3: 1st byte of a "KCCC" sequence. */
+ CHARCLASS_INIT (0, 0, 0, 0x000e000000000000),
+
+ /* L. f4 (just a token). */
+
+ /* M. 80-8f: 2nd byte of a "LMCC" sequence. */
+ CHARCLASS_INIT (0, 0, 0x00000000000000ff, 0),
+ };
+
+ /* Define the character classes that are needed below. */
+ if (dfa->utf8_anychar_classes[0] == 0)
+ {
+ charclass c = utf8_classes[0];
+ if (! (dfa->syntax.syntax_bits & RE_DOT_NEWLINE))
+ clrbit ('\n', &c);
+ if (dfa->syntax.syntax_bits & RE_DOT_NOT_NULL)
+ clrbit ('\0', &c);
+ dfa->utf8_anychar_classes[0] = CSET + charclass_index (dfa, &c);
+
+ for (int i = 1; i < sizeof utf8_classes / sizeof *utf8_classes; i++)
+ dfa->utf8_anychar_classes[i]
+ = CSET + charclass_index (dfa, &utf8_classes[i]);
+ }
+
+ /* Implement the "A|(B|DE|GH|(F|IJ|LM|KC)C)C" pattern mentioned above.
+ The token buffer is in reverse Polish order, so we get
+ "A B D E CAT OR G H CAT OR F I J CAT OR L M CAT OR K
+ C CAT OR C CAT OR C CAT OR". */
+ addtok (dfa, dfa->utf8_anychar_classes[A]);
+ addtok (dfa, dfa->utf8_anychar_classes[B]);
+ addtok (dfa, D_token);
+ addtok (dfa, dfa->utf8_anychar_classes[E]);
+ addtok (dfa, CAT);
+ addtok (dfa, OR);
+ addtok (dfa, G_token);
+ addtok (dfa, dfa->utf8_anychar_classes[H]);
+ addtok (dfa, CAT);
+ addtok (dfa, OR);
+ addtok (dfa, dfa->utf8_anychar_classes[F]);
+ addtok (dfa, I_token);
+ addtok (dfa, dfa->utf8_anychar_classes[J]);
+ addtok (dfa, CAT);
+ addtok (dfa, OR);
+ addtok (dfa, L_token);
+ addtok (dfa, dfa->utf8_anychar_classes[M]);
+ addtok (dfa, CAT);
+ addtok (dfa, OR);
+ addtok (dfa, dfa->utf8_anychar_classes[K]);
+ for (int i = 0; i < 3; i++)
{
- addtok (dfa, dfa->utf8_anychar_classes[0]);
+ addtok (dfa, dfa->utf8_anychar_classes[C]);
addtok (dfa, CAT);
addtok (dfa, OR);
}
@@ -1843,9 +1853,8 @@ atom (struct dfa *dfa)
if (dfa->syntax.case_fold)
{
wchar_t folded[CASE_FOLDED_BUFSIZE];
- unsigned int n = case_folded_counterparts (dfa->lex.wctok,
- folded);
- for (unsigned int i = 0; i < n; i++)
+ int n = case_folded_counterparts (dfa->lex.wctok, folded);
+ for (int i = 0; i < n; i++)
{
addtok_wc (dfa, folded[i]);
addtok (dfa, OR);
@@ -1868,8 +1877,8 @@ atom (struct dfa *dfa)
}
/* Return the number of tokens in the given subexpression. */
-static size_t _GL_ATTRIBUTE_PURE
-nsubtoks (struct dfa const *dfa, size_t tindex)
+static idx_t _GL_ATTRIBUTE_PURE
+nsubtoks (struct dfa const *dfa, idx_t tindex)
{
switch (dfa->tokens[tindex - 1])
{
@@ -1882,7 +1891,7 @@ nsubtoks (struct dfa const *dfa, size_t tindex)
case CAT:
case OR:
{
- size_t ntoks1 = nsubtoks (dfa, tindex - 1);
+ idx_t ntoks1 = nsubtoks (dfa, tindex - 1);
return 1 + ntoks1 + nsubtoks (dfa, tindex - 1 - ntoks1);
}
}
@@ -1890,14 +1899,14 @@ nsubtoks (struct dfa const *dfa, size_t tindex)
/* Copy the given subexpression to the top of the tree. */
static void
-copytoks (struct dfa *dfa, size_t tindex, size_t ntokens)
+copytoks (struct dfa *dfa, idx_t tindex, idx_t ntokens)
{
if (dfa->localeinfo.multibyte)
- for (size_t i = 0; i < ntokens; ++i)
+ for (idx_t i = 0; i < ntokens; i++)
addtok_mb (dfa, dfa->tokens[tindex + i],
dfa->multibyte_prop[tindex + i]);
else
- for (size_t i = 0; i < ntokens; ++i)
+ for (idx_t i = 0; i < ntokens; i++)
addtok_mb (dfa, dfa->tokens[tindex + i], 3);
}
@@ -1909,8 +1918,8 @@ closure (struct dfa *dfa)
|| dfa->parse.tok == PLUS || dfa->parse.tok == REPMN)
if (dfa->parse.tok == REPMN && (dfa->lex.minrep || dfa->lex.maxrep))
{
- size_t ntokens = nsubtoks (dfa, dfa->tindex);
- size_t tindex = dfa->tindex - ntokens;
+ idx_t ntokens = nsubtoks (dfa, dfa->tindex);
+ idx_t tindex = dfa->tindex - ntokens;
if (dfa->lex.maxrep < 0)
addtok (dfa, PLUS);
if (dfa->lex.minrep == 0)
@@ -1966,11 +1975,10 @@ regexp (struct dfa *dfa)
}
}
-/* Main entry point for the parser. S is a string to be parsed, len is the
- length of the string, so s can include NUL characters. D is a pointer to
- the struct dfa to parse into. */
-static void
-dfaparse (char const *s, size_t len, struct dfa *d)
+/* Parse a string S of length LEN into D. S can include NUL characters.
+ This is the main entry point for the parser. */
+void
+dfaparse (char const *s, idx_t len, struct dfa *d)
{
d->lex.ptr = s;
d->lex.left = len;
@@ -2018,7 +2026,7 @@ copy (position_set const *src, position_set *dst)
}
static void
-alloc_position_set (position_set *s, size_t size)
+alloc_position_set (position_set *s, idx_t size)
{
s->elems = xnmalloc (size, sizeof *s->elems);
s->alloc = size;
@@ -2032,11 +2040,11 @@ alloc_position_set (position_set *s, size_t size)
static void
insert (position p, position_set *s)
{
- ptrdiff_t count = s->nelem;
- ptrdiff_t lo = 0, hi = count;
+ idx_t count = s->nelem;
+ idx_t lo = 0, hi = count;
while (lo < hi)
{
- ptrdiff_t mid = (lo + hi) >> 1;
+ idx_t mid = (lo + hi) >> 1;
if (s->elems[mid].index < p.index)
lo = mid + 1;
else if (s->elems[mid].index == p.index)
@@ -2049,7 +2057,7 @@ insert (position p, position_set *s)
}
s->elems = maybe_realloc (s->elems, count, &s->alloc, -1, sizeof *s->elems);
- for (ptrdiff_t i = count; i > lo; i--)
+ for (idx_t i = count; i > lo; i--)
s->elems[i] = s->elems[i - 1];
s->elems[lo] = p;
++s->nelem;
@@ -2058,7 +2066,7 @@ insert (position p, position_set *s)
static void
append (position p, position_set *s)
{
- ptrdiff_t count = s->nelem;
+ idx_t count = s->nelem;
s->elems = maybe_realloc (s->elems, count, &s->alloc, -1, sizeof *s->elems);
s->elems[s->nelem++] = p;
}
@@ -2070,7 +2078,7 @@ static void
merge_constrained (position_set const *s1, position_set const *s2,
unsigned int c2, position_set *m)
{
- ptrdiff_t i = 0, j = 0;
+ idx_t i = 0, j = 0;
if (m->alloc - s1->nelem < s2->nelem)
{
@@ -2114,7 +2122,7 @@ merge2 (position_set *dst, position_set const *src, position_set *m)
{
if (src->nelem < 4)
{
- for (ptrdiff_t i = 0; i < src->nelem; ++i)
+ for (idx_t i = 0; i < src->nelem; i++)
insert (src->elems[i], dst);
}
else
@@ -2127,19 +2135,19 @@ merge2 (position_set *dst, position_set const *src, position_set *m)
/* Delete a position from a set. Return the nonzero constraint of the
deleted position, or zero if there was no such position. */
static unsigned int
-delete (size_t del, position_set *s)
+delete (idx_t del, position_set *s)
{
- size_t count = s->nelem;
- size_t lo = 0, hi = count;
+ idx_t count = s->nelem;
+ idx_t lo = 0, hi = count;
while (lo < hi)
{
- size_t mid = (lo + hi) >> 1;
+ idx_t mid = (lo + hi) >> 1;
if (s->elems[mid].index < del)
lo = mid + 1;
else if (s->elems[mid].index == del)
{
unsigned int c = s->elems[mid].constraint;
- size_t i;
+ idx_t i;
for (i = mid; i + 1 < count; i++)
s->elems[i] = s->elems[i + 1];
s->nelem = i;
@@ -2153,7 +2161,7 @@ delete (size_t del, position_set *s)
/* Replace a position with the followed set. */
static void
-replace (position_set *dst, size_t del, position_set *add,
+replace (position_set *dst, idx_t del, position_set *add,
unsigned int constraint, position_set *tmp)
{
unsigned int c = delete (del, dst) & constraint;
@@ -2177,7 +2185,10 @@ state_index (struct dfa *d, position_set const *s, int context)
token first_end = 0;
for (i = 0; i < s->nelem; ++i)
- hash ^= s->elems[i].index + s->elems[i].constraint;
+ {
+ size_t ind = s->elems[i].index;
+ hash ^= ind + s->elems[i].constraint;
+ }
/* Try to find a state that exactly matches the proposed one. */
for (i = 0; i < d->sindex; ++i)
@@ -2195,10 +2206,10 @@ state_index (struct dfa *d, position_set const *s, int context)
}
#ifdef DEBUG
- fprintf (stderr, "new state %zd\n nextpos:", i);
+ fprintf (stderr, "new state %td\n nextpos:", i);
for (state_num j = 0; j < s->nelem; j++)
{
- fprintf (stderr, " %zu:", s->elems[j].index);
+ fprintf (stderr, " %td:", s->elems[j].index);
prtok (d->tokens[s->elems[j].index]);
}
fprintf (stderr, "\n context:");
@@ -2260,7 +2271,7 @@ epsclosure (struct dfa const *d)
{
position_set tmp;
alloc_position_set (&tmp, d->nleaves);
- for (size_t i = 0; i < d->tindex; ++i)
+ for (idx_t i = 0; i < d->tindex; i++)
if (d->follows[i].nelem > 0 && d->tokens[i] >= NOTCHAR
&& d->tokens[i] != BACKREF && d->tokens[i] != ANYCHAR
&& d->tokens[i] != MBCSET && d->tokens[i] < CSET)
@@ -2293,7 +2304,7 @@ epsclosure (struct dfa const *d)
delete (i, &d->follows[i]);
- for (size_t j = 0; j < d->tindex; j++)
+ for (idx_t j = 0; j < d->tindex; j++)
if (i != j && d->follows[j].nelem > 0)
replace (&d->follows[j], i, &d->follows[i], constraint, &tmp);
}
@@ -2308,7 +2319,7 @@ charclass_context (struct dfa const *dfa, charclass const *c)
{
int context = 0;
- for (unsigned int j = 0; j < CHARCLASS_WORDS; ++j)
+ for (int j = 0; j < CHARCLASS_WORDS; j++)
{
if (c->w[j] & dfa->syntax.newline.w[j])
context |= CTX_NEWLINE;
@@ -2332,7 +2343,7 @@ state_separate_contexts (struct dfa *d, position_set const *s)
{
int separate_contexts = 0;
- for (size_t j = 0; j < s->nelem; j++)
+ for (idx_t j = 0; j < s->nelem; j++)
separate_contexts |= d->separates[s->elems[j].index];
return separate_contexts;
@@ -2359,17 +2370,17 @@ enum
};
static void
-merge_nfa_state (struct dfa *d, size_t tindex, char *flags,
+merge_nfa_state (struct dfa *d, idx_t tindex, char *flags,
position_set *merged)
{
position_set *follows = d->follows;
- ptrdiff_t nelem = 0;
+ idx_t nelem = 0;
d->constraints[tindex] = 0;
- for (ptrdiff_t i = 0; i < follows[tindex].nelem; i++)
+ for (idx_t i = 0; i < follows[tindex].nelem; i++)
{
- size_t sindex = follows[tindex].elems[i].index;
+ idx_t sindex = follows[tindex].elems[i].index;
/* Skip the node as pruned in future. */
unsigned int iconstraint = follows[tindex].elems[i].constraint;
@@ -2384,11 +2395,11 @@ merge_nfa_state (struct dfa *d, size_t tindex, char *flags,
if (!(flags[sindex] & (OPT_LPAREN | OPT_RPAREN)))
{
- ptrdiff_t j;
+ idx_t j;
for (j = 0; j < nelem; j++)
{
- size_t dindex = follows[tindex].elems[j].index;
+ idx_t dindex = follows[tindex].elems[j].index;
if (follows[tindex].elems[j].constraint != iconstraint)
continue;
@@ -2424,19 +2435,14 @@ merge_nfa_state (struct dfa *d, size_t tindex, char *flags,
static int
compare (const void *a, const void *b)
{
- int aindex;
- int bindex;
-
- aindex = (int) ((position *) a)->index;
- bindex = (int) ((position *) b)->index;
-
- return aindex - bindex;
+ position const *p = a, *q = b;
+ return p->index < q->index ? -1 : p->index > q->index;
}
static void
reorder_tokens (struct dfa *d)
{
- ptrdiff_t nleaves;
+ idx_t nleaves;
ptrdiff_t *map;
token *tokens;
position_set *follows;
@@ -2449,7 +2455,7 @@ reorder_tokens (struct dfa *d)
map[0] = nleaves++;
- for (ptrdiff_t i = 1; i < d->tindex; i++)
+ for (idx_t i = 1; i < d->tindex; i++)
map[i] = -1;
tokens = xnmalloc (d->nleaves, sizeof *tokens);
@@ -2461,7 +2467,7 @@ reorder_tokens (struct dfa *d)
else
multibyte_prop = NULL;
- for (ptrdiff_t i = 0; i < d->tindex; i++)
+ for (idx_t i = 0; i < d->tindex; i++)
{
if (map[i] == -1)
{
@@ -2478,7 +2484,7 @@ reorder_tokens (struct dfa *d)
if (multibyte_prop != NULL)
multibyte_prop[map[i]] = d->multibyte_prop[i];
- for (ptrdiff_t j = 0; j < d->follows[i].nelem; j++)
+ for (idx_t j = 0; j < d->follows[i].nelem; j++)
{
if (map[d->follows[i].elems[j].index] == -1)
map[d->follows[i].elems[j].index] = nleaves++;
@@ -2490,7 +2496,7 @@ reorder_tokens (struct dfa *d)
sizeof *d->follows[i].elems, compare);
}
- for (ptrdiff_t i = 0; i < nleaves; i++)
+ for (idx_t i = 0; i < nleaves; i++)
{
d->tokens[i] = tokens[i];
d->follows[i] = follows[i];
@@ -2512,16 +2518,11 @@ reorder_tokens (struct dfa *d)
static void
dfaoptimize (struct dfa *d)
{
- char *flags;
- position_set merged0;
- position_set *merged;
-
- flags = xmalloc (d->tindex * sizeof *flags);
- memset (flags, 0, d->tindex * sizeof *flags);
+ char *flags = xzalloc (d->tindex);
- for (size_t i = 0; i < d->tindex; i++)
+ for (idx_t i = 0; i < d->tindex; i++)
{
- for (ptrdiff_t j = 0; j < d->follows[i].nelem; j++)
+ for (idx_t j = 0; j < d->follows[i].nelem; j++)
{
if (d->follows[i].elems[j].index == i)
flags[d->follows[i].elems[j].index] |= OPT_REPEAT;
@@ -2536,12 +2537,13 @@ dfaoptimize (struct dfa *d)
flags[0] |= OPT_QUEUED;
- merged = &merged0;
+ position_set merged0;
+ position_set *merged = &merged0;
alloc_position_set (merged, d->nleaves);
d->constraints = xnmalloc (d->tindex, sizeof *d->constraints);
- for (ptrdiff_t i = 0; i < d->tindex; i++)
+ for (idx_t i = 0; i < d->tindex; i++)
if (flags[i] & OPT_QUEUED)
merge_nfa_state (d, i, flags, merged);
@@ -2621,8 +2623,8 @@ dfaanalyze (struct dfa *d, bool searchflag)
bool nullable;
/* Counts of firstpos and lastpos sets. */
- size_t nfirstpos;
- size_t nlastpos;
+ idx_t nfirstpos;
+ idx_t nlastpos;
} *stkalloc = xnmalloc (d->depth, sizeof *stkalloc), *stk = stkalloc;
position_set merged; /* Result of merging sets. */
@@ -2631,9 +2633,9 @@ dfaanalyze (struct dfa *d, bool searchflag)
#ifdef DEBUG
fprintf (stderr, "dfaanalyze:\n");
- for (size_t i = 0; i < d->tindex; ++i)
+ for (idx_t i = 0; i < d->tindex; i++)
{
- fprintf (stderr, " %zu:", i);
+ fprintf (stderr, " %td:", i);
prtok (d->tokens[i]);
}
putc ('\n', stderr);
@@ -2643,7 +2645,7 @@ dfaanalyze (struct dfa *d, bool searchflag)
alloc_position_set (&merged, d->nleaves);
d->follows = xcalloc (d->tindex, sizeof *d->follows);
- for (size_t i = 0; i < d->tindex; ++i)
+ for (idx_t i = 0; i < d->tindex; i++)
{
switch (d->tokens[i])
{
@@ -2664,7 +2666,7 @@ dfaanalyze (struct dfa *d, bool searchflag)
tmp.elems = firstpos - stk[-1].nfirstpos;
tmp.nelem = stk[-1].nfirstpos;
position *p = lastpos - stk[-1].nlastpos;
- for (size_t j = 0; j < stk[-1].nlastpos; j++)
+ for (idx_t j = 0; j < stk[-1].nlastpos; j++)
{
merge (&tmp, &d->follows[p[j].index], &merged);
copy (&merged, &d->follows[p[j].index]);
@@ -2684,7 +2686,7 @@ dfaanalyze (struct dfa *d, bool searchflag)
tmp.nelem = stk[-1].nfirstpos;
tmp.elems = firstpos - stk[-1].nfirstpos;
position *p = lastpos - stk[-1].nlastpos - stk[-2].nlastpos;
- for (size_t j = 0; j < stk[-2].nlastpos; j++)
+ for (idx_t j = 0; j < stk[-2].nlastpos; j++)
{
merge (&tmp, &d->follows[p[j].index], &merged);
copy (&merged, &d->follows[p[j].index]);
@@ -2705,7 +2707,7 @@ dfaanalyze (struct dfa *d, bool searchflag)
else
{
position *p = lastpos - stk[-1].nlastpos - stk[-2].nlastpos;
- for (size_t j = 0; j < stk[-1].nlastpos; j++)
+ for (idx_t j = 0; j < stk[-1].nlastpos; j++)
p[j] = p[j + stk[-2].nlastpos];
lastpos -= stk[-2].nlastpos;
stk[-2].nlastpos = stk[-1].nlastpos;
@@ -2748,21 +2750,21 @@ dfaanalyze (struct dfa *d, bool searchflag)
}
#ifdef DEBUG
/* ... balance the above nonsyntactic #ifdef goo... */
- fprintf (stderr, "node %zu:", i);
+ fprintf (stderr, "node %td:", i);
prtok (d->tokens[i]);
putc ('\n', stderr);
fprintf (stderr,
stk[-1].nullable ? " nullable: yes\n" : " nullable: no\n");
fprintf (stderr, " firstpos:");
- for (size_t j = 0; j < stk[-1].nfirstpos; j++)
+ for (idx_t j = 0; j < stk[-1].nfirstpos; j++)
{
- fprintf (stderr, " %zu:", firstpos[j - stk[-1].nfirstpos].index);
+ fprintf (stderr, " %td:", firstpos[j - stk[-1].nfirstpos].index);
prtok (d->tokens[firstpos[j - stk[-1].nfirstpos].index]);
}
fprintf (stderr, "\n lastpos:");
- for (size_t j = 0; j < stk[-1].nlastpos; j++)
+ for (idx_t j = 0; j < stk[-1].nlastpos; j++)
{
- fprintf (stderr, " %zu:", lastpos[j - stk[-1].nlastpos].index);
+ fprintf (stderr, " %td:", lastpos[j - stk[-1].nlastpos].index);
prtok (d->tokens[lastpos[j - stk[-1].nlastpos].index]);
}
putc ('\n', stderr);
@@ -2776,17 +2778,17 @@ dfaanalyze (struct dfa *d, bool searchflag)
dfaoptimize (d);
#ifdef DEBUG
- for (size_t i = 0; i < d->tindex; ++i)
+ for (idx_t i = 0; i < d->tindex; i++)
if (d->tokens[i] == BEG || d->tokens[i] < NOTCHAR
|| d->tokens[i] == BACKREF || d->tokens[i] == ANYCHAR
|| d->tokens[i] == MBCSET || d->tokens[i] >= CSET)
{
- fprintf (stderr, "follows(%zu:", i);
+ fprintf (stderr, "follows(%td:", i);
prtok (d->tokens[i]);
fprintf (stderr, "):");
- for (size_t j = 0; j < d->follows[i].nelem; j++)
+ for (idx_t j = 0; j < d->follows[i].nelem; j++)
{
- fprintf (stderr, " %zu:", d->follows[i].elems[j].index);
+ fprintf (stderr, " %td:", d->follows[i].elems[j].index);
prtok (d->tokens[d->follows[i].elems[j].index]);
}
putc ('\n', stderr);
@@ -2802,7 +2804,7 @@ dfaanalyze (struct dfa *d, bool searchflag)
d->separates = xnmalloc (d->tindex, sizeof *d->separates);
- for (ptrdiff_t i = 0; i < d->tindex; i++)
+ for (idx_t i = 0; i < d->tindex; i++)
{
d->separates[i] = 0;
@@ -2811,7 +2813,7 @@ dfaanalyze (struct dfa *d, bool searchflag)
if (prev_letter_dependent (d->constraints[i]))
d->separates[i] |= CTX_LETTER;
- for (ptrdiff_t j = 0; j < d->follows[i].nelem; j++)
+ for (idx_t j = 0; j < d->follows[i].nelem; j++)
{
if (prev_newline_dependent (d->follows[i].elems[j].constraint))
d->separates[i] |= CTX_NEWLINE;
@@ -2847,12 +2849,12 @@ realloc_trans_if_necessary (struct dfa *d)
if (oldalloc < d->sindex)
{
state_num **realtrans = d->trans ? d->trans - 2 : NULL;
- ptrdiff_t newalloc1 = realtrans ? d->tralloc + 2 : 0;
+ idx_t newalloc1 = realtrans ? d->tralloc + 2 : 0;
realtrans = xpalloc (realtrans, &newalloc1, d->sindex - oldalloc,
-1, sizeof *realtrans);
realtrans[0] = realtrans[1] = NULL;
d->trans = realtrans + 2;
- ptrdiff_t newalloc = d->tralloc = newalloc1 - 2;
+ idx_t newalloc = d->tralloc = newalloc1 - 2;
d->fails = xnrealloc (d->fails, newalloc, sizeof *d->fails);
d->success = xnrealloc (d->success, newalloc, sizeof *d->success);
d->newlines = xnrealloc (d->newlines, newalloc, sizeof *d->newlines);
@@ -2965,8 +2967,8 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
/* Find the union of the follows of the positions of the group.
This is a hideously inefficient loop. Fix it someday. */
- for (size_t j = 0; j < d->states[s].elems.nelem; ++j)
- for (size_t k = 0;
+ for (idx_t j = 0; j < d->states[s].elems.nelem; j++)
+ for (idx_t k = 0;
k < d->follows[d->states[s].elems.elems[j].index].nelem; ++k)
insert (d->follows[d->states[s].elems.elems[j].index].elems[k],
&follows);
@@ -2978,7 +2980,7 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
charclass label;
fillset (&label);
- for (size_t i = 0; i < follows.nelem; ++i)
+ for (idx_t i = 0; i < follows.nelem; i++)
{
charclass matches; /* Set of matching characters. */
position pos = follows.elems[i];
@@ -3025,15 +3027,15 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
{
if (!succeeds_in_context (pos.constraint,
d->states[s].context, CTX_NEWLINE))
- for (size_t j = 0; j < CHARCLASS_WORDS; ++j)
+ for (int j = 0; j < CHARCLASS_WORDS; j++)
matches.w[j] &= ~d->syntax.newline.w[j];
if (!succeeds_in_context (pos.constraint,
d->states[s].context, CTX_LETTER))
- for (size_t j = 0; j < CHARCLASS_WORDS; ++j)
+ for (int j = 0; j < CHARCLASS_WORDS; ++j)
matches.w[j] &= ~d->syntax.letters.w[j];
if (!succeeds_in_context (pos.constraint,
d->states[s].context, CTX_NONE))
- for (size_t j = 0; j < CHARCLASS_WORDS; ++j)
+ for (int j = 0; j < CHARCLASS_WORDS; ++j)
matches.w[j] &= d->syntax.letters.w[j] | d->syntax.newline.w[j];
/* If there are no characters left, there's no point in going on. */
@@ -3048,24 +3050,24 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
}
#ifdef DEBUG
- fprintf (stderr, " nextpos %zu:", pos.index);
+ fprintf (stderr, " nextpos %td:", pos.index);
prtok (d->tokens[pos.index]);
fprintf (stderr, " of");
- for (size_t j = 0; j < NOTCHAR; j++)
+ for (unsigned j = 0; j < NOTCHAR; j++)
if (tstbit (j, &matches))
- fprintf (stderr, " 0x%02zx", j);
+ fprintf (stderr, " 0x%02x", j);
fprintf (stderr, "\n");
#endif
if (matched)
{
- for (size_t k = 0; k < CHARCLASS_WORDS; ++k)
+ for (int k = 0; k < CHARCLASS_WORDS; ++k)
label.w[k] &= matches.w[k];
append (pos, &group);
}
else
{
- for (size_t k = 0; k < CHARCLASS_WORDS; ++k)
+ for (int k = 0; k < CHARCLASS_WORDS; ++k)
label.w[k] &= ~matches.w[k];
}
}
@@ -3099,7 +3101,7 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
if (!mergeit)
{
mergeit = true;
- for (size_t j = 0; mergeit && j < group.nelem; j++)
+ for (idx_t j = 0; mergeit && j < group.nelem; j++)
mergeit &= d->multibyte_prop[group.elems[j].index];
}
if (mergeit)
@@ -3150,7 +3152,7 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
}
/* Set the transitions for each character in the label. */
- for (size_t i = 0; i < NOTCHAR; i++)
+ for (int i = 0; i < NOTCHAR; i++)
if (tstbit (i, &label))
switch (d->syntax.sbit[i])
{
@@ -3167,7 +3169,7 @@ build_state (state_num s, struct dfa *d, unsigned char uc)
#ifdef DEBUG
fprintf (stderr, "trans table %td", s);
- for (size_t i = 0; i < NOTCHAR; ++i)
+ for (int i = 0; i < NOTCHAR; ++i)
{
if (!(i & 0xf))
fprintf (stderr, "\n");
@@ -3346,11 +3348,11 @@ skip_remains_mb (struct dfa *d, unsigned char const *p,
- [[:alpha:]] etc. in multibyte locale (except [[:digit:]] works OK)
- back-reference: (.)\1
- word-delimiter in multibyte locale: \<, \>, \b, \B
- See using_simple_locale for the definition of "simple locale". */
+ See struct localeinfo.simple for the definition of "simple locale". */
static inline char *
dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
- size_t *count, bool multibyte)
+ ptrdiff_t *count, bool multibyte)
{
if (MAX_TRCOUNT <= d->sindex)
{
@@ -3408,7 +3410,7 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
alloc_position_set (&d->mb_follows, d->nleaves);
}
- size_t nlcount = 0;
+ idx_t nlcount = 0;
for (;;)
{
state_num *t;
@@ -3533,14 +3535,14 @@ dfaexec_main (struct dfa *d, char const *begin, char *end, bool allow_nl,
static char *
dfaexec_mb (struct dfa *d, char const *begin, char *end,
- bool allow_nl, size_t *count, bool *backref)
+ bool allow_nl, ptrdiff_t *count, bool *backref)
{
return dfaexec_main (d, begin, end, allow_nl, count, true);
}
static char *
dfaexec_sb (struct dfa *d, char const *begin, char *end,
- bool allow_nl, size_t *count, bool *backref)
+ bool allow_nl, ptrdiff_t *count, bool *backref)
{
return dfaexec_main (d, begin, end, allow_nl, count, false);
}
@@ -3549,7 +3551,7 @@ dfaexec_sb (struct dfa *d, char const *begin, char *end,
any regexp that uses a construct not supported by this code. */
static char *
dfaexec_noop (struct dfa *d, char const *begin, char *end,
- bool allow_nl, size_t *count, bool *backref)
+ bool allow_nl, ptrdiff_t *count, bool *backref)
{
*backref = true;
return (char *) begin;
@@ -3561,7 +3563,7 @@ dfaexec_noop (struct dfa *d, char const *begin, char *end,
char *
dfaexec (struct dfa *d, char const *begin, char *end,
- bool allow_nl, size_t *count, bool *backref)
+ bool allow_nl, ptrdiff_t *count, bool *backref)
{
return d->dfaexec (d, begin, end, allow_nl, count, backref);
}
@@ -3598,7 +3600,7 @@ free_mbdata (struct dfa *d)
static bool _GL_ATTRIBUTE_PURE
dfa_supported (struct dfa const *d)
{
- for (size_t i = 0; i < d->tindex; i++)
+ for (idx_t i = 0; i < d->tindex; i++)
{
switch (d->tokens[i])
{
@@ -3626,7 +3628,7 @@ maybe_disable_superset_dfa (struct dfa *d)
return;
bool have_backref = false;
- for (size_t i = 0; i < d->tindex; ++i)
+ for (idx_t i = 0; i < d->tindex; i++)
{
switch (d->tokens[i])
{
@@ -3691,8 +3693,8 @@ dfassbuild (struct dfa *d)
bool have_achar = false;
bool have_nchar = false;
- size_t j;
- for (size_t i = j = 0; i < d->tindex; i++)
+ idx_t j;
+ for (idx_t i = j = 0; i < d->tindex; i++)
{
switch (d->tokens[i])
{
@@ -3741,11 +3743,15 @@ dfassbuild (struct dfa *d)
}
}
-/* Parse and analyze a single string of the given length. */
+/* Parse a string S of length LEN into D (but skip this step if S is null).
+ Then analyze D and build a matcher for it.
+ SEARCHFLAG says whether to build a searching or an exact matcher. */
void
-dfacomp (char const *s, size_t len, struct dfa *d, bool searchflag)
+dfacomp (char const *s, idx_t len, struct dfa *d, bool searchflag)
{
- dfaparse (s, len, d);
+ if (s != NULL)
+ dfaparse (s, len, d);
+
dfassbuild (d);
if (dfa_supported (d))
@@ -3778,7 +3784,7 @@ dfafree (struct dfa *d)
free (d->constraints);
free (d->separates);
- for (size_t i = 0; i < d->sindex; ++i)
+ for (idx_t i = 0; i < d->sindex; i++)
{
free (d->states[i].elems.elems);
free (d->states[i].mbps.elems);
@@ -3787,14 +3793,14 @@ dfafree (struct dfa *d)
if (d->follows)
{
- for (size_t i = 0; i < d->tindex; ++i)
+ for (idx_t i = 0; i < d->tindex; i++)
free (d->follows[i].elems);
free (d->follows);
}
if (d->trans)
{
- for (size_t i = 0; i < d->tralloc; ++i)
+ for (idx_t i = 0; i < d->tralloc; i++)
{
free (d->trans[i]);
free (d->fails[i]);
@@ -3898,10 +3904,10 @@ dfafree (struct dfa *d)
static char *
icatalloc (char *old, char const *new)
{
- size_t newsize = strlen (new);
+ idx_t newsize = strlen (new);
if (newsize == 0)
return old;
- size_t oldsize = strlen (old);
+ idx_t oldsize = strlen (old);
char *result = xrealloc (old, oldsize + newsize + 1);
memcpy (result + oldsize, new, newsize + 1);
return result;
@@ -3915,20 +3921,20 @@ freelist (char **cpp)
}
static char **
-enlist (char **cpp, char *new, size_t len)
+enlist (char **cpp, char *new, idx_t len)
{
new = memcpy (xmalloc (len + 1), new, len);
new[len] = '\0';
/* Is there already something in the list that's new (or longer)? */
- size_t i;
- for (i = 0; cpp[i] != NULL; ++i)
+ idx_t i;
+ for (i = 0; cpp[i] != NULL; i++)
if (strstr (cpp[i], new) != NULL)
{
free (new);
return cpp;
}
/* Eliminate any obsoleted strings. */
- for (size_t j = 0; cpp[j] != NULL; )
+ for (idx_t j = 0; cpp[j] != NULL; )
if (strstr (new, cpp[j]) == NULL)
++j;
else
@@ -3955,11 +3961,11 @@ comsubs (char *left, char const *right)
for (char *lcp = left; *lcp != '\0'; lcp++)
{
- size_t len = 0;
+ idx_t len = 0;
char *rcp = strchr (right, *lcp);
while (rcp != NULL)
{
- size_t i;
+ idx_t i;
for (i = 1; lcp[i] != '\0' && lcp[i] == rcp[i]; ++i)
continue;
if (i > len)
@@ -3987,9 +3993,9 @@ inboth (char **left, char **right)
{
char **both = xzalloc (sizeof *both);
- for (size_t lnum = 0; left[lnum] != NULL; ++lnum)
+ for (idx_t lnum = 0; left[lnum] != NULL; lnum++)
{
- for (size_t rnum = 0; right[rnum] != NULL; ++rnum)
+ for (idx_t rnum = 0; right[rnum] != NULL; rnum++)
{
char **temp = comsubs (left[lnum], right[rnum]);
both = addlists (both, temp);
@@ -4014,7 +4020,7 @@ struct must
};
static must *
-allocmust (must *mp, size_t size)
+allocmust (must *mp, idx_t size)
{
must *new_mp = xmalloc (sizeof *new_mp);
new_mp->in = xzalloc (sizeof *new_mp->in);
@@ -4058,9 +4064,9 @@ dfamust (struct dfa const *d)
bool endline = false;
bool need_begline = false;
bool need_endline = false;
- bool case_fold_unibyte = d->syntax.case_fold && MB_CUR_MAX == 1;
+ bool case_fold_unibyte = d->syntax.case_fold & !d->localeinfo.multibyte;
- for (size_t ri = 1; ri + 1 < d->tindex; ri++)
+ for (idx_t ri = 1; ri + 1 < d->tindex; ri++)
{
token t = d->tokens[ri];
switch (t)
@@ -4100,7 +4106,7 @@ dfamust (struct dfa const *d)
char **new;
must *rmp = mp;
must *lmp = mp = mp->prev;
- size_t j, ln, rn, n;
+ idx_t j, ln, rn, n;
/* Guaranteed to be. Unlikely, but ... */
if (streq (lmp->is, rmp->is))
@@ -4115,7 +4121,7 @@ dfamust (struct dfa const *d)
lmp->endline = false;
}
/* Left side--easy */
- size_t i = 0;
+ idx_t i = 0;
while (lmp->left[i] != '\0' && lmp->left[i] == rmp->left[i])
++i;
lmp->left[i] = '\0';
@@ -4145,7 +4151,7 @@ dfamust (struct dfa const *d)
case END:
assert (!mp->prev);
- for (size_t i = 0; mp->in[i] != NULL; ++i)
+ for (idx_t i = 0; mp->in[i] != NULL; i++)
if (strlen (mp->in[i]) > strlen (result))
result = mp->in[i];
if (streq (result, mp->is))
@@ -4169,8 +4175,8 @@ dfamust (struct dfa const *d)
lmp->in = addlists (lmp->in, rmp->in);
if (lmp->right[0] != '\0' && rmp->left[0] != '\0')
{
- size_t lrlen = strlen (lmp->right);
- size_t rllen = strlen (rmp->left);
+ idx_t lrlen = strlen (lmp->right);
+ idx_t rllen = strlen (rmp->left);
char *tp = xmalloc (lrlen + rllen);
memcpy (tp, lmp->right, lrlen);
memcpy (tp + lrlen, rmp->left, rllen);
@@ -4235,7 +4241,7 @@ dfamust (struct dfa const *d)
}
}
- size_t rj = ri + 2;
+ idx_t rj = ri + 2;
if (d->tokens[ri + 1] == CAT)
{
for (; rj < d->tindex - 1; rj += 2)
@@ -4250,7 +4256,7 @@ dfamust (struct dfa const *d)
mp->is[0] = mp->left[0] = mp->right[0]
= case_fold_unibyte ? toupper (t) : t;
- size_t i;
+ idx_t i;
for (i = 1; ri + 2 < rj; i++)
{
ri += 2;
@@ -4268,11 +4274,11 @@ dfamust (struct dfa const *d)
struct dfamust *dm = NULL;
if (*result)
{
- dm = xmalloc (sizeof *dm);
+ dm = xmalloc (FLEXSIZEOF (struct dfamust, must, strlen (result) + 1));
dm->exact = exact;
dm->begline = begline;
dm->endline = endline;
- dm->must = xstrdup (result);
+ strcpy (dm->must, result);
}
while (mp)
@@ -4288,7 +4294,6 @@ dfamust (struct dfa const *d)
void
dfamustfree (struct dfamust *dm)
{
- free (dm->must);
free (dm);
}
@@ -4305,13 +4310,11 @@ dfasyntax (struct dfa *dfa, struct localeinfo const *linfo,
{
memset (dfa, 0, offsetof (struct dfa, dfaexec));
dfa->dfaexec = linfo->multibyte ? dfaexec_mb : dfaexec_sb;
- dfa->simple_locale = using_simple_locale (linfo->multibyte);
dfa->localeinfo = *linfo;
dfa->fast = !dfa->localeinfo.multibyte;
dfa->canychar = -1;
- dfa->lex.cur_mb_len = 1;
dfa->syntax.syntax_bits_set = true;
dfa->syntax.case_fold = (bits & RE_ICASE) != 0;
dfa->syntax.anchor = (dfaopts & DFA_ANCHOR) != 0;
@@ -4341,4 +4344,16 @@ dfasyntax (struct dfa *dfa, struct localeinfo const *linfo,
}
}
+/* Initialize TO by copying FROM's syntax settings. */
+void
+dfacopysyntax (struct dfa *to, struct dfa const *from)
+{
+ memset (to, 0, offsetof (struct dfa, syntax));
+ to->canychar = -1;
+ to->fast = from->fast;
+ to->syntax = from->syntax;
+ to->dfaexec = from->dfaexec;
+ to->localeinfo = from->localeinfo;
+}
+
/* vim:set shiftwidth=2: */
diff --git a/lib/dfa.h b/lib/dfa.h
index fea815d..c5bff89 100644
--- a/lib/dfa.h
+++ b/lib/dfa.h
@@ -1,5 +1,5 @@
/* dfa.h - declarations for GNU deterministic regexp compiler
- Copyright (C) 1988, 1998, 2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1998, 2007, 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
@@ -31,15 +31,21 @@ struct dfamust
bool exact;
bool begline;
bool endline;
- char *must;
+ char must[FLEXIBLE_ARRAY_MEMBER];
};
/* The dfa structure. It is completely opaque. */
struct dfa;
+/* Needed when Gnulib is not used. */
+#ifndef _GL_ATTRIBUTE_MALLOC
+# define _GL_ATTRIBUTE_MALLOC
+#endif
+
/* Entry points. */
/* Allocate a struct dfa. The struct dfa is completely opaque.
+ It should be initialized via dfasyntax or dfacopysyntax before other use.
The returned pointer should be passed directly to free() after
calling dfafree() on it. */
extern struct dfa *dfaalloc (void) _GL_ATTRIBUTE_MALLOC;
@@ -56,8 +62,7 @@ enum
DFA_EOL_NUL = 1 << 1
};
-/* Initialize or reinitialize a DFA. This must be called before
- any of the routines below. The arguments are:
+/* Initialize or reinitialize a DFA. The arguments are:
1. The DFA to operate on.
2. Information about the current locale.
3. Syntax bits described in regex.h.
@@ -65,16 +70,24 @@ enum
extern void dfasyntax (struct dfa *, struct localeinfo const *,
reg_syntax_t, int);
-/* Build and return the struct dfamust from the given struct dfa. */
+/* Initialize or reinitialize a DFA from an already-initialized DFA. */
+extern void dfacopysyntax (struct dfa *, struct dfa const *);
+
+/* Parse the given string of given length into the given struct dfa. */
+extern void dfaparse (char const *, ptrdiff_t, struct dfa *);
+
+/* Allocate and return a struct dfamust from a struct dfa that was
+ initialized by dfaparse and not yet given to dfacomp. */
extern struct dfamust *dfamust (struct dfa const *);
/* Free the storage held by the components of a struct dfamust. */
extern void dfamustfree (struct dfamust *);
/* Compile the given string of the given length into the given struct dfa.
- Final argument is a flag specifying whether to build a searching or an
- exact matcher. */
-extern void dfacomp (char const *, size_t, struct dfa *, bool);
+ The last argument says whether to build a searching or an exact matcher.
+ A null first argument means the struct dfa has already been
+ initialized by dfaparse; the second argument is ignored. */
+extern void dfacomp (char const *, ptrdiff_t, struct dfa *, bool);
/* Search through a buffer looking for a match to the given struct dfa.
Find the first occurrence of a string matching the regexp in the
@@ -89,7 +102,7 @@ extern void dfacomp (char const *, size_t, struct dfa *, bool);
encountered a back-reference. The caller can use this to decide
whether to fall back on a backtracking matcher. */
extern char *dfaexec (struct dfa *d, char const *begin, char *end,
- bool allow_nl, size_t *count, bool *backref);
+ bool allow_nl, ptrdiff_t *count, bool *backref);
/* Return a superset for D. The superset matches everything that D
matches, along with some other strings (though the latter should be
diff --git a/lib/dirname-lgpl.c b/lib/dirname-lgpl.c
index a40f6a9..27d4374 100644
--- a/lib/dirname-lgpl.c
+++ b/lib/dirname-lgpl.c
@@ -1,6 +1,6 @@
/* dirname.c -- return all but the last element in a file name
- Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2018 Free Software
+ Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2020 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/dirname.h b/lib/dirname.h
index 8b51111..8c12d93 100644
--- a/lib/dirname.h
+++ b/lib/dirname.h
@@ -1,6 +1,6 @@
/* Take file names apart into directory and base names.
- Copyright (C) 1998, 2001, 2003-2006, 2009-2018 Free Software Foundation,
+ Copyright (C) 1998, 2001, 2003-2006, 2009-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/dosname.h b/lib/dosname.h
index fef3b6d..5782960 100644
--- a/lib/dosname.h
+++ b/lib/dosname.h
@@ -1,6 +1,6 @@
/* File names on MS-DOS/Windows systems.
- Copyright (C) 2000-2001, 2004-2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2000-2001, 2004-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
diff --git a/lib/errno.in.h b/lib/errno.in.h
index b95c4e9..c27e0c7 100644
--- a/lib/errno.in.h
+++ b/lib/errno.in.h
@@ -1,6 +1,6 @@
/* A POSIX-like <errno.h>.
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/error.c b/lib/error.c
index adc8733..3657b51 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -1,5 +1,5 @@
/* Error handler for noninteractive utilities
- Copyright (C) 1990-1998, 2000-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-1998, 2000-2007, 2009-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
@@ -119,7 +119,7 @@ int strerror_r (int errnum, char *buf, size_t buflen);
# endif
# endif
-#define program_name getprogname ()
+# define program_name getprogname ()
# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r
diff --git a/lib/error.h b/lib/error.h
index 36401e1..bad47a1 100644
--- a/lib/error.h
+++ b/lib/error.h
@@ -1,5 +1,5 @@
/* Declaration for error-reporting function
- Copyright (C) 1995-1997, 2003, 2006, 2008-2018 Free Software Foundation,
+ Copyright (C) 1995-1997, 2003, 2006, 2008-2020 Free Software Foundation,
Inc.
This file is part of the GNU C Library.
diff --git a/lib/exitfail.c b/lib/exitfail.c
index 19c5cba..189fa16 100644
--- a/lib/exitfail.c
+++ b/lib/exitfail.c
@@ -1,6 +1,6 @@
/* Failure exit status
- Copyright (C) 2002-2003, 2005-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-2007, 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
diff --git a/lib/exitfail.h b/lib/exitfail.h
index a42057b..a69a03b 100644
--- a/lib/exitfail.h
+++ b/lib/exitfail.h
@@ -1,6 +1,6 @@
/* Failure exit status
- Copyright (C) 2002, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002, 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
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index a1e7d35..b2e1e51 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -1,6 +1,6 @@
/* Like <fcntl.h>, but with non-working flags defined to 0.
- Copyright (C) 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 2006-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
@@ -39,6 +39,12 @@
#endif
#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
+/* Native Windows platforms declare open(), creat() in <io.h>. */
+#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
+ && (defined _WIN32 && ! defined __CYGWIN__)
+# include <io.h>
+#endif
+
#else
/* Normal invocation convention. */
@@ -59,6 +65,12 @@
/* The include_next requires a split double-inclusion guard. */
#@INCLUDE_NEXT@ @NEXT_FCNTL_H@
+/* Native Windows platforms declare open(), creat() in <io.h>. */
+#if (@GNULIB_CREAT@ || @GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
+ && (defined _WIN32 && ! defined __CYGWIN__)
+# include <io.h>
+#endif
+
#ifndef _@GUARD_PREFIX@_FCNTL_H
#define _@GUARD_PREFIX@_FCNTL_H
@@ -66,12 +78,6 @@
# include <unistd.h>
#endif
-/* Native Windows platforms declare open(), creat() in <io.h>. */
-#if (@GNULIB_OPEN@ || defined GNULIB_POSIXCHECK) \
- && (defined _WIN32 && ! defined __CYGWIN__)
-# include <io.h>
-#endif
-
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
@@ -82,6 +88,26 @@
/* Declare overridden functions. */
+#if @GNULIB_CREAT@
+# if @REPLACE_CREAT@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef creat
+# define creat rpl_creat
+# endif
+_GL_FUNCDECL_RPL (creat, int, (const char *filename, mode_t mode)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (creat, int, (const char *filename, mode_t mode));
+# else
+_GL_CXXALIAS_SYS (creat, int, (const char *filename, mode_t mode));
+# endif
+_GL_CXXALIASWARN (creat);
+#elif defined GNULIB_POSIXCHECK
+# undef creat
+/* Assume creat is always declared. */
+_GL_WARN_ON_USE (creat, "creat is not always POSIX compliant - "
+ "use gnulib module creat for portability");
+#endif
+
#if @GNULIB_FCNTL@
# if @REPLACE_FCNTL@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
diff --git a/lib/filename.h b/lib/filename.h
index a7ad7e7..d4c7020 100644
--- a/lib/filename.h
+++ b/lib/filename.h
@@ -1,5 +1,5 @@
/* Basic filename support macros.
- Copyright (C) 2001-2004, 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2007-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
diff --git a/lib/flexmember.h b/lib/flexmember.h
new file mode 100644
index 0000000..0dc77c3
--- /dev/null
+++ b/lib/flexmember.h
@@ -0,0 +1,60 @@
+/* Sizes of structs with flexible array members.
+
+ Copyright 2016-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/>.
+
+ Written by Paul Eggert. */
+
+#include <stddef.h>
+
+/* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below.
+ On older platforms without _Alignof, use a pessimistic bound that is
+ safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1.
+ On newer platforms, use _Alignof to get a tighter bound. */
+
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
+# define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1))
+#else
+# define FLEXALIGNOF(type) _Alignof (type)
+#endif
+
+/* Yield a properly aligned upper bound on the size of a struct of
+ type TYPE with a flexible array member named MEMBER that is
+ followed by N bytes of other data. The result is suitable as an
+ argument to malloc. For example:
+
+ struct s { int n; char d[FLEXIBLE_ARRAY_MEMBER]; };
+ struct s *p = malloc (FLEXSIZEOF (struct s, d, n * sizeof (char)));
+
+ FLEXSIZEOF (TYPE, MEMBER, N) is not simply (sizeof (TYPE) + N),
+ since FLEXIBLE_ARRAY_MEMBER may be 1 on pre-C11 platforms. Nor is
+ it simply (offsetof (TYPE, MEMBER) + N), as that might yield a size
+ that causes malloc to yield a pointer that is not properly aligned
+ for TYPE; for example, if sizeof (int) == alignof (int) == 4,
+ malloc (offsetof (struct s, d) + 3 * sizeof (char)) is equivalent
+ to malloc (7) and might yield a pointer that is not a multiple of 4
+ (which means the pointer is not properly aligned for struct s),
+ whereas malloc (FLEXSIZEOF (struct s, d, 3 * sizeof (char))) is
+ equivalent to malloc (8) and must yield a pointer that is a
+ multiple of 4.
+
+ Yield a value less than N if and only if arithmetic overflow occurs. */
+
+#define FLEXSIZEOF(type, member, n) \
+ ((offsetof (type, member) + FLEXALIGNOF (type) - 1 + (n)) \
+ & ~ (FLEXALIGNOF (type) - 1))
diff --git a/lib/fpending.c b/lib/fpending.c
index de370d4..802ebcb 100644
--- a/lib/fpending.c
+++ b/lib/fpending.c
@@ -1,5 +1,5 @@
/* fpending.c -- return the number of pending output bytes on a stream
- Copyright (C) 2000, 2004, 2006-2007, 2009-2018 Free Software Foundation,
+ Copyright (C) 2000, 2004, 2006-2007, 2009-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/fpending.h b/lib/fpending.h
index 2ff26bc..a8b8859 100644
--- a/lib/fpending.h
+++ b/lib/fpending.h
@@ -1,6 +1,6 @@
/* Declare __fpending.
- Copyright (C) 2000, 2003, 2005-2006, 2009-2018 Free Software Foundation,
+ Copyright (C) 2000, 2003, 2005-2006, 2009-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/fstat.c b/lib/fstat.c
index 41ee761..235014a 100644
--- a/lib/fstat.c
+++ b/lib/fstat.c
@@ -1,5 +1,5 @@
/* fstat() replacement.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-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
@@ -40,10 +40,14 @@ orig_fstat (int fd, struct stat *buf)
#endif
/* Specification. */
+#ifdef __osf__
/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
eliminates this include because of the preliminary #include <sys/stat.h>
above. */
-#include "sys/stat.h"
+# include "sys/stat.h"
+#else
+# include <sys/stat.h>
+#endif
#include "stat-time.h"
diff --git a/lib/fwriting.c b/lib/fwriting.c
index 4ffa12d..e0d535d 100644
--- a/lib/fwriting.c
+++ b/lib/fwriting.c
@@ -1,5 +1,5 @@
/* Retrieve information about a FILE stream.
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
diff --git a/lib/fwriting.h b/lib/fwriting.h
index 42f7e94..111e3dc 100644
--- a/lib/fwriting.h
+++ b/lib/fwriting.h
@@ -1,5 +1,5 @@
/* Retrieve information about a FILE stream.
- Copyright (C) 2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007, 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
diff --git a/lib/get-permissions.c b/lib/get-permissions.c
index 3b98451..e1bcd9f 100644
--- a/lib/get-permissions.c
+++ b/lib/get-permissions.c
@@ -1,6 +1,6 @@
/* Get permissions of a file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
@@ -108,7 +108,7 @@ get_permissions (const char *name, int desc, mode_t mode,
When fetching the source ACL, we simply fetch both ACL types.
When setting the destination ACL, we try either ACL types, assuming
that the kernel will translate the ACL from one form to the other.
- (See in <http://docs.sun.com/app/docs/doc/819-2241/6n4huc7ia?l=en&a=view>
+ (See in <https://docs.oracle.com/cd/E86824_01/html/E54765/acl-2.html>
the description of ENOTSUP.) */
for (;;)
{
diff --git a/lib/getdelim.c b/lib/getdelim.c
index cc1e9fe..fb39b46 100644
--- a/lib/getdelim.c
+++ b/lib/getdelim.c
@@ -1,5 +1,5 @@
/* getdelim.c --- Implementation of replacement getdelim function.
- Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2018 Free Software
+ Copyright (C) 1994, 1996-1998, 2001, 2003, 2005-2020 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or
diff --git a/lib/getfilecon.c b/lib/getfilecon.c
index 3bf254e..a35a001 100644
--- a/lib/getfilecon.c
+++ b/lib/getfilecon.c
@@ -1,5 +1,5 @@
/* wrap getfilecon, lgetfilecon, and fgetfilecon
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
diff --git a/lib/getopt-cdefs.in.h b/lib/getopt-cdefs.in.h
index 12b5a87..c510ab1 100644
--- a/lib/getopt-cdefs.in.h
+++ b/lib/getopt-cdefs.in.h
@@ -1,5 +1,5 @@
/* getopt-on-non-glibc compatibility macros.
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
diff --git a/lib/getopt-core.h b/lib/getopt-core.h
index e51b6c7..d4d942e 100644
--- a/lib/getopt-core.h
+++ b/lib/getopt-core.h
@@ -1,5 +1,5 @@
/* Declarations for getopt (basic, portable features only).
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt-ext.h b/lib/getopt-ext.h
index cb41206..05f7083 100644
--- a/lib/getopt-ext.h
+++ b/lib/getopt-ext.h
@@ -1,5 +1,5 @@
/* Declarations for getopt (GNU extensions).
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt-pfx-core.h b/lib/getopt-pfx-core.h
index c62f9e2..da0a6d0 100644
--- a/lib/getopt-pfx-core.h
+++ b/lib/getopt-pfx-core.h
@@ -1,5 +1,5 @@
/* getopt (basic, portable features) gnulib wrapper header.
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
diff --git a/lib/getopt-pfx-ext.h b/lib/getopt-pfx-ext.h
index 753f129..647fae6 100644
--- a/lib/getopt-pfx-ext.h
+++ b/lib/getopt-pfx-ext.h
@@ -1,5 +1,5 @@
/* getopt (GNU extensions) gnulib wrapper header.
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library.
diff --git a/lib/getopt.c b/lib/getopt.c
index 11e36ee..a6389d8 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -1,5 +1,5 @@
/* Getopt for GNU.
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt.in.h b/lib/getopt.in.h
index 5fb58dd..36e04bb 100644
--- a/lib/getopt.in.h
+++ b/lib/getopt.in.h
@@ -1,5 +1,5 @@
/* Declarations for getopt.
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of gnulib.
Unlike most of the getopt implementation, it is NOT shared
with the GNU C Library, which supplies a different version of
diff --git a/lib/getopt1.c b/lib/getopt1.c
index 9c7fff4..0902efe 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -1,5 +1,5 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
index b0e9a6d..afcd8a6 100644
--- a/lib/getopt_int.h
+++ b/lib/getopt_int.h
@@ -1,5 +1,5 @@
/* Internal declarations for getopt.
- Copyright (C) 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library and is also part of gnulib.
Patches to this file should be submitted to both projects.
diff --git a/lib/getprogname.c b/lib/getprogname.c
index 58da144..9f69f5a 100644
--- a/lib/getprogname.c
+++ b/lib/getprogname.c
@@ -1,5 +1,5 @@
/* Program name management.
- Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
@@ -70,10 +70,10 @@ getprogname (void)
p = "?";
return last_component (p);
# elif HAVE_DECL___ARGV /* mingw, MSVC */
- /* https://msdn.microsoft.com/en-us/library/dn727674.aspx */
+ /* https://docs.microsoft.com/en-us/cpp/c-runtime-library/argc-argv-wargv */
const char *p = __argv && __argv[0] ? __argv[0] : "?";
return last_component (p);
-# elif HAVE_VAR___PROGNAME /* OpenBSD, QNX */
+# elif HAVE_VAR___PROGNAME /* OpenBSD, Android, QNX */
/* https://man.openbsd.org/style.9 */
/* http://www.qnx.de/developers/docs/6.5.0/index.jsp?topic=%2Fcom.qnx.doc.neutrino_lib_ref%2Fp%2F__progname.html */
/* Be careful to declare this only when we absolutely need it
@@ -82,7 +82,11 @@ getprogname (void)
malfunction (have zero length) with Fedora 25's glibc. */
extern char *__progname;
const char *p = __progname;
+# if defined __ANDROID__
+ return last_component (p);
+# else
return p && p[0] ? p : "?";
+# endif
# elif _AIX /* AIX */
/* Idea by Bastien ROUCARIÈS,
https://lists.gnu.org/r/bug-gnulib/2010-12/msg00095.html
@@ -229,12 +233,13 @@ getprogname (void)
{
char *name = buf.pr_fname;
size_t namesize = sizeof buf.pr_fname;
+ /* It may not be NUL-terminated. */
char *namenul = memchr (name, '\0', namesize);
size_t namelen = namenul ? namenul - name : namesize;
char *namecopy = malloc (namelen + 1);
if (namecopy)
{
- namecopy[namelen] = 0;
+ namecopy[namelen] = '\0';
return memcpy (namecopy, name, namelen);
}
}
diff --git a/lib/getprogname.h b/lib/getprogname.h
index ee6688f..676912b 100644
--- a/lib/getprogname.h
+++ b/lib/getprogname.h
@@ -1,5 +1,5 @@
/* Program name management.
- Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ Copyright (C) 2016-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
diff --git a/lib/gettext.h b/lib/gettext.h
index 8eef008..0bd1e13 100644
--- a/lib/gettext.h
+++ b/lib/gettext.h
@@ -1,5 +1,5 @@
/* Convenience header for conditional use of GNU <libintl.h>.
- Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2018 Free Software
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2020 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -184,9 +184,16 @@ npgettext_aux (const char *domain,
#include <string.h>
-#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
- /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
- || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ )
+/* GNULIB_NO_VLA can be defined to disable use of VLAs even if supported.
+ This relates to the -Wvla and -Wvla-larger-than warnings, enabled in
+ the default GCC many warnings set. This allows programs to disable use
+ of VLAs, which may be unintended, or may be awkward to support portably,
+ or may have security implications due to non-deterministic stack usage. */
+
+#if (!defined GNULIB_NO_VLA \
+ && (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
+ /* || (__STDC_VERSION__ == 199901L && !defined __HP_cc)
+ || (__STDC_VERSION__ >= 201112L && !defined __STDC_NO_VLA__) */ ))
# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
#else
# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
index 1bd50fa..b63f8f2 100644
--- a/lib/gettimeofday.c
+++ b/lib/gettimeofday.c
@@ -1,6 +1,6 @@
/* Provide gettimeofday for systems that don't have it or for which it's broken.
- Copyright (C) 2001-2003, 2005-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2007, 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
@@ -72,10 +72,10 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz)
/* On native Windows, there are two ways to get the current time:
GetSystemTimeAsFileTime
- <https://msdn.microsoft.com/en-us/library/ms724397.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime>
or
GetSystemTimePreciseAsFileTime
- <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.
+ <https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime>.
GetSystemTimeAsFileTime produces values that jump by increments of
15.627 milliseconds (!) on average.
Whereas GetSystemTimePreciseAsFileTime values usually jump by 1 or 2
@@ -92,7 +92,7 @@ gettimeofday (struct timeval *restrict tv, void *restrict tz)
GetSystemTimeAsFileTime (&current_time);
/* Convert from FILETIME to 'struct timeval'. */
- /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
+ /* FILETIME: <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
ULONGLONG since_1601 =
((ULONGLONG) current_time.dwHighDateTime << 32)
| (ULONGLONG) current_time.dwLowDateTime;
diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c
index f166d7c..a84318b 100644
--- a/lib/glthread/lock.c
+++ b/lib/glthread/lock.c
@@ -1,5 +1,5 @@
/* Locking in multithreaded situations.
- Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2005-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
@@ -15,8 +15,7 @@
along with this program; if not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
- gthr-win32.h. */
+ Based on GCC's gthr-posix.h, gthr-posix95.h. */
#include <config.h>
@@ -24,6 +23,229 @@
/* ========================================================================= */
+#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+int
+glthread_lock_init (gl_lock_t *lock)
+{
+ if (mtx_init (&lock->mutex, mtx_plain) != thrd_success)
+ return ENOMEM;
+ lock->init_needed = 0;
+ return 0;
+}
+
+int
+glthread_lock_lock (gl_lock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_lock (&lock->mutex) != thrd_success)
+ return EAGAIN;
+ return 0;
+}
+
+int
+glthread_lock_unlock (gl_lock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_unlock (&lock->mutex) != thrd_success)
+ return EINVAL;
+ return 0;
+}
+
+int
+glthread_lock_destroy (gl_lock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ mtx_destroy (&lock->mutex);
+ return 0;
+}
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+int
+glthread_rwlock_init (gl_rwlock_t *lock)
+{
+ if (mtx_init (&lock->lock, mtx_plain) != thrd_success
+ || cnd_init (&lock->waiting_readers) != thrd_success
+ || cnd_init (&lock->waiting_writers) != thrd_success)
+ return ENOMEM;
+ lock->waiting_writers_count = 0;
+ lock->runcount = 0;
+ lock->init_needed = 0;
+ return 0;
+}
+
+int
+glthread_rwlock_rdlock (gl_rwlock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_lock (&lock->lock) != thrd_success)
+ return EAGAIN;
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow, and whether no writer is waiting. The latter
+ condition is because POSIX recommends that "write locks shall take
+ precedence over read locks", to avoid "writer starvation". */
+ while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ if (cnd_wait (&lock->waiting_readers, &lock->lock) != thrd_success)
+ {
+ mtx_unlock (&lock->lock);
+ return EINVAL;
+ }
+ }
+ lock->runcount++;
+ if (mtx_unlock (&lock->lock) != thrd_success)
+ return EINVAL;
+ return 0;
+}
+
+int
+glthread_rwlock_wrlock (gl_rwlock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_lock (&lock->lock) != thrd_success)
+ return EAGAIN;
+ /* Test whether no readers or writers are currently running. */
+ while (!(lock->runcount == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_writers. */
+ lock->waiting_writers_count++;
+ if (cnd_wait (&lock->waiting_writers, &lock->lock) != thrd_success)
+ {
+ lock->waiting_writers_count--;
+ mtx_unlock (&lock->lock);
+ return EINVAL;
+ }
+ lock->waiting_writers_count--;
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ if (mtx_unlock (&lock->lock) != thrd_success)
+ return EINVAL;
+ return 0;
+}
+
+int
+glthread_rwlock_unlock (gl_rwlock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_lock (&lock->lock) != thrd_success)
+ return EAGAIN;
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ {
+ mtx_unlock (&lock->lock);
+ return EINVAL;
+ }
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ {
+ mtx_unlock (&lock->lock);
+ return EINVAL;
+ }
+ lock->runcount--;
+ }
+ if (lock->runcount == 0)
+ {
+ /* POSIX recommends that "write locks shall take precedence over read
+ locks", to avoid "writer starvation". */
+ if (lock->waiting_writers_count > 0)
+ {
+ /* Wake up one of the waiting writers. */
+ if (cnd_signal (&lock->waiting_writers) != thrd_success)
+ {
+ mtx_unlock (&lock->lock);
+ return EINVAL;
+ }
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ if (cnd_broadcast (&lock->waiting_readers) != thrd_success)
+ {
+ mtx_unlock (&lock->lock);
+ return EINVAL;
+ }
+ }
+ }
+ if (mtx_unlock (&lock->lock) != thrd_success)
+ return EINVAL;
+ return 0;
+}
+
+int
+glthread_rwlock_destroy (gl_rwlock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ mtx_destroy (&lock->lock);
+ cnd_destroy (&lock->waiting_readers);
+ cnd_destroy (&lock->waiting_writers);
+ return 0;
+}
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+int
+glthread_recursive_lock_init (gl_recursive_lock_t *lock)
+{
+ if (mtx_init (&lock->mutex, mtx_plain | mtx_recursive) != thrd_success)
+ return ENOMEM;
+ lock->init_needed = 0;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock (gl_recursive_lock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_lock (&lock->mutex) != thrd_success)
+ return EAGAIN;
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock (gl_recursive_lock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ if (mtx_unlock (&lock->mutex) != thrd_success)
+ return EINVAL;
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy (gl_recursive_lock_t *lock)
+{
+ if (lock->init_needed)
+ call_once (&lock->init_once, lock->init_func);
+ mtx_destroy (&lock->mutex);
+ return 0;
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+#endif
+
+/* ========================================================================= */
+
#if USE_POSIX_THREADS
/* -------------------------- gl_lock_t datatype -------------------------- */
@@ -32,7 +254,7 @@
# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
-# ifdef PTHREAD_RWLOCK_INITIALIZER
+# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
# if !HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
/* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
@@ -500,722 +722,8 @@ glthread_once_singlethreaded (pthread_once_t *once_control)
/* ========================================================================= */
-#if USE_PTH_THREADS
-
-/* Use the GNU Pth threads library. */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-# if !HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER
-
-int
-glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
-{
- if (!pth_mutex_init (&lock->lock))
- return errno;
- if (!pth_cond_init (&lock->waiting_readers))
- return errno;
- if (!pth_cond_init (&lock->waiting_writers))
- return errno;
- lock->waiting_writers_count = 0;
- lock->runcount = 0;
- lock->initialized = 1;
- return 0;
-}
-
-int
-glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
-{
- if (!lock->initialized)
- glthread_rwlock_init_multithreaded (lock);
- if (!pth_mutex_acquire (&lock->lock, 0, NULL))
- return errno;
- /* Test whether only readers are currently running, and whether the runcount
- field will not overflow, and whether no writer is waiting. The latter
- condition is because POSIX recommends that "write locks shall take
- precedence over read locks", to avoid "writer starvation". */
- while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_readers. */
- if (!pth_cond_await (&lock->waiting_readers, &lock->lock, NULL))
- {
- int err = errno;
- pth_mutex_release (&lock->lock);
- return err;
- }
- }
- lock->runcount++;
- return (!pth_mutex_release (&lock->lock) ? errno : 0);
-}
-
-int
-glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
-{
- if (!lock->initialized)
- glthread_rwlock_init_multithreaded (lock);
- if (!pth_mutex_acquire (&lock->lock, 0, NULL))
- return errno;
- /* Test whether no readers or writers are currently running. */
- while (!(lock->runcount == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_writers. */
- lock->waiting_writers_count++;
- if (!pth_cond_await (&lock->waiting_writers, &lock->lock, NULL))
- {
- int err = errno;
- lock->waiting_writers_count--;
- pth_mutex_release (&lock->lock);
- return err;
- }
- lock->waiting_writers_count--;
- }
- lock->runcount--; /* runcount becomes -1 */
- return (!pth_mutex_release (&lock->lock) ? errno : 0);
-}
-
-int
-glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
-{
- int err;
-
- if (!lock->initialized)
- return EINVAL;
- if (!pth_mutex_acquire (&lock->lock, 0, NULL))
- return errno;
- if (lock->runcount < 0)
- {
- /* Drop a writer lock. */
- if (!(lock->runcount == -1))
- {
- pth_mutex_release (&lock->lock);
- return EINVAL;
- }
- lock->runcount = 0;
- }
- else
- {
- /* Drop a reader lock. */
- if (!(lock->runcount > 0))
- {
- pth_mutex_release (&lock->lock);
- return EINVAL;
- }
- lock->runcount--;
- }
- if (lock->runcount == 0)
- {
- /* POSIX recommends that "write locks shall take precedence over read
- locks", to avoid "writer starvation". */
- if (lock->waiting_writers_count > 0)
- {
- /* Wake up one of the waiting writers. */
- if (!pth_cond_notify (&lock->waiting_writers, FALSE))
- {
- int err = errno;
- pth_mutex_release (&lock->lock);
- return err;
- }
- }
- else
- {
- /* Wake up all waiting readers. */
- if (!pth_cond_notify (&lock->waiting_readers, TRUE))
- {
- int err = errno;
- pth_mutex_release (&lock->lock);
- return err;
- }
- }
- }
- return (!pth_mutex_release (&lock->lock) ? errno : 0);
-}
-
-int
-glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
-{
- lock->initialized = 0;
- return 0;
-}
-
-# endif
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-static void
-glthread_once_call (void *arg)
-{
- void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;
- void (*initfunction) (void) = *gl_once_temp_addr;
- initfunction ();
-}
-
-int
-glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void))
-{
- void (*temp) (void) = initfunction;
- return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0);
-}
-
-int
-glthread_once_singlethreaded (pth_once_t *once_control)
-{
- /* We know that pth_once_t is an integer type. */
- if (*once_control == PTH_ONCE_INIT)
- {
- /* First time use of once_control. Invert the marker. */
- *once_control = ~ PTH_ONCE_INIT;
- return 1;
- }
- else
- return 0;
-}
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_SOLARIS_THREADS
-
-/* Use the old Solaris threads library. */
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-int
-glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
-{
- int err;
-
- err = mutex_init (&lock->mutex, USYNC_THREAD, NULL);
- if (err != 0)
- return err;
- lock->owner = (thread_t) 0;
- lock->depth = 0;
- return 0;
-}
-
-int
-glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
-{
- thread_t self = thr_self ();
- if (lock->owner != self)
- {
- int err;
-
- err = mutex_lock (&lock->mutex);
- if (err != 0)
- return err;
- lock->owner = self;
- }
- if (++(lock->depth) == 0) /* wraparound? */
- {
- lock->depth--;
- return EAGAIN;
- }
- return 0;
-}
-
-int
-glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
-{
- if (lock->owner != thr_self ())
- return EPERM;
- if (lock->depth == 0)
- return EINVAL;
- if (--(lock->depth) == 0)
- {
- lock->owner = (thread_t) 0;
- return mutex_unlock (&lock->mutex);
- }
- else
- return 0;
-}
-
-int
-glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
-{
- if (lock->owner != (thread_t) 0)
- return EBUSY;
- return mutex_destroy (&lock->mutex);
-}
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-int
-glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void))
-{
- if (!once_control->inited)
- {
- int err;
-
- /* Use the mutex to guarantee that if another thread is already calling
- the initfunction, this thread waits until it's finished. */
- err = mutex_lock (&once_control->mutex);
- if (err != 0)
- return err;
- if (!once_control->inited)
- {
- once_control->inited = 1;
- initfunction ();
- }
- return mutex_unlock (&once_control->mutex);
- }
- else
- return 0;
-}
-
-int
-glthread_once_singlethreaded (gl_once_t *once_control)
-{
- /* We know that gl_once_t contains an integer type. */
- if (!once_control->inited)
- {
- /* First time use of once_control. Invert the marker. */
- once_control->inited = ~ 0;
- return 1;
- }
- else
- return 0;
-}
-
-#endif
-
-/* ========================================================================= */
-
#if USE_WINDOWS_THREADS
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-void
-glthread_lock_init_func (gl_lock_t *lock)
-{
- InitializeCriticalSection (&lock->lock);
- lock->guard.done = 1;
-}
-
-int
-glthread_lock_lock_func (gl_lock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glthread_lock_init (lock);
- else
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- EnterCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glthread_lock_unlock_func (gl_lock_t *lock)
-{
- if (!lock->guard.done)
- return EINVAL;
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glthread_lock_destroy_func (gl_lock_t *lock)
-{
- if (!lock->guard.done)
- return EINVAL;
- DeleteCriticalSection (&lock->lock);
- lock->guard.done = 0;
- return 0;
-}
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-/* In this file, the waitqueues are implemented as circular arrays. */
-#define gl_waitqueue_t gl_carray_waitqueue_t
-
-static void
-gl_waitqueue_init (gl_waitqueue_t *wq)
-{
- wq->array = NULL;
- wq->count = 0;
- wq->alloc = 0;
- wq->offset = 0;
-}
-
-/* Enqueues the current thread, represented by an event, in a wait queue.
- Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */
-static HANDLE
-gl_waitqueue_add (gl_waitqueue_t *wq)
-{
- HANDLE event;
- unsigned int index;
-
- if (wq->count == wq->alloc)
- {
- unsigned int new_alloc = 2 * wq->alloc + 1;
- HANDLE *new_array =
- (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
- if (new_array == NULL)
- /* No more memory. */
- return INVALID_HANDLE_VALUE;
- /* Now is a good opportunity to rotate the array so that its contents
- starts at offset 0. */
- if (wq->offset > 0)
- {
- unsigned int old_count = wq->count;
- unsigned int old_alloc = wq->alloc;
- unsigned int old_offset = wq->offset;
- unsigned int i;
- if (old_offset + old_count > old_alloc)
- {
- unsigned int limit = old_offset + old_count - old_alloc;
- for (i = 0; i < limit; i++)
- new_array[old_alloc + i] = new_array[i];
- }
- for (i = 0; i < old_count; i++)
- new_array[i] = new_array[old_offset + i];
- wq->offset = 0;
- }
- wq->array = new_array;
- wq->alloc = new_alloc;
- }
- /* Whether the created event is a manual-reset one or an auto-reset one,
- does not matter, since we will wait on it only once. */
- event = CreateEvent (NULL, TRUE, FALSE, NULL);
- if (event == INVALID_HANDLE_VALUE)
- /* No way to allocate an event. */
- return INVALID_HANDLE_VALUE;
- index = wq->offset + wq->count;
- if (index >= wq->alloc)
- index -= wq->alloc;
- wq->array[index] = event;
- wq->count++;
- return event;
-}
-
-/* Notifies the first thread from a wait queue and dequeues it. */
-static void
-gl_waitqueue_notify_first (gl_waitqueue_t *wq)
-{
- SetEvent (wq->array[wq->offset + 0]);
- wq->offset++;
- wq->count--;
- if (wq->count == 0 || wq->offset == wq->alloc)
- wq->offset = 0;
-}
-
-/* Notifies all threads from a wait queue and dequeues them all. */
-static void
-gl_waitqueue_notify_all (gl_waitqueue_t *wq)
-{
- unsigned int i;
-
- for (i = 0; i < wq->count; i++)
- {
- unsigned int index = wq->offset + i;
- if (index >= wq->alloc)
- index -= wq->alloc;
- SetEvent (wq->array[index]);
- }
- wq->count = 0;
- wq->offset = 0;
-}
-
-void
-glthread_rwlock_init_func (gl_rwlock_t *lock)
-{
- InitializeCriticalSection (&lock->lock);
- gl_waitqueue_init (&lock->waiting_readers);
- gl_waitqueue_init (&lock->waiting_writers);
- lock->runcount = 0;
- lock->guard.done = 1;
-}
-
-int
-glthread_rwlock_rdlock_func (gl_rwlock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glthread_rwlock_init (lock);
- else
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- EnterCriticalSection (&lock->lock);
- /* Test whether only readers are currently running, and whether the runcount
- field will not overflow, and whether no writer is waiting. The latter
- condition is because POSIX recommends that "write locks shall take
- precedence over read locks", to avoid "writer starvation". */
- if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_readers. */
- HANDLE event = gl_waitqueue_add (&lock->waiting_readers);
- if (event != INVALID_HANDLE_VALUE)
- {
- DWORD result;
- LeaveCriticalSection (&lock->lock);
- /* Wait until another thread signals this event. */
- result = WaitForSingleObject (event, INFINITE);
- if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
- abort ();
- CloseHandle (event);
- /* The thread which signalled the event already did the bookkeeping:
- removed us from the waiting_readers, incremented lock->runcount. */
- if (!(lock->runcount > 0))
- abort ();
- return 0;
- }
- else
- {
- /* Allocation failure. Weird. */
- do
- {
- LeaveCriticalSection (&lock->lock);
- Sleep (1);
- EnterCriticalSection (&lock->lock);
- }
- while (!(lock->runcount + 1 > 0));
- }
- }
- lock->runcount++;
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glthread_rwlock_wrlock_func (gl_rwlock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glthread_rwlock_init (lock);
- else
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- EnterCriticalSection (&lock->lock);
- /* Test whether no readers or writers are currently running. */
- if (!(lock->runcount == 0))
- {
- /* This thread has to wait for a while. Enqueue it among the
- waiting_writers. */
- HANDLE event = gl_waitqueue_add (&lock->waiting_writers);
- if (event != INVALID_HANDLE_VALUE)
- {
- DWORD result;
- LeaveCriticalSection (&lock->lock);
- /* Wait until another thread signals this event. */
- result = WaitForSingleObject (event, INFINITE);
- if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
- abort ();
- CloseHandle (event);
- /* The thread which signalled the event already did the bookkeeping:
- removed us from the waiting_writers, set lock->runcount = -1. */
- if (!(lock->runcount == -1))
- abort ();
- return 0;
- }
- else
- {
- /* Allocation failure. Weird. */
- do
- {
- LeaveCriticalSection (&lock->lock);
- Sleep (1);
- EnterCriticalSection (&lock->lock);
- }
- while (!(lock->runcount == 0));
- }
- }
- lock->runcount--; /* runcount becomes -1 */
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glthread_rwlock_unlock_func (gl_rwlock_t *lock)
-{
- if (!lock->guard.done)
- return EINVAL;
- EnterCriticalSection (&lock->lock);
- if (lock->runcount < 0)
- {
- /* Drop a writer lock. */
- if (!(lock->runcount == -1))
- abort ();
- lock->runcount = 0;
- }
- else
- {
- /* Drop a reader lock. */
- if (!(lock->runcount > 0))
- {
- LeaveCriticalSection (&lock->lock);
- return EPERM;
- }
- lock->runcount--;
- }
- if (lock->runcount == 0)
- {
- /* POSIX recommends that "write locks shall take precedence over read
- locks", to avoid "writer starvation". */
- if (lock->waiting_writers.count > 0)
- {
- /* Wake up one of the waiting writers. */
- lock->runcount--;
- gl_waitqueue_notify_first (&lock->waiting_writers);
- }
- else
- {
- /* Wake up all waiting readers. */
- lock->runcount += lock->waiting_readers.count;
- gl_waitqueue_notify_all (&lock->waiting_readers);
- }
- }
- LeaveCriticalSection (&lock->lock);
- return 0;
-}
-
-int
-glthread_rwlock_destroy_func (gl_rwlock_t *lock)
-{
- if (!lock->guard.done)
- return EINVAL;
- if (lock->runcount != 0)
- return EBUSY;
- DeleteCriticalSection (&lock->lock);
- if (lock->waiting_readers.array != NULL)
- free (lock->waiting_readers.array);
- if (lock->waiting_writers.array != NULL)
- free (lock->waiting_writers.array);
- lock->guard.done = 0;
- return 0;
-}
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-void
-glthread_recursive_lock_init_func (gl_recursive_lock_t *lock)
-{
- lock->owner = 0;
- lock->depth = 0;
- InitializeCriticalSection (&lock->lock);
- lock->guard.done = 1;
-}
-
-int
-glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock)
-{
- if (!lock->guard.done)
- {
- if (InterlockedIncrement (&lock->guard.started) == 0)
- /* This thread is the first one to need this lock. Initialize it. */
- glthread_recursive_lock_init (lock);
- else
- /* Yield the CPU while waiting for another thread to finish
- initializing this lock. */
- while (!lock->guard.done)
- Sleep (0);
- }
- {
- DWORD self = GetCurrentThreadId ();
- if (lock->owner != self)
- {
- EnterCriticalSection (&lock->lock);
- lock->owner = self;
- }
- if (++(lock->depth) == 0) /* wraparound? */
- {
- lock->depth--;
- return EAGAIN;
- }
- }
- return 0;
-}
-
-int
-glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock)
-{
- if (lock->owner != GetCurrentThreadId ())
- return EPERM;
- if (lock->depth == 0)
- return EINVAL;
- if (--(lock->depth) == 0)
- {
- lock->owner = 0;
- LeaveCriticalSection (&lock->lock);
- }
- return 0;
-}
-
-int
-glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock)
-{
- if (lock->owner != 0)
- return EBUSY;
- DeleteCriticalSection (&lock->lock);
- lock->guard.done = 0;
- return 0;
-}
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-void
-glthread_once_func (gl_once_t *once_control, void (*initfunction) (void))
-{
- if (once_control->inited <= 0)
- {
- if (InterlockedIncrement (&once_control->started) == 0)
- {
- /* This thread is the first one to come to this once_control. */
- InitializeCriticalSection (&once_control->lock);
- EnterCriticalSection (&once_control->lock);
- once_control->inited = 0;
- initfunction ();
- once_control->inited = 1;
- LeaveCriticalSection (&once_control->lock);
- }
- else
- {
- /* Undo last operation. */
- InterlockedDecrement (&once_control->started);
- /* Some other thread has already started the initialization.
- Yield the CPU while waiting for the other thread to finish
- initializing and taking the lock. */
- while (once_control->inited < 0)
- Sleep (0);
- if (once_control->inited <= 0)
- {
- /* Take the lock. This blocks until the other thread has
- finished calling the initfunction. */
- EnterCriticalSection (&once_control->lock);
- LeaveCriticalSection (&once_control->lock);
- if (!(once_control->inited > 0))
- abort ();
- }
- }
- }
-}
-
#endif
/* ========================================================================= */
diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h
index 30aa730..28a9e3d 100644
--- a/lib/glthread/lock.h
+++ b/lib/glthread/lock.h
@@ -1,5 +1,5 @@
/* Locking in multithreaded situations.
- Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2005-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
@@ -15,8 +15,7 @@
along with this program; if not, see <https://www.gnu.org/licenses/>. */
/* Written by Bruno Haible <bruno@clisp.org>, 2005.
- Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
- gthr-win32.h. */
+ Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h. */
/* This file contains locking primitives for use with a given thread library.
It does not contain primitives for creating threads or for other
@@ -81,6 +80,125 @@
#include <errno.h>
#include <stdlib.h>
+#if !defined c11_threads_in_use
+# if HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
+# include <threads.h>
+# pragma weak thrd_exit
+# define c11_threads_in_use() (thrd_exit != NULL)
+# else
+# define c11_threads_in_use() 0
+# endif
+#endif
+
+/* ========================================================================= */
+
+#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
+
+/* Use the ISO C threads library. */
+
+# include <threads.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef struct
+ {
+ int volatile init_needed;
+ once_flag init_once;
+ void (*init_func) (void);
+ mtx_t mutex;
+ }
+ gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_lock_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ static void _atomic_init_##NAME (void); \
+ STORAGECLASS gl_lock_t NAME = \
+ { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
+ static void _atomic_init_##NAME (void) \
+ { \
+ if (glthread_lock_init (&(NAME))) \
+ abort (); \
+ }
+extern int glthread_lock_init (gl_lock_t *lock);
+extern int glthread_lock_lock (gl_lock_t *lock);
+extern int glthread_lock_unlock (gl_lock_t *lock);
+extern int glthread_lock_destroy (gl_lock_t *lock);
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef struct
+ {
+ int volatile init_needed;
+ once_flag init_once;
+ void (*init_func) (void);
+ mtx_t lock; /* protects the remaining fields */
+ cnd_t waiting_readers; /* waiting readers */
+ cnd_t waiting_writers; /* waiting writers */
+ unsigned int waiting_writers_count; /* number of waiting writers */
+ int runcount; /* number of readers running, or -1 when a writer runs */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ static void _atomic_init_##NAME (void); \
+ STORAGECLASS gl_rwlock_t NAME = \
+ { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
+ static void _atomic_init_##NAME (void) \
+ { \
+ if (glthread_rwlock_init (&(NAME))) \
+ abort (); \
+ }
+extern int glthread_rwlock_init (gl_rwlock_t *lock);
+extern int glthread_rwlock_rdlock (gl_rwlock_t *lock);
+extern int glthread_rwlock_wrlock (gl_rwlock_t *lock);
+extern int glthread_rwlock_unlock (gl_rwlock_t *lock);
+extern int glthread_rwlock_destroy (gl_rwlock_t *lock);
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+typedef struct
+ {
+ int volatile init_needed;
+ once_flag init_once;
+ void (*init_func) (void);
+ mtx_t mutex;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ static void _atomic_init_##NAME (void); \
+ STORAGECLASS gl_recursive_lock_t NAME = \
+ { 1, ONCE_FLAG_INIT, _atomic_init_##NAME }; \
+ static void _atomic_init_##NAME (void) \
+ { \
+ if (glthread_recursive_lock_init (&(NAME))) \
+ abort (); \
+ }
+extern int glthread_recursive_lock_init (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy (gl_recursive_lock_t *lock);
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef once_flag gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS once_flag NAME = ONCE_FLAG_INIT;
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (call_once (ONCE_CONTROL, INITFUNCTION), 0)
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
/* ========================================================================= */
#if USE_POSIX_THREADS
@@ -156,7 +274,8 @@ extern int glthread_in_use (void);
pthread_rwlockattr_init
*/
# pragma weak pthread_mutexattr_gettype
-# define pthread_in_use() (pthread_mutexattr_gettype != NULL)
+# define pthread_in_use() \
+ (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
# endif
# else
@@ -189,7 +308,7 @@ typedef pthread_mutex_t gl_lock_t;
# if HAVE_PTHREAD_RWLOCK && (HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER || (defined PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP && (__GNU_LIBRARY__ > 1)))
-# ifdef PTHREAD_RWLOCK_INITIALIZER
+# if defined PTHREAD_RWLOCK_INITIALIZER || defined PTHREAD_RWLOCK_INITIALIZER_NP
typedef pthread_rwlock_t gl_rwlock_t;
# define gl_rwlock_define(STORAGECLASS, NAME) \
@@ -197,8 +316,13 @@ typedef pthread_rwlock_t gl_rwlock_t;
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
# if HAVE_PTHREAD_RWLOCK_RDLOCK_PREFER_WRITER
-# define gl_rwlock_initializer \
- PTHREAD_RWLOCK_INITIALIZER
+# if defined PTHREAD_RWLOCK_INITIALIZER
+# define gl_rwlock_initializer \
+ PTHREAD_RWLOCK_INITIALIZER
+# else
+# define gl_rwlock_initializer \
+ PTHREAD_RWLOCK_INITIALIZER_NP
+# endif
# define glthread_rwlock_init(LOCK) \
(pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
# else /* glibc with bug https://sourceware.org/bugzilla/show_bug.cgi?id=13701 */
@@ -395,287 +519,16 @@ extern int glthread_once_singlethreaded (pthread_once_t *once_control);
/* ========================================================================= */
-#if USE_PTH_THREADS
-
-/* Use the GNU Pth threads library. */
-
-# include <pth.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# if USE_PTH_THREADS_WEAK
-
-/* Use weak references to the GNU Pth threads library. */
-
-# pragma weak pth_mutex_init
-# pragma weak pth_mutex_acquire
-# pragma weak pth_mutex_release
-# pragma weak pth_rwlock_init
-# pragma weak pth_rwlock_acquire
-# pragma weak pth_rwlock_release
-# pragma weak pth_once
-
-# pragma weak pth_cancel
-# define pth_in_use() (pth_cancel != NULL)
-
-# else
-
-# define pth_in_use() 1
-
-# endif
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef pth_mutex_t gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
-# define gl_lock_initializer \
- PTH_MUTEX_INIT
-# define glthread_lock_init(LOCK) \
- (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
-# define glthread_lock_lock(LOCK) \
- (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
-# define glthread_lock_unlock(LOCK) \
- (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
-# define glthread_lock_destroy(LOCK) \
- ((void)(LOCK), 0)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-/* Pth pth_rwlock_acquire always prefers readers. No autoconf test so far. */
-# if HAVE_PTH_RWLOCK_ACQUIRE_PREFER_WRITER
-
-typedef pth_rwlock_t gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
- PTH_RWLOCK_INIT
-# define glthread_rwlock_init(LOCK) \
- (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
-# define glthread_rwlock_rdlock(LOCK) \
- (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
-# define glthread_rwlock_wrlock(LOCK) \
- (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
-# define glthread_rwlock_unlock(LOCK) \
- (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
-# define glthread_rwlock_destroy(LOCK) \
- ((void)(LOCK), 0)
-
-# else
-
-typedef struct
- {
- int initialized;
- pth_mutex_t lock; /* protects the remaining fields */
- pth_cond_t waiting_readers; /* waiting readers */
- pth_cond_t waiting_writers; /* waiting writers */
- unsigned int waiting_writers_count; /* number of waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
- { 0 }
-# define glthread_rwlock_init(LOCK) \
- (pth_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
-# define glthread_rwlock_rdlock(LOCK) \
- (pth_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_wrlock(LOCK) \
- (pth_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_unlock(LOCK) \
- (pth_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
-# define glthread_rwlock_destroy(LOCK) \
- (pth_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
-
-# endif
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-/* In Pth, mutexes are recursive by default. */
-typedef pth_mutex_t gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
-# define gl_recursive_lock_initializer \
- PTH_MUTEX_INIT
-# define glthread_recursive_lock_init(LOCK) \
- (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
-# define glthread_recursive_lock_lock(LOCK) \
- (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
-# define glthread_recursive_lock_unlock(LOCK) \
- (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
-# define glthread_recursive_lock_destroy(LOCK) \
- ((void)(LOCK), 0)
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef pth_once_t gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (pth_in_use () \
- ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
- : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
-extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
-extern int glthread_once_singlethreaded (pth_once_t *once_control);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
-#if USE_SOLARIS_THREADS
-
-/* Use the old Solaris threads library. */
-
-# include <thread.h>
-# include <synch.h>
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# if USE_SOLARIS_THREADS_WEAK
-
-/* Use weak references to the old Solaris threads library. */
-
-# pragma weak mutex_init
-# pragma weak mutex_lock
-# pragma weak mutex_unlock
-# pragma weak mutex_destroy
-# pragma weak rwlock_init
-# pragma weak rw_rdlock
-# pragma weak rw_wrlock
-# pragma weak rw_unlock
-# pragma weak rwlock_destroy
-# pragma weak thr_self
-
-# pragma weak thr_suspend
-# define thread_in_use() (thr_suspend != NULL)
-
-# else
-
-# define thread_in_use() 1
-
-# endif
-
-/* -------------------------- gl_lock_t datatype -------------------------- */
-
-typedef mutex_t gl_lock_t;
-# define gl_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS mutex_t NAME;
-# define gl_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS mutex_t NAME = gl_lock_initializer;
-# define gl_lock_initializer \
- DEFAULTMUTEX
-# define glthread_lock_init(LOCK) \
- (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
-# define glthread_lock_lock(LOCK) \
- (thread_in_use () ? mutex_lock (LOCK) : 0)
-# define glthread_lock_unlock(LOCK) \
- (thread_in_use () ? mutex_unlock (LOCK) : 0)
-# define glthread_lock_destroy(LOCK) \
- (thread_in_use () ? mutex_destroy (LOCK) : 0)
-
-/* ------------------------- gl_rwlock_t datatype ------------------------- */
-
-typedef rwlock_t gl_rwlock_t;
-# define gl_rwlock_define(STORAGECLASS, NAME) \
- STORAGECLASS rwlock_t NAME;
-# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
-# define gl_rwlock_initializer \
- DEFAULTRWLOCK
-# define glthread_rwlock_init(LOCK) \
- (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
-# define glthread_rwlock_rdlock(LOCK) \
- (thread_in_use () ? rw_rdlock (LOCK) : 0)
-# define glthread_rwlock_wrlock(LOCK) \
- (thread_in_use () ? rw_wrlock (LOCK) : 0)
-# define glthread_rwlock_unlock(LOCK) \
- (thread_in_use () ? rw_unlock (LOCK) : 0)
-# define glthread_rwlock_destroy(LOCK) \
- (thread_in_use () ? rwlock_destroy (LOCK) : 0)
-
-/* --------------------- gl_recursive_lock_t datatype --------------------- */
-
-/* Old Solaris threads did not have recursive locks.
- We have to implement them ourselves. */
-
-typedef struct
- {
- mutex_t mutex;
- thread_t owner;
- unsigned long depth;
- }
- gl_recursive_lock_t;
-# define gl_recursive_lock_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME;
-# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
- STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
-# define gl_recursive_lock_initializer \
- { DEFAULTMUTEX, (thread_t) 0, 0 }
-# define glthread_recursive_lock_init(LOCK) \
- (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_lock(LOCK) \
- (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_unlock(LOCK) \
- (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
-# define glthread_recursive_lock_destroy(LOCK) \
- (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
-extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
-
-/* -------------------------- gl_once_t datatype -------------------------- */
-
-typedef struct
- {
- volatile int inited;
- mutex_t mutex;
- }
- gl_once_t;
-# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (thread_in_use () \
- ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
- : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
-extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
-extern int glthread_once_singlethreaded (gl_once_t *once_control);
-
-# ifdef __cplusplus
-}
-# endif
-
-#endif
-
-/* ========================================================================= */
-
#if USE_WINDOWS_THREADS
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
+# include "windows-mutex.h"
+# include "windows-rwlock.h"
+# include "windows-recmutex.h"
+# include "windows-once.h"
+
# ifdef __cplusplus
extern "C" {
# endif
@@ -691,127 +544,69 @@ extern "C" {
/* There is no way to statically initialize a CRITICAL_SECTION. It needs
to be done lazily, once only. For this we need spinlocks. */
-typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
-
/* -------------------------- gl_lock_t datatype -------------------------- */
-typedef struct
- {
- gl_spinlock_t guard; /* protects the initialization */
- CRITICAL_SECTION lock;
- }
- gl_lock_t;
+typedef glwthread_mutex_t gl_lock_t;
# define gl_lock_define(STORAGECLASS, NAME) \
STORAGECLASS gl_lock_t NAME;
# define gl_lock_define_initialized(STORAGECLASS, NAME) \
STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
# define gl_lock_initializer \
- { { 0, -1 } }
+ GLWTHREAD_MUTEX_INIT
# define glthread_lock_init(LOCK) \
- (glthread_lock_init_func (LOCK), 0)
+ (glwthread_mutex_init (LOCK), 0)
# define glthread_lock_lock(LOCK) \
- glthread_lock_lock_func (LOCK)
+ glwthread_mutex_lock (LOCK)
# define glthread_lock_unlock(LOCK) \
- glthread_lock_unlock_func (LOCK)
+ glwthread_mutex_unlock (LOCK)
# define glthread_lock_destroy(LOCK) \
- glthread_lock_destroy_func (LOCK)
-extern void glthread_lock_init_func (gl_lock_t *lock);
-extern int glthread_lock_lock_func (gl_lock_t *lock);
-extern int glthread_lock_unlock_func (gl_lock_t *lock);
-extern int glthread_lock_destroy_func (gl_lock_t *lock);
+ glwthread_mutex_destroy (LOCK)
/* ------------------------- gl_rwlock_t datatype ------------------------- */
-/* It is impossible to implement read-write locks using plain locks, without
- introducing an extra thread dedicated to managing read-write locks.
- Therefore here we need to use the low-level Event type. */
-
-typedef struct
- {
- HANDLE *array; /* array of waiting threads, each represented by an event */
- unsigned int count; /* number of waiting threads */
- unsigned int alloc; /* length of allocated array */
- unsigned int offset; /* index of first waiting thread in array */
- }
- gl_carray_waitqueue_t;
-typedef struct
- {
- gl_spinlock_t guard; /* protects the initialization */
- CRITICAL_SECTION lock; /* protects the remaining fields */
- gl_carray_waitqueue_t waiting_readers; /* waiting readers */
- gl_carray_waitqueue_t waiting_writers; /* waiting writers */
- int runcount; /* number of readers running, or -1 when a writer runs */
- }
- gl_rwlock_t;
+typedef glwthread_rwlock_t gl_rwlock_t;
# define gl_rwlock_define(STORAGECLASS, NAME) \
STORAGECLASS gl_rwlock_t NAME;
# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
# define gl_rwlock_initializer \
- { { 0, -1 } }
+ GLWTHREAD_RWLOCK_INIT
# define glthread_rwlock_init(LOCK) \
- (glthread_rwlock_init_func (LOCK), 0)
+ (glwthread_rwlock_init (LOCK), 0)
# define glthread_rwlock_rdlock(LOCK) \
- glthread_rwlock_rdlock_func (LOCK)
+ glwthread_rwlock_rdlock (LOCK)
# define glthread_rwlock_wrlock(LOCK) \
- glthread_rwlock_wrlock_func (LOCK)
+ glwthread_rwlock_wrlock (LOCK)
# define glthread_rwlock_unlock(LOCK) \
- glthread_rwlock_unlock_func (LOCK)
+ glwthread_rwlock_unlock (LOCK)
# define glthread_rwlock_destroy(LOCK) \
- glthread_rwlock_destroy_func (LOCK)
-extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
-extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
+ glwthread_rwlock_destroy (LOCK)
/* --------------------- gl_recursive_lock_t datatype --------------------- */
-/* The native Windows documentation says that CRITICAL_SECTION already
- implements a recursive lock. But we need not rely on it: It's easy to
- implement a recursive lock without this assumption. */
-
-typedef struct
- {
- gl_spinlock_t guard; /* protects the initialization */
- DWORD owner;
- unsigned long depth;
- CRITICAL_SECTION lock;
- }
- gl_recursive_lock_t;
+typedef glwthread_recmutex_t gl_recursive_lock_t;
# define gl_recursive_lock_define(STORAGECLASS, NAME) \
STORAGECLASS gl_recursive_lock_t NAME;
# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
# define gl_recursive_lock_initializer \
- { { 0, -1 }, 0, 0 }
+ GLWTHREAD_RECMUTEX_INIT
# define glthread_recursive_lock_init(LOCK) \
- (glthread_recursive_lock_init_func (LOCK), 0)
+ (glwthread_recmutex_init (LOCK), 0)
# define glthread_recursive_lock_lock(LOCK) \
- glthread_recursive_lock_lock_func (LOCK)
+ glwthread_recmutex_lock (LOCK)
# define glthread_recursive_lock_unlock(LOCK) \
- glthread_recursive_lock_unlock_func (LOCK)
+ glwthread_recmutex_unlock (LOCK)
# define glthread_recursive_lock_destroy(LOCK) \
- glthread_recursive_lock_destroy_func (LOCK)
-extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
-extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock);
+ glwthread_recmutex_destroy (LOCK)
/* -------------------------- gl_once_t datatype -------------------------- */
-typedef struct
- {
- volatile int inited;
- volatile long started;
- CRITICAL_SECTION lock;
- }
- gl_once_t;
+typedef glwthread_once_t gl_once_t;
# define gl_once_define(STORAGECLASS, NAME) \
- STORAGECLASS gl_once_t NAME = { -1, -1 };
+ STORAGECLASS gl_once_t NAME = GLWTHREAD_ONCE_INIT;
# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
- (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0)
-extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void));
+ (glwthread_once (ONCE_CONTROL, INITFUNCTION), 0)
# ifdef __cplusplus
}
@@ -821,7 +616,7 @@ extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (v
/* ========================================================================= */
-#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS)
+#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
/* Provide dummy implementation if threads are not supported. */
diff --git a/lib/glthread/threadlib.c b/lib/glthread/threadlib.c
index e8b484a..28bf3c6 100644
--- a/lib/glthread/threadlib.c
+++ b/lib/glthread/threadlib.c
@@ -1,5 +1,5 @@
/* Multithreading primitives.
- Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2005-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
@@ -20,7 +20,7 @@
/* ========================================================================= */
-#if USE_POSIX_THREADS
+#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
/* Use the POSIX threads library. */
diff --git a/lib/gnulib.mk b/lib/gnulib.mk
index bedc672..f8fd3ac 100644
--- a/lib/gnulib.mk
+++ b/lib/gnulib.mk
@@ -1,6 +1,6 @@
## DO NOT EDIT! GENERATED AUTOMATICALLY!
## Process this file with automake to produce Makefile.in.
-# Copyright (C) 2002-2018 Free Software Foundation, Inc.
+# Copyright (C) 2002-2020 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -61,6 +61,7 @@
# mkostemp \
# non-recursive-gnulib-prefix-hack \
# obstack \
+# perl \
# progname \
# readme-release \
# regex \
@@ -72,7 +73,6 @@
# stdbool \
# strerror \
# strverscmp \
-# threadlib \
# unlocked-io \
# update-copyright \
# verify \
@@ -97,7 +97,7 @@ EXTRA_lib_libsed_a_SOURCES =
# Use this preprocessor expression to decide whether #include_next works.
# Do not rely on a 'configure'-time test for this, since the expression
# might appear in an installed header, which is used by some other compiler.
-HAVE_INCLUDE_NEXT = lib/(__GNUC__ lib/|| lib/60000000 lib/<= lib/__DECC_VER)
+HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER)
## end gnulib module absolute-header
@@ -145,7 +145,7 @@ if GL_GENERATE_ALLOCA_H
lib/alloca.h: lib/alloca.in.h $(top_builddir)/config.status
$(AM_V_GEN)rm -f $@-t $@ && \
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
- cat $(top_srcdir)/lib/alloca.in.h; \
+ sed -e 's|@''HAVE_ALLOCA_H''@|$(HAVE_ALLOCA_H)|g' < $(top_srcdir)/lib/alloca.in.h; \
} > $@-t && \
mv -f $@-t $@
else
@@ -346,12 +346,14 @@ lib/fcntl.h: lib/fcntl.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NON
-e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
-e 's|@''NEXT_FCNTL_H''@|$(NEXT_FCNTL_H)|g' \
+ -e 's/@''GNULIB_CREAT''@/$(GNULIB_CREAT)/g' \
-e 's/@''GNULIB_FCNTL''@/$(GNULIB_FCNTL)/g' \
-e 's/@''GNULIB_NONBLOCKING''@/$(GNULIB_NONBLOCKING)/g' \
-e 's/@''GNULIB_OPEN''@/$(GNULIB_OPEN)/g' \
-e 's/@''GNULIB_OPENAT''@/$(GNULIB_OPENAT)/g' \
-e 's|@''HAVE_FCNTL''@|$(HAVE_FCNTL)|g' \
-e 's|@''HAVE_OPENAT''@|$(HAVE_OPENAT)|g' \
+ -e 's|@''REPLACE_CREAT''@|$(REPLACE_CREAT)|g' \
-e 's|@''REPLACE_FCNTL''@|$(REPLACE_FCNTL)|g' \
-e 's|@''REPLACE_OPEN''@|$(REPLACE_OPEN)|g' \
-e 's|@''REPLACE_OPENAT''@|$(REPLACE_OPENAT)|g' \
@@ -374,6 +376,13 @@ EXTRA_DIST += lib/filename.h
## end gnulib module filename
+## begin gnulib module flexmember
+
+
+EXTRA_DIST += lib/flexmember.h
+
+## end gnulib module flexmember
+
## begin gnulib module fpending
@@ -519,13 +528,6 @@ EXTRA_DIST += lib/hard-locale.h
## end gnulib module hard-locale
-## begin gnulib module havelib
-
-
-EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
-
-## end gnulib module havelib
-
## begin gnulib module ignore-value
@@ -540,6 +542,50 @@ EXTRA_DIST += lib/intprops.h
## end gnulib module intprops
+## begin gnulib module inttypes-incomplete
+
+BUILT_SOURCES += lib/inttypes.h
+
+# We need the following in order to create <inttypes.h> when the system
+# doesn't have one that works with the given compiler.
+lib/inttypes.h: lib/inttypes.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE_H) $(ARG_NONNULL_H)
+ $(AM_V_GEN)rm -f $@-t $@ && \
+ { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+ sed -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
+ -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+ -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+ -e 's|@''NEXT_INTTYPES_H''@|$(NEXT_INTTYPES_H)|g' \
+ -e 's/@''PRI_MACROS_BROKEN''@/$(PRI_MACROS_BROKEN)/g' \
+ -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
+ -e 's/@''PRIPTR_PREFIX''@/$(PRIPTR_PREFIX)/g' \
+ -e 's/@''GNULIB_IMAXABS''@/$(GNULIB_IMAXABS)/g' \
+ -e 's/@''GNULIB_IMAXDIV''@/$(GNULIB_IMAXDIV)/g' \
+ -e 's/@''GNULIB_STRTOIMAX''@/$(GNULIB_STRTOIMAX)/g' \
+ -e 's/@''GNULIB_STRTOUMAX''@/$(GNULIB_STRTOUMAX)/g' \
+ -e 's/@''HAVE_DECL_IMAXABS''@/$(HAVE_DECL_IMAXABS)/g' \
+ -e 's/@''HAVE_DECL_IMAXDIV''@/$(HAVE_DECL_IMAXDIV)/g' \
+ -e 's/@''HAVE_DECL_STRTOIMAX''@/$(HAVE_DECL_STRTOIMAX)/g' \
+ -e 's/@''HAVE_DECL_STRTOUMAX''@/$(HAVE_DECL_STRTOUMAX)/g' \
+ -e 's/@''HAVE_IMAXDIV_T''@/$(HAVE_IMAXDIV_T)/g' \
+ -e 's/@''REPLACE_STRTOIMAX''@/$(REPLACE_STRTOIMAX)/g' \
+ -e 's/@''REPLACE_STRTOUMAX''@/$(REPLACE_STRTOUMAX)/g' \
+ -e 's/@''INT32_MAX_LT_INTMAX_MAX''@/$(INT32_MAX_LT_INTMAX_MAX)/g' \
+ -e 's/@''INT64_MAX_EQ_LONG_MAX''@/$(INT64_MAX_EQ_LONG_MAX)/g' \
+ -e 's/@''UINT32_MAX_LT_UINTMAX_MAX''@/$(UINT32_MAX_LT_UINTMAX_MAX)/g' \
+ -e 's/@''UINT64_MAX_EQ_ULONG_MAX''@/$(UINT64_MAX_EQ_ULONG_MAX)/g' \
+ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
+ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \
+ < $(top_srcdir)/lib/inttypes.in.h; \
+ } > $@-t && \
+ mv $@-t $@
+MOSTLYCLEANFILES += lib/inttypes.h lib/inttypes.h-t
+
+EXTRA_DIST += lib/inttypes.in.h
+
+## end gnulib module inttypes-incomplete
+
## begin gnulib module isblank
@@ -642,6 +688,7 @@ lib/locale.h: lib/locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_N
-e 's|@''NEXT_LOCALE_H''@|$(NEXT_LOCALE_H)|g' \
-e 's/@''GNULIB_LOCALECONV''@/$(GNULIB_LOCALECONV)/g' \
-e 's/@''GNULIB_SETLOCALE''@/$(GNULIB_SETLOCALE)/g' \
+ -e 's/@''GNULIB_SETLOCALE_NULL''@/$(GNULIB_SETLOCALE_NULL)/g' \
-e 's/@''GNULIB_DUPLOCALE''@/$(GNULIB_DUPLOCALE)/g' \
-e 's/@''GNULIB_LOCALENAME''@/$(GNULIB_LOCALENAME)/g' \
-e 's|@''HAVE_NEWLOCALE''@|$(HAVE_NEWLOCALE)|g' \
@@ -734,9 +781,9 @@ EXTRA_lib_libsed_a_SOURCES += lib/mbrlen.c
## begin gnulib module mbrtowc
-EXTRA_DIST += lib/mbrtowc.c
+EXTRA_DIST += lib/lc-charset-dispatch.c lib/lc-charset-dispatch.h lib/mbrtowc-impl-utf8.h lib/mbrtowc-impl.h lib/mbrtowc.c lib/mbtowc-lock.c lib/mbtowc-lock.h lib/windows-initguard.h
-EXTRA_lib_libsed_a_SOURCES += lib/mbrtowc.c
+EXTRA_lib_libsed_a_SOURCES += lib/lc-charset-dispatch.c lib/mbrtowc.c lib/mbtowc-lock.c
## end gnulib module mbrtowc
@@ -971,6 +1018,16 @@ EXTRA_lib_libsed_a_SOURCES += lib/getfilecon.c
## end gnulib module selinux-h
+## begin gnulib module setlocale-null
+
+lib_libsed_a_SOURCES += lib/setlocale_null.c
+
+EXTRA_DIST += lib/setlocale-lock.c lib/setlocale_null.h lib/windows-initguard.h
+
+EXTRA_lib_libsed_a_SOURCES += lib/setlocale-lock.c
+
+## end gnulib module setlocale-null
+
## begin gnulib module snippet/_Noreturn
# Because this Makefile snippet defines a variable used by other
@@ -1182,8 +1239,6 @@ lib/stdint.h: lib/stdint.in.h $(top_builddir)/config.status
-e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
-e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
-e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \
- -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
- -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
-e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
-e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \
-e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \
@@ -1383,6 +1438,7 @@ lib/stdlib.h: lib/stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \
-e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \
-e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
+ -e 's/@''GNULIB_STRTOLD''@/$(GNULIB_STRTOLD)/g' \
-e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
-e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \
-e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \
@@ -1396,7 +1452,9 @@ lib/stdlib.h: lib/stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \
-e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \
-e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \
+ -e 's|@''HAVE_INITSTATE''@|$(HAVE_INITSTATE)|g' \
-e 's|@''HAVE_DECL_INITSTATE''@|$(HAVE_DECL_INITSTATE)|g' \
+ -e 's|@''HAVE_MBTOWC''@|$(HAVE_MBTOWC)|g' \
-e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \
-e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \
-e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \
@@ -1414,8 +1472,10 @@ lib/stdlib.h: lib/stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \
-e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \
-e 's|@''HAVE_DECL_SETENV''@|$(HAVE_DECL_SETENV)|g' \
+ -e 's|@''HAVE_SETSTATE''@|$(HAVE_SETSTATE)|g' \
-e 's|@''HAVE_DECL_SETSTATE''@|$(HAVE_DECL_SETSTATE)|g' \
-e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
+ -e 's|@''HAVE_STRTOLD''@|$(HAVE_STRTOLD)|g' \
-e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
-e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
-e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
@@ -1424,6 +1484,7 @@ lib/stdlib.h: lib/stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_DECL_UNSETENV''@|$(HAVE_DECL_UNSETENV)|g' \
-e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
-e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|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' \
@@ -1431,11 +1492,14 @@ lib/stdlib.h: lib/stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''REPLACE_PTSNAME_R''@|$(REPLACE_PTSNAME_R)|g' \
-e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
-e 's|@''REPLACE_QSORT_R''@|$(REPLACE_QSORT_R)|g' \
+ -e 's|@''REPLACE_RANDOM''@|$(REPLACE_RANDOM)|g' \
-e 's|@''REPLACE_RANDOM_R''@|$(REPLACE_RANDOM_R)|g' \
-e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \
-e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \
-e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
+ -e 's|@''REPLACE_SETSTATE''@|$(REPLACE_SETSTATE)|g' \
-e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
+ -e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
-e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
@@ -1722,8 +1786,6 @@ EXTRA_DIST += lib/tempname.h
lib_libsed_a_SOURCES += lib/glthread/threadlib.c
-EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath
-
## end gnulib module threadlib
## begin gnulib module time
@@ -1798,9 +1860,11 @@ lib/unistd.h: lib/unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_N
-e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
-e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \
-e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
+ -e 's/@''GNULIB_ACCESS''@/$(GNULIB_ACCESS)/g' \
-e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \
-e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \
-e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \
+ -e 's/@''GNULIB_COPY_FILE_RANGE''@/$(GNULIB_COPY_FILE_RANGE)/g' \
-e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \
-e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \
-e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \
@@ -1819,6 +1883,7 @@ lib/unistd.h: lib/unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_N
-e 's/@''GNULIB_GETHOSTNAME''@/$(GNULIB_GETHOSTNAME)/g' \
-e 's/@''GNULIB_GETLOGIN''@/$(GNULIB_GETLOGIN)/g' \
-e 's/@''GNULIB_GETLOGIN_R''@/$(GNULIB_GETLOGIN_R)/g' \
+ -e 's/@''GNULIB_GETOPT_POSIX''@/$(GNULIB_GETOPT_POSIX)/g' \
-e 's/@''GNULIB_GETPAGESIZE''@/$(GNULIB_GETPAGESIZE)/g' \
-e 's/@''GNULIB_GETPASS''@/$(GNULIB_GETPASS)/g' \
-e 's/@''GNULIB_GETUSERSHELL''@/$(GNULIB_GETUSERSHELL)/g' \
@@ -1851,6 +1916,7 @@ lib/unistd.h: lib/unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_N
-e 's/@''GNULIB_WRITE''@/$(GNULIB_WRITE)/g' \
< $(top_srcdir)/lib/unistd.in.h | \
sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \
+ -e 's|@''HAVE_COPY_FILE_RANGE''@|$(HAVE_COPY_FILE_RANGE)|g' \
-e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
-e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \
-e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \
@@ -1895,7 +1961,8 @@ lib/unistd.h: lib/unistd.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_N
-e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \
-e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \
| \
- sed -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
+ sed -e 's|@''REPLACE_ACCESS''@|$(REPLACE_ACCESS)|g' \
+ -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \
-e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \
-e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
-e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
@@ -2104,6 +2171,7 @@ lib/wchar.h: lib/wchar.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NON
-e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \
-e 's|@''REPLACE_WCSWIDTH''@|$(REPLACE_WCSWIDTH)|g' \
-e 's|@''REPLACE_WCSFTIME''@|$(REPLACE_WCSFTIME)|g' \
+ -e 's|@''REPLACE_WCSTOK''@|$(REPLACE_WCSTOK)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
@@ -2184,6 +2252,42 @@ EXTRA_DIST += lib/wctype.in.h
## end gnulib module wctype-h
+## begin gnulib module windows-mutex
+
+
+EXTRA_DIST += lib/windows-initguard.h lib/windows-mutex.c lib/windows-mutex.h
+
+EXTRA_lib_libsed_a_SOURCES += lib/windows-mutex.c
+
+## end gnulib module windows-mutex
+
+## begin gnulib module windows-once
+
+
+EXTRA_DIST += lib/windows-once.c lib/windows-once.h
+
+EXTRA_lib_libsed_a_SOURCES += lib/windows-once.c
+
+## end gnulib module windows-once
+
+## begin gnulib module windows-recmutex
+
+
+EXTRA_DIST += lib/windows-initguard.h lib/windows-recmutex.c lib/windows-recmutex.h
+
+EXTRA_lib_libsed_a_SOURCES += lib/windows-recmutex.c
+
+## end gnulib module windows-recmutex
+
+## begin gnulib module windows-rwlock
+
+
+EXTRA_DIST += lib/windows-initguard.h lib/windows-rwlock.c lib/windows-rwlock.h
+
+EXTRA_lib_libsed_a_SOURCES += lib/windows-rwlock.c
+
+## end gnulib module windows-rwlock
+
## begin gnulib module xalloc
lib_libsed_a_SOURCES += lib/xmalloc.c
diff --git a/lib/hard-locale.c b/lib/hard-locale.c
index 49bc6ca..730e9be 100644
--- a/lib/hard-locale.c
+++ b/lib/hard-locale.c
@@ -1,6 +1,6 @@
/* hard-locale.c -- Determine whether a locale is hard.
- Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2018 Free Software
+ Copyright (C) 1997-1999, 2002-2004, 2006-2007, 2009-2020 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
@@ -21,52 +21,15 @@
#include "hard-locale.h"
#include <locale.h>
-#include <stdlib.h>
#include <string.h>
-#ifdef __GLIBC__
-# define GLIBC_VERSION __GLIBC__
-#elif defined __UCLIBC__
-# define GLIBC_VERSION 2
-#else
-# define GLIBC_VERSION 0
-#endif
-
-/* Return true if the current CATEGORY locale is hard, i.e. if you
- can't get away with assuming traditional C or POSIX behavior. */
bool
hard_locale (int category)
{
- bool hard = true;
- char const *p = setlocale (category, NULL);
-
- if (p)
- {
- if (2 <= GLIBC_VERSION)
- {
- if (strcmp (p, "C") == 0 || strcmp (p, "POSIX") == 0)
- hard = false;
- }
- else
- {
- char *locale = strdup (p);
- if (locale)
- {
- /* Temporarily set the locale to the "C" and "POSIX" locales
- to find their names, so that we can determine whether one
- or the other is the caller's locale. */
- if (((p = setlocale (category, "C"))
- && strcmp (p, locale) == 0)
- || ((p = setlocale (category, "POSIX"))
- && strcmp (p, locale) == 0))
- hard = false;
+ char locale[SETLOCALE_NULL_MAX];
- /* Restore the caller's locale. */
- setlocale (category, locale);
- free (locale);
- }
- }
- }
+ if (setlocale_null_r (category, locale, sizeof (locale)))
+ return false;
- return hard;
+ return !(strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0);
}
diff --git a/lib/hard-locale.h b/lib/hard-locale.h
index 22eecc5..1886eaa 100644
--- a/lib/hard-locale.h
+++ b/lib/hard-locale.h
@@ -1,6 +1,6 @@
/* Determine whether a locale is hard.
- Copyright (C) 1999, 2003-2004, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2003-2004, 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
@@ -20,6 +20,9 @@
# include <stdbool.h>
-bool hard_locale (int);
+/* Return true if the specified CATEGORY of the current locale is hard, i.e.
+ different from the C or POSIX locale that has a fixed behavior.
+ CATEGORY must be one of the LC_* values, but not LC_ALL. */
+extern bool hard_locale (int category);
#endif /* HARD_LOCALE_H_ */
diff --git a/lib/ignore-value.h b/lib/ignore-value.h
index 95eac1c..7a92226 100644
--- a/lib/ignore-value.h
+++ b/lib/ignore-value.h
@@ -1,6 +1,6 @@
/* ignore a function return without a compiler warning. -*- coding: utf-8 -*-
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/intprops.h b/lib/intprops.h
index cdaf658..dfbcaae 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -1,6 +1,6 @@
/* intprops.h -- properties of integer types
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-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
@@ -111,8 +111,8 @@
Subtract 1 for the sign bit if T is signed, and then add 1 more for
a minus sign if needed.
- Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is
- signed, this macro may overestimate the true bound by one byte when
+ Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 1 when its argument is
+ unsigned, this macro may overestimate the true bound by one byte when
applied to unsigned types of size 2, 4, 16, ... bytes. */
#define INT_STRLEN_BOUND(t) \
(INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \
@@ -220,14 +220,26 @@
? (a) < (min) >> (b) \
: (max) >> (b) < (a))
-/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */
+/* 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
-# define _GL_HAS_BUILTIN_OVERFLOW 1
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
#else
-# define _GL_HAS_BUILTIN_OVERFLOW 0
+# define _GL_HAS_BUILTIN_ADD_OVERFLOW 0
#endif
-/* True if __builtin_add_overflow_p (A, B, C) works. */
+/* True if __builtin_mul_overflow (A, B, P) works when P is non-null. */
+#ifdef __clang__
+/* Work around Clang bug <https://bugs.llvm.org/show_bug.cgi?id=16404>. */
+# define _GL_HAS_BUILTIN_MUL_OVERFLOW 0
+#else
+# define _GL_HAS_BUILTIN_MUL_OVERFLOW _GL_HAS_BUILTIN_ADD_OVERFLOW
+#endif
+
+/* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
+ __builtin_mul_overflow_p and __builtin_mul_overflow_p. */
#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
/* The _GL*_OVERFLOW macros have the same restrictions as the
@@ -281,7 +293,9 @@
The INT_<op>_OVERFLOW macros return 1 if the corresponding C operators
might not yield numerically correct answers due to arithmetic overflow.
- The INT_<op>_WRAPV macros also store the low-order bits of the answer.
+ The INT_<op>_WRAPV macros compute the low-order bits of the sum,
+ difference, and product of two C integers, and return 1 if these
+ low-order bits are not numerically correct.
These macros work correctly on all known practical hosts, and do not rely
on undefined behavior due to signed arithmetic overflow.
@@ -309,9 +323,11 @@
arguments should not have side effects.
The WRAPV macros are not constant expressions. They support only
- +, binary -, and *. The result type must be signed.
+ +, binary -, and *. Because the WRAPV macros convert the result,
+ they report overflow in different circumstances than the OVERFLOW
+ macros do.
- These macros are tuned for their last argument being a constant.
+ These macros are tuned for their last input argument being a constant.
Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B,
A % B, and A << B would overflow, respectively. */
@@ -347,19 +363,38 @@
/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R.
Return 1 if the result overflows. See above for restrictions. */
-#define INT_ADD_WRAPV(a, b, r) \
- _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW)
-#define INT_SUBTRACT_WRAPV(a, b, r) \
- _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW)
-#define INT_MULTIPLY_WRAPV(a, b, r) \
- _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW)
+#if _GL_HAS_BUILTIN_ADD_OVERFLOW
+# define INT_ADD_WRAPV(a, b, r) __builtin_add_overflow (a, b, r)
+# define INT_SUBTRACT_WRAPV(a, b, r) __builtin_sub_overflow (a, b, r)
+#else
+# define INT_ADD_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, +, _GL_INT_ADD_RANGE_OVERFLOW)
+# define INT_SUBTRACT_WRAPV(a, b, r) \
+ _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__))
+# define INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
+# else
+ /* Work around GCC bug 91450. */
+# define INT_MULTIPLY_WRAPV(a, b, r) \
+ ((!_GL_SIGNED_TYPE_OR_EXPR (*(r)) && EXPR_SIGNED (a) && EXPR_SIGNED (b) \
+ && _GL_INT_MULTIPLY_RANGE_OVERFLOW (a, b, 0, (__typeof__ (*(r))) -1)) \
+ ? ((void) __builtin_mul_overflow (a, b, r), 1) \
+ : __builtin_mul_overflow (a, b, r))
+# endif
+#else
+# define INT_MULTIPLY_WRAPV(a, b, r) \
+ _GL_INT_OP_WRAPV (a, b, r, *, _GL_INT_MULTIPLY_RANGE_OVERFLOW)
+#endif
/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193
https://llvm.org/bugs/show_bug.cgi?id=25390
For now, assume all versions of GCC-like compilers generate bogus
- warnings for _Generic. This matters only for older compilers that
- lack __builtin_add_overflow. */
+ warnings for _Generic. This matters only for compilers that
+ lack relevant builtins. */
#if __GNUC__
# define _GL__GENERIC_BOGUS 1
#else
@@ -367,53 +402,100 @@
#endif
/* Store the low-order bits of A <op> B into *R, where OP specifies
- the operation. BUILTIN is the builtin operation, and OVERFLOW the
- overflow predicate. Return 1 if the result overflows. See above
- for restrictions. */
-#if _GL_HAS_BUILTIN_OVERFLOW
-# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r)
-#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
-# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+ the operation and OVERFLOW the overflow predicate. Return 1 if the
+ result overflows. See above for restrictions. */
+#if 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS
+# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
(_Generic \
(*(r), \
signed char: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
signed char, SCHAR_MIN, SCHAR_MAX), \
+ unsigned char: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned char, 0, UCHAR_MAX), \
short int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
short int, SHRT_MIN, SHRT_MAX), \
+ unsigned short int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned short int, 0, USHRT_MAX), \
int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
int, INT_MIN, INT_MAX), \
+ unsigned int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned int, 0, UINT_MAX), \
long int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
long int, LONG_MIN, LONG_MAX), \
+ unsigned long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ unsigned long int, 0, ULONG_MAX), \
long long int: \
_GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
- long long int, LLONG_MIN, LLONG_MAX)))
+ long long int, LLONG_MIN, LLONG_MAX), \
+ unsigned long long int: \
+ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ unsigned long long int, 0, ULLONG_MAX)))
#else
-# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \
+/* Store the low-order bits of A <op> B into *R, where OP specifies
+ the operation and OVERFLOW the overflow predicate. If *R is
+ signed, its type is ST with bounds SMIN..SMAX; otherwise its type
+ is UT with bounds U..UMAX. ST and UT are narrower than int.
+ Return 1 if the result overflows. See above for restrictions. */
+# if _GL_HAVE___TYPEOF__
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (TYPE_SIGNED (__typeof__ (*(r))) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, st, smin, smax) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, ut, 0, umax))
+# else
+# define _GL_INT_OP_WRAPV_SMALLISH(a,b,r,op,overflow,st,smin,smax,ut,umax) \
+ (overflow (a, b, smin, smax) \
+ ? (overflow (a, b, 0, umax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 1) \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) < 0) \
+ : (overflow (a, b, 0, umax) \
+ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st)) >= 0 \
+ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a,b,op,unsigned,st), 0)))
+# endif
+
+# define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
(sizeof *(r) == sizeof (signed char) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- signed char, SCHAR_MIN, SCHAR_MAX) \
+ ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ signed char, SCHAR_MIN, SCHAR_MAX, \
+ unsigned char, UCHAR_MAX) \
: sizeof *(r) == sizeof (short int) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- short int, SHRT_MIN, SHRT_MAX) \
+ ? _GL_INT_OP_WRAPV_SMALLISH (a, b, r, op, overflow, \
+ short int, SHRT_MIN, SHRT_MAX, \
+ unsigned short int, USHRT_MAX) \
: sizeof *(r) == sizeof (int) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
- int, INT_MIN, INT_MAX) \
+ ? (EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ int, INT_MIN, INT_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
+ unsigned int, 0, UINT_MAX)) \
: _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow))
# ifdef LLONG_MAX
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
(sizeof *(r) == sizeof (long int) \
- ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
- long int, LONG_MIN, LONG_MAX) \
- : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
- long long int, LLONG_MIN, LLONG_MAX))
+ ? (EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ unsigned long int, 0, ULONG_MAX)) \
+ : (EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ long long int, LLONG_MIN, LLONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \
+ unsigned long long int, 0, ULLONG_MAX)))
# else
# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \
- _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
- long int, LONG_MIN, LONG_MAX)
+ (EXPR_SIGNED (*(r)) \
+ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ long int, LONG_MIN, LONG_MAX) \
+ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \
+ unsigned long int, 0, ULONG_MAX))
# endif
#endif
@@ -422,13 +504,7 @@
overflow problems. *R's type is T, with extrema TMIN and TMAX.
T must be a signed integer type. Return 1 if the result overflows. */
#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
- (sizeof ((a) op (b)) < sizeof (t) \
- ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \
- : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax))
-#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \
- ((overflow (a, b) \
- || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \
- || (tmax) < ((a) op (b))) \
+ (overflow (a, b, tmin, tmax) \
? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
: (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
@@ -452,4 +528,57 @@
#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
((t) ((ut) (a) op (ut) (b)))
+/* Return true if the numeric values A + B, A - B, A * B fall outside
+ the range TMIN..TMAX. Arguments should be integer expressions
+ without side effects. TMIN should be signed and nonpositive.
+ TMAX should be positive, and should be signed unless TMIN is zero. */
+#define _GL_INT_ADD_RANGE_OVERFLOW(a, b, tmin, tmax) \
+ ((b) < 0 \
+ ? (((tmin) \
+ ? ((EXPR_SIGNED (_GL_INT_CONVERT (a, (tmin) - (b))) || (b) < (tmin)) \
+ && (a) < (tmin) - (b)) \
+ : (a) <= -1 - (b)) \
+ || ((EXPR_SIGNED (a) ? 0 <= (a) : (tmax) < (a)) && (tmax) < (a) + (b))) \
+ : (a) < 0 \
+ ? (((tmin) \
+ ? ((EXPR_SIGNED (_GL_INT_CONVERT (b, (tmin) - (a))) || (a) < (tmin)) \
+ && (b) < (tmin) - (a)) \
+ : (b) <= -1 - (a)) \
+ || ((EXPR_SIGNED (_GL_INT_CONVERT (a, b)) || (tmax) < (b)) \
+ && (tmax) < (a) + (b))) \
+ : (tmax) < (b) || (tmax) - (b) < (a))
+#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \
+ (((a) < 0) == ((b) < 0) \
+ ? ((a) < (b) \
+ ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \
+ : (tmax) < (a) - (b)) \
+ : (a) < 0 \
+ ? ((!EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
+ || (a) - (tmin) < (b)) \
+ : ((! (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+ && EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \
+ && (tmax) <= -1 - (b)) \
+ || (tmax) + (b) < (a)))
+#define _GL_INT_MULTIPLY_RANGE_OVERFLOW(a, b, tmin, tmax) \
+ ((b) < 0 \
+ ? ((a) < 0 \
+ ? (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
+ ? (a) < (tmax) / (b) \
+ : ((INT_NEGATE_OVERFLOW (b) \
+ ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (b) - 1) \
+ : (tmax) / -(b)) \
+ <= -1 - (a))) \
+ : INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \
+ ? (EXPR_SIGNED (a) \
+ ? 0 < (a) + (tmin) \
+ : 0 < (a) && -1 - (tmin) < (a) - 1) \
+ : (tmin) / (b) < (a)) \
+ : (b) == 0 \
+ ? 0 \
+ : ((a) < 0 \
+ ? (INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (a, tmin)) && (a) == -1 \
+ ? (EXPR_SIGNED (b) ? 0 < (b) + (tmin) : -1 - (tmin) < (b) - 1) \
+ : (tmin) / (a) < (b)) \
+ : (tmax) / (b) < (a)))
+
#endif /* _GL_INTPROPS_H */
diff --git a/lib/inttypes.in.h b/lib/inttypes.in.h
new file mode 100644
index 0000000..d6efc7e
--- /dev/null
+++ b/lib/inttypes.in.h
@@ -0,0 +1,1148 @@
+/* Copyright (C) 2006-2020 Free Software Foundation, Inc.
+ Written by Paul Eggert, Bruno Haible, Derek Price.
+ This file is part of gnulib.
+
+ 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/>. */
+
+/*
+ * ISO C 99 <inttypes.h> for platforms that lack it.
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/inttypes.h.html>
+ */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+/* Include the original <inttypes.h> if it exists, and if this file
+ has not been included yet or if this file includes gnulib stdint.h
+ which in turn includes this file.
+ The include_next requires a split double-inclusion guard. */
+#if ! defined INTTYPES_H || defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+# if @HAVE_INTTYPES_H@
+
+ /* Some pre-C++11 <stdint.h> implementations need this. */
+# if defined __cplusplus && ! defined __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS 1
+# endif
+
+# @INCLUDE_NEXT@ @NEXT_INTTYPES_H@
+
+# define _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H
+# endif
+#endif
+
+#if ! defined INTTYPES_H && ! defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
+#define INTTYPES_H
+
+/* Include <stdint.h> or the gnulib replacement.
+ But avoid namespace pollution on glibc systems. */
+#ifndef __GLIBC__
+# include <stdint.h>
+#endif
+/* Get CHAR_BIT, INT_MAX, LONG_MAX, etc. */
+#include <limits.h>
+/* On mingw, __USE_MINGW_ANSI_STDIO only works if <stdio.h> is also included */
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <stdio.h>
+#endif
+
+#if !(INT_MAX == 0x7fffffff && INT_MIN + INT_MAX == -1)
+# error "This file assumes that 'int' is 32-bit two's complement. Please report your platform and compiler to <bug-gnulib@gnu.org>."
+#endif
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
+
+/* The definition of _GL_ARG_NONNULL is copied here. */
+
+/* The definition of _GL_WARN_ON_USE is copied here. */
+
+/* 7.8.1 Macros for format specifiers */
+
+#if defined _TNS_R_TARGET
+ /* Tandem NonStop R series and compatible platforms released before
+ July 2005 support %Ld but not %lld. */
+# define _LONG_LONG_FORMAT_PREFIX "L"
+#else
+# define _LONG_LONG_FORMAT_PREFIX "ll"
+#endif
+
+#if !defined PRId8 || @PRI_MACROS_BROKEN@
+# undef PRId8
+# ifdef INT8_MAX
+# define PRId8 "d"
+# endif
+#endif
+#if !defined PRIi8 || @PRI_MACROS_BROKEN@
+# undef PRIi8
+# ifdef INT8_MAX
+# define PRIi8 "i"
+# endif
+#endif
+#if !defined PRIo8 || @PRI_MACROS_BROKEN@
+# undef PRIo8
+# ifdef UINT8_MAX
+# define PRIo8 "o"
+# endif
+#endif
+#if !defined PRIu8 || @PRI_MACROS_BROKEN@
+# undef PRIu8
+# ifdef UINT8_MAX
+# define PRIu8 "u"
+# endif
+#endif
+#if !defined PRIx8 || @PRI_MACROS_BROKEN@
+# undef PRIx8
+# ifdef UINT8_MAX
+# define PRIx8 "x"
+# endif
+#endif
+#if !defined PRIX8 || @PRI_MACROS_BROKEN@
+# undef PRIX8
+# ifdef UINT8_MAX
+# define PRIX8 "X"
+# endif
+#endif
+#if !defined PRId16 || @PRI_MACROS_BROKEN@
+# undef PRId16
+# ifdef INT16_MAX
+# define PRId16 "d"
+# endif
+#endif
+#if !defined PRIi16 || @PRI_MACROS_BROKEN@
+# undef PRIi16
+# ifdef INT16_MAX
+# define PRIi16 "i"
+# endif
+#endif
+#if !defined PRIo16 || @PRI_MACROS_BROKEN@
+# undef PRIo16
+# ifdef UINT16_MAX
+# define PRIo16 "o"
+# endif
+#endif
+#if !defined PRIu16 || @PRI_MACROS_BROKEN@
+# undef PRIu16
+# ifdef UINT16_MAX
+# define PRIu16 "u"
+# endif
+#endif
+#if !defined PRIx16 || @PRI_MACROS_BROKEN@
+# undef PRIx16
+# ifdef UINT16_MAX
+# define PRIx16 "x"
+# endif
+#endif
+#if !defined PRIX16 || @PRI_MACROS_BROKEN@
+# undef PRIX16
+# ifdef UINT16_MAX
+# define PRIX16 "X"
+# endif
+#endif
+#if !defined PRId32 || @PRI_MACROS_BROKEN@
+# undef PRId32
+# ifdef INT32_MAX
+# define PRId32 "d"
+# endif
+#endif
+#if !defined PRIi32 || @PRI_MACROS_BROKEN@
+# undef PRIi32
+# ifdef INT32_MAX
+# define PRIi32 "i"
+# endif
+#endif
+#if !defined PRIo32 || @PRI_MACROS_BROKEN@
+# undef PRIo32
+# ifdef UINT32_MAX
+# define PRIo32 "o"
+# endif
+#endif
+#if !defined PRIu32 || @PRI_MACROS_BROKEN@
+# undef PRIu32
+# ifdef UINT32_MAX
+# define PRIu32 "u"
+# endif
+#endif
+#if !defined PRIx32 || @PRI_MACROS_BROKEN@
+# undef PRIx32
+# ifdef UINT32_MAX
+# define PRIx32 "x"
+# endif
+#endif
+#if !defined PRIX32 || @PRI_MACROS_BROKEN@
+# undef PRIX32
+# ifdef UINT32_MAX
+# define PRIX32 "X"
+# endif
+#endif
+#ifdef INT64_MAX
+# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@)
+# define _PRI64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _PRI64_PREFIX "I64"
+# elif LONG_MAX >> 30 == 1
+# define _PRI64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined PRId64 || @PRI_MACROS_BROKEN@
+# undef PRId64
+# define PRId64 _PRI64_PREFIX "d"
+# endif
+# if !defined PRIi64 || @PRI_MACROS_BROKEN@
+# undef PRIi64
+# define PRIi64 _PRI64_PREFIX "i"
+# endif
+#endif
+#ifdef UINT64_MAX
+# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@)
+# define _PRIu64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _PRIu64_PREFIX "I64"
+# elif ULONG_MAX >> 31 == 1
+# define _PRIu64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined PRIo64 || @PRI_MACROS_BROKEN@
+# undef PRIo64
+# define PRIo64 _PRIu64_PREFIX "o"
+# endif
+# if !defined PRIu64 || @PRI_MACROS_BROKEN@
+# undef PRIu64
+# define PRIu64 _PRIu64_PREFIX "u"
+# endif
+# if !defined PRIx64 || @PRI_MACROS_BROKEN@
+# undef PRIx64
+# define PRIx64 _PRIu64_PREFIX "x"
+# endif
+# if !defined PRIX64 || @PRI_MACROS_BROKEN@
+# undef PRIX64
+# define PRIX64 _PRIu64_PREFIX "X"
+# endif
+#endif
+
+#if !defined PRIdLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST8
+# define PRIdLEAST8 "d"
+#endif
+#if !defined PRIiLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST8
+# define PRIiLEAST8 "i"
+#endif
+#if !defined PRIoLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST8
+# define PRIoLEAST8 "o"
+#endif
+#if !defined PRIuLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST8
+# define PRIuLEAST8 "u"
+#endif
+#if !defined PRIxLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST8
+# define PRIxLEAST8 "x"
+#endif
+#if !defined PRIXLEAST8 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST8
+# define PRIXLEAST8 "X"
+#endif
+#if !defined PRIdLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST16
+# define PRIdLEAST16 "d"
+#endif
+#if !defined PRIiLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST16
+# define PRIiLEAST16 "i"
+#endif
+#if !defined PRIoLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST16
+# define PRIoLEAST16 "o"
+#endif
+#if !defined PRIuLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST16
+# define PRIuLEAST16 "u"
+#endif
+#if !defined PRIxLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST16
+# define PRIxLEAST16 "x"
+#endif
+#if !defined PRIXLEAST16 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST16
+# define PRIXLEAST16 "X"
+#endif
+#if !defined PRIdLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST32
+# define PRIdLEAST32 "d"
+#endif
+#if !defined PRIiLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST32
+# define PRIiLEAST32 "i"
+#endif
+#if !defined PRIoLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST32
+# define PRIoLEAST32 "o"
+#endif
+#if !defined PRIuLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST32
+# define PRIuLEAST32 "u"
+#endif
+#if !defined PRIxLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST32
+# define PRIxLEAST32 "x"
+#endif
+#if !defined PRIXLEAST32 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST32
+# define PRIXLEAST32 "X"
+#endif
+#ifdef INT64_MAX
+# if !defined PRIdLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIdLEAST64
+# define PRIdLEAST64 PRId64
+# endif
+# if !defined PRIiLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIiLEAST64
+# define PRIiLEAST64 PRIi64
+# endif
+#endif
+#ifdef UINT64_MAX
+# if !defined PRIoLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIoLEAST64
+# define PRIoLEAST64 PRIo64
+# endif
+# if !defined PRIuLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIuLEAST64
+# define PRIuLEAST64 PRIu64
+# endif
+# if !defined PRIxLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIxLEAST64
+# define PRIxLEAST64 PRIx64
+# endif
+# if !defined PRIXLEAST64 || @PRI_MACROS_BROKEN@
+# undef PRIXLEAST64
+# define PRIXLEAST64 PRIX64
+# endif
+#endif
+
+#if !defined PRIdFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define PRIdFAST8 PRId64
+# else
+# define PRIdFAST8 "d"
+# endif
+#endif
+#if !defined PRIiFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define PRIiFAST8 PRIi64
+# else
+# define PRIiFAST8 "i"
+# endif
+#endif
+#if !defined PRIoFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIoFAST8 PRIo64
+# else
+# define PRIoFAST8 "o"
+# endif
+#endif
+#if !defined PRIuFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIuFAST8 PRIu64
+# else
+# define PRIuFAST8 "u"
+# endif
+#endif
+#if !defined PRIxFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIxFAST8 PRIx64
+# else
+# define PRIxFAST8 "x"
+# endif
+#endif
+#if !defined PRIXFAST8 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define PRIXFAST8 PRIX64
+# else
+# define PRIXFAST8 "X"
+# endif
+#endif
+#if !defined PRIdFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define PRIdFAST16 PRId64
+# else
+# define PRIdFAST16 "d"
+# endif
+#endif
+#if !defined PRIiFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define PRIiFAST16 PRIi64
+# else
+# define PRIiFAST16 "i"
+# endif
+#endif
+#if !defined PRIoFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIoFAST16 PRIo64
+# else
+# define PRIoFAST16 "o"
+# endif
+#endif
+#if !defined PRIuFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIuFAST16 PRIu64
+# else
+# define PRIuFAST16 "u"
+# endif
+#endif
+#if !defined PRIxFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIxFAST16 PRIx64
+# else
+# define PRIxFAST16 "x"
+# endif
+#endif
+#if !defined PRIXFAST16 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define PRIXFAST16 PRIX64
+# else
+# define PRIXFAST16 "X"
+# endif
+#endif
+#if !defined PRIdFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define PRIdFAST32 PRId64
+# else
+# define PRIdFAST32 "d"
+# endif
+#endif
+#if !defined PRIiFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define PRIiFAST32 PRIi64
+# else
+# define PRIiFAST32 "i"
+# endif
+#endif
+#if !defined PRIoFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIoFAST32 PRIo64
+# else
+# define PRIoFAST32 "o"
+# endif
+#endif
+#if !defined PRIuFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIuFAST32 PRIu64
+# else
+# define PRIuFAST32 "u"
+# endif
+#endif
+#if !defined PRIxFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIxFAST32 PRIx64
+# else
+# define PRIxFAST32 "x"
+# endif
+#endif
+#if !defined PRIXFAST32 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define PRIXFAST32 PRIX64
+# else
+# define PRIXFAST32 "X"
+# endif
+#endif
+#ifdef INT64_MAX
+# if !defined PRIdFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIdFAST64
+# define PRIdFAST64 PRId64
+# endif
+# if !defined PRIiFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIiFAST64
+# define PRIiFAST64 PRIi64
+# endif
+#endif
+#ifdef UINT64_MAX
+# if !defined PRIoFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIoFAST64
+# define PRIoFAST64 PRIo64
+# endif
+# if !defined PRIuFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIuFAST64
+# define PRIuFAST64 PRIu64
+# endif
+# if !defined PRIxFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIxFAST64
+# define PRIxFAST64 PRIx64
+# endif
+# if !defined PRIXFAST64 || @PRI_MACROS_BROKEN@
+# undef PRIXFAST64
+# define PRIXFAST64 PRIX64
+# endif
+#endif
+
+#if !defined PRIdMAX || @PRI_MACROS_BROKEN@
+# undef PRIdMAX
+# if @INT32_MAX_LT_INTMAX_MAX@
+# define PRIdMAX PRId64
+# else
+# define PRIdMAX "ld"
+# endif
+#endif
+#if !defined PRIiMAX || @PRI_MACROS_BROKEN@
+# undef PRIiMAX
+# if @INT32_MAX_LT_INTMAX_MAX@
+# define PRIiMAX PRIi64
+# else
+# define PRIiMAX "li"
+# endif
+#endif
+#if !defined PRIoMAX || @PRI_MACROS_BROKEN@
+# undef PRIoMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define PRIoMAX PRIo64
+# else
+# define PRIoMAX "lo"
+# endif
+#endif
+#if !defined PRIuMAX || @PRI_MACROS_BROKEN@
+# undef PRIuMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define PRIuMAX PRIu64
+# else
+# define PRIuMAX "lu"
+# endif
+#endif
+#if !defined PRIxMAX || @PRI_MACROS_BROKEN@
+# undef PRIxMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define PRIxMAX PRIx64
+# else
+# define PRIxMAX "lx"
+# endif
+#endif
+#if !defined PRIXMAX || @PRI_MACROS_BROKEN@
+# undef PRIXMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define PRIXMAX PRIX64
+# else
+# define PRIXMAX "lX"
+# endif
+#endif
+
+#if !defined PRIdPTR || @PRI_MACROS_BROKEN@
+# undef PRIdPTR
+# ifdef INTPTR_MAX
+# define PRIdPTR @PRIPTR_PREFIX@ "d"
+# endif
+#endif
+#if !defined PRIiPTR || @PRI_MACROS_BROKEN@
+# undef PRIiPTR
+# ifdef INTPTR_MAX
+# define PRIiPTR @PRIPTR_PREFIX@ "i"
+# endif
+#endif
+#if !defined PRIoPTR || @PRI_MACROS_BROKEN@
+# undef PRIoPTR
+# ifdef UINTPTR_MAX
+# define PRIoPTR @PRIPTR_PREFIX@ "o"
+# endif
+#endif
+#if !defined PRIuPTR || @PRI_MACROS_BROKEN@
+# undef PRIuPTR
+# ifdef UINTPTR_MAX
+# define PRIuPTR @PRIPTR_PREFIX@ "u"
+# endif
+#endif
+#if !defined PRIxPTR || @PRI_MACROS_BROKEN@
+# undef PRIxPTR
+# ifdef UINTPTR_MAX
+# define PRIxPTR @PRIPTR_PREFIX@ "x"
+# endif
+#endif
+#if !defined PRIXPTR || @PRI_MACROS_BROKEN@
+# undef PRIXPTR
+# ifdef UINTPTR_MAX
+# define PRIXPTR @PRIPTR_PREFIX@ "X"
+# endif
+#endif
+
+#if !defined SCNd8 || @PRI_MACROS_BROKEN@
+# undef SCNd8
+# ifdef INT8_MAX
+# define SCNd8 "hhd"
+# endif
+#endif
+#if !defined SCNi8 || @PRI_MACROS_BROKEN@
+# undef SCNi8
+# ifdef INT8_MAX
+# define SCNi8 "hhi"
+# endif
+#endif
+#if !defined SCNo8 || @PRI_MACROS_BROKEN@
+# undef SCNo8
+# ifdef UINT8_MAX
+# define SCNo8 "hho"
+# endif
+#endif
+#if !defined SCNu8 || @PRI_MACROS_BROKEN@
+# undef SCNu8
+# ifdef UINT8_MAX
+# define SCNu8 "hhu"
+# endif
+#endif
+#if !defined SCNx8 || @PRI_MACROS_BROKEN@
+# undef SCNx8
+# ifdef UINT8_MAX
+# define SCNx8 "hhx"
+# endif
+#endif
+#if !defined SCNd16 || @PRI_MACROS_BROKEN@
+# undef SCNd16
+# ifdef INT16_MAX
+# define SCNd16 "hd"
+# endif
+#endif
+#if !defined SCNi16 || @PRI_MACROS_BROKEN@
+# undef SCNi16
+# ifdef INT16_MAX
+# define SCNi16 "hi"
+# endif
+#endif
+#if !defined SCNo16 || @PRI_MACROS_BROKEN@
+# undef SCNo16
+# ifdef UINT16_MAX
+# define SCNo16 "ho"
+# endif
+#endif
+#if !defined SCNu16 || @PRI_MACROS_BROKEN@
+# undef SCNu16
+# ifdef UINT16_MAX
+# define SCNu16 "hu"
+# endif
+#endif
+#if !defined SCNx16 || @PRI_MACROS_BROKEN@
+# undef SCNx16
+# ifdef UINT16_MAX
+# define SCNx16 "hx"
+# endif
+#endif
+#if !defined SCNd32 || @PRI_MACROS_BROKEN@
+# undef SCNd32
+# ifdef INT32_MAX
+# define SCNd32 "d"
+# endif
+#endif
+#if !defined SCNi32 || @PRI_MACROS_BROKEN@
+# undef SCNi32
+# ifdef INT32_MAX
+# define SCNi32 "i"
+# endif
+#endif
+#if !defined SCNo32 || @PRI_MACROS_BROKEN@
+# undef SCNo32
+# ifdef UINT32_MAX
+# define SCNo32 "o"
+# endif
+#endif
+#if !defined SCNu32 || @PRI_MACROS_BROKEN@
+# undef SCNu32
+# ifdef UINT32_MAX
+# define SCNu32 "u"
+# endif
+#endif
+#if !defined SCNx32 || @PRI_MACROS_BROKEN@
+# undef SCNx32
+# ifdef UINT32_MAX
+# define SCNx32 "x"
+# endif
+#endif
+#ifdef INT64_MAX
+# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @INT64_MAX_EQ_LONG_MAX@)
+# define _SCN64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _SCN64_PREFIX "I64"
+# elif LONG_MAX >> 30 == 1
+# define _SCN64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined SCNd64 || @PRI_MACROS_BROKEN@
+# undef SCNd64
+# define SCNd64 _SCN64_PREFIX "d"
+# endif
+# if !defined SCNi64 || @PRI_MACROS_BROKEN@
+# undef SCNi64
+# define SCNi64 _SCN64_PREFIX "i"
+# endif
+#endif
+#ifdef UINT64_MAX
+# if (@APPLE_UNIVERSAL_BUILD@ ? defined _LP64 : @UINT64_MAX_EQ_ULONG_MAX@)
+# define _SCNu64_PREFIX "l"
+# elif defined _MSC_VER || defined __MINGW32__
+# define _SCNu64_PREFIX "I64"
+# elif ULONG_MAX >> 31 == 1
+# define _SCNu64_PREFIX _LONG_LONG_FORMAT_PREFIX
+# endif
+# if !defined SCNo64 || @PRI_MACROS_BROKEN@
+# undef SCNo64
+# define SCNo64 _SCNu64_PREFIX "o"
+# endif
+# if !defined SCNu64 || @PRI_MACROS_BROKEN@
+# undef SCNu64
+# define SCNu64 _SCNu64_PREFIX "u"
+# endif
+# if !defined SCNx64 || @PRI_MACROS_BROKEN@
+# undef SCNx64
+# define SCNx64 _SCNu64_PREFIX "x"
+# endif
+#endif
+
+#if !defined SCNdLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST8
+# define SCNdLEAST8 "hhd"
+#endif
+#if !defined SCNiLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST8
+# define SCNiLEAST8 "hhi"
+#endif
+#if !defined SCNoLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST8
+# define SCNoLEAST8 "hho"
+#endif
+#if !defined SCNuLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST8
+# define SCNuLEAST8 "hhu"
+#endif
+#if !defined SCNxLEAST8 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST8
+# define SCNxLEAST8 "hhx"
+#endif
+#if !defined SCNdLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST16
+# define SCNdLEAST16 "hd"
+#endif
+#if !defined SCNiLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST16
+# define SCNiLEAST16 "hi"
+#endif
+#if !defined SCNoLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST16
+# define SCNoLEAST16 "ho"
+#endif
+#if !defined SCNuLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST16
+# define SCNuLEAST16 "hu"
+#endif
+#if !defined SCNxLEAST16 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST16
+# define SCNxLEAST16 "hx"
+#endif
+#if !defined SCNdLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST32
+# define SCNdLEAST32 "d"
+#endif
+#if !defined SCNiLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST32
+# define SCNiLEAST32 "i"
+#endif
+#if !defined SCNoLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST32
+# define SCNoLEAST32 "o"
+#endif
+#if !defined SCNuLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST32
+# define SCNuLEAST32 "u"
+#endif
+#if !defined SCNxLEAST32 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST32
+# define SCNxLEAST32 "x"
+#endif
+#ifdef INT64_MAX
+# if !defined SCNdLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNdLEAST64
+# define SCNdLEAST64 SCNd64
+# endif
+# if !defined SCNiLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNiLEAST64
+# define SCNiLEAST64 SCNi64
+# endif
+#endif
+#ifdef UINT64_MAX
+# if !defined SCNoLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNoLEAST64
+# define SCNoLEAST64 SCNo64
+# endif
+# if !defined SCNuLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNuLEAST64
+# define SCNuLEAST64 SCNu64
+# endif
+# if !defined SCNxLEAST64 || @PRI_MACROS_BROKEN@
+# undef SCNxLEAST64
+# define SCNxLEAST64 SCNx64
+# endif
+#endif
+
+#if !defined SCNdFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define SCNdFAST8 SCNd64
+# elif INT_FAST8_MAX == 0x7fff
+# define SCNdFAST8 "hd"
+# elif INT_FAST8_MAX == 0x7f
+# define SCNdFAST8 "hhd"
+# else
+# define SCNdFAST8 "d"
+# endif
+#endif
+#if !defined SCNiFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST8
+# if INT_FAST8_MAX > INT32_MAX
+# define SCNiFAST8 SCNi64
+# elif INT_FAST8_MAX == 0x7fff
+# define SCNiFAST8 "hi"
+# elif INT_FAST8_MAX == 0x7f
+# define SCNiFAST8 "hhi"
+# else
+# define SCNiFAST8 "i"
+# endif
+#endif
+#if !defined SCNoFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define SCNoFAST8 SCNo64
+# elif UINT_FAST8_MAX == 0xffff
+# define SCNoFAST8 "ho"
+# elif UINT_FAST8_MAX == 0xff
+# define SCNoFAST8 "hho"
+# else
+# define SCNoFAST8 "o"
+# endif
+#endif
+#if !defined SCNuFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define SCNuFAST8 SCNu64
+# elif UINT_FAST8_MAX == 0xffff
+# define SCNuFAST8 "hu"
+# elif UINT_FAST8_MAX == 0xff
+# define SCNuFAST8 "hhu"
+# else
+# define SCNuFAST8 "u"
+# endif
+#endif
+#if !defined SCNxFAST8 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST8
+# if UINT_FAST8_MAX > UINT32_MAX
+# define SCNxFAST8 SCNx64
+# elif UINT_FAST8_MAX == 0xffff
+# define SCNxFAST8 "hx"
+# elif UINT_FAST8_MAX == 0xff
+# define SCNxFAST8 "hhx"
+# else
+# define SCNxFAST8 "x"
+# endif
+#endif
+#if !defined SCNdFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define SCNdFAST16 SCNd64
+# elif INT_FAST16_MAX == 0x7fff
+# define SCNdFAST16 "hd"
+# else
+# define SCNdFAST16 "d"
+# endif
+#endif
+#if !defined SCNiFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST16
+# if INT_FAST16_MAX > INT32_MAX
+# define SCNiFAST16 SCNi64
+# elif INT_FAST16_MAX == 0x7fff
+# define SCNiFAST16 "hi"
+# else
+# define SCNiFAST16 "i"
+# endif
+#endif
+#if !defined SCNoFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define SCNoFAST16 SCNo64
+# elif UINT_FAST16_MAX == 0xffff
+# define SCNoFAST16 "ho"
+# else
+# define SCNoFAST16 "o"
+# endif
+#endif
+#if !defined SCNuFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define SCNuFAST16 SCNu64
+# elif UINT_FAST16_MAX == 0xffff
+# define SCNuFAST16 "hu"
+# else
+# define SCNuFAST16 "u"
+# endif
+#endif
+#if !defined SCNxFAST16 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST16
+# if UINT_FAST16_MAX > UINT32_MAX
+# define SCNxFAST16 SCNx64
+# elif UINT_FAST16_MAX == 0xffff
+# define SCNxFAST16 "hx"
+# else
+# define SCNxFAST16 "x"
+# endif
+#endif
+#if !defined SCNdFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define SCNdFAST32 SCNd64
+# else
+# define SCNdFAST32 "d"
+# endif
+#endif
+#if !defined SCNiFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST32
+# if INT_FAST32_MAX > INT32_MAX
+# define SCNiFAST32 SCNi64
+# else
+# define SCNiFAST32 "i"
+# endif
+#endif
+#if !defined SCNoFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define SCNoFAST32 SCNo64
+# else
+# define SCNoFAST32 "o"
+# endif
+#endif
+#if !defined SCNuFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define SCNuFAST32 SCNu64
+# else
+# define SCNuFAST32 "u"
+# endif
+#endif
+#if !defined SCNxFAST32 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST32
+# if UINT_FAST32_MAX > UINT32_MAX
+# define SCNxFAST32 SCNx64
+# else
+# define SCNxFAST32 "x"
+# endif
+#endif
+#ifdef INT64_MAX
+# if !defined SCNdFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNdFAST64
+# define SCNdFAST64 SCNd64
+# endif
+# if !defined SCNiFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNiFAST64
+# define SCNiFAST64 SCNi64
+# endif
+#endif
+#ifdef UINT64_MAX
+# if !defined SCNoFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNoFAST64
+# define SCNoFAST64 SCNo64
+# endif
+# if !defined SCNuFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNuFAST64
+# define SCNuFAST64 SCNu64
+# endif
+# if !defined SCNxFAST64 || @PRI_MACROS_BROKEN@
+# undef SCNxFAST64
+# define SCNxFAST64 SCNx64
+# endif
+#endif
+
+#if !defined SCNdMAX || @PRI_MACROS_BROKEN@
+# undef SCNdMAX
+# if @INT32_MAX_LT_INTMAX_MAX@
+# define SCNdMAX SCNd64
+# else
+# define SCNdMAX "ld"
+# endif
+#endif
+#if !defined SCNiMAX || @PRI_MACROS_BROKEN@
+# undef SCNiMAX
+# if @INT32_MAX_LT_INTMAX_MAX@
+# define SCNiMAX SCNi64
+# else
+# define SCNiMAX "li"
+# endif
+#endif
+#if !defined SCNoMAX || @PRI_MACROS_BROKEN@
+# undef SCNoMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define SCNoMAX SCNo64
+# else
+# define SCNoMAX "lo"
+# endif
+#endif
+#if !defined SCNuMAX || @PRI_MACROS_BROKEN@
+# undef SCNuMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define SCNuMAX SCNu64
+# else
+# define SCNuMAX "lu"
+# endif
+#endif
+#if !defined SCNxMAX || @PRI_MACROS_BROKEN@
+# undef SCNxMAX
+# if @UINT32_MAX_LT_UINTMAX_MAX@
+# define SCNxMAX SCNx64
+# else
+# define SCNxMAX "lx"
+# endif
+#endif
+
+#if !defined SCNdPTR || @PRI_MACROS_BROKEN@
+# undef SCNdPTR
+# ifdef INTPTR_MAX
+# define SCNdPTR @PRIPTR_PREFIX@ "d"
+# endif
+#endif
+#if !defined SCNiPTR || @PRI_MACROS_BROKEN@
+# undef SCNiPTR
+# ifdef INTPTR_MAX
+# define SCNiPTR @PRIPTR_PREFIX@ "i"
+# endif
+#endif
+#if !defined SCNoPTR || @PRI_MACROS_BROKEN@
+# undef SCNoPTR
+# ifdef UINTPTR_MAX
+# define SCNoPTR @PRIPTR_PREFIX@ "o"
+# endif
+#endif
+#if !defined SCNuPTR || @PRI_MACROS_BROKEN@
+# undef SCNuPTR
+# ifdef UINTPTR_MAX
+# define SCNuPTR @PRIPTR_PREFIX@ "u"
+# endif
+#endif
+#if !defined SCNxPTR || @PRI_MACROS_BROKEN@
+# undef SCNxPTR
+# ifdef UINTPTR_MAX
+# define SCNxPTR @PRIPTR_PREFIX@ "x"
+# endif
+#endif
+
+/* 7.8.2 Functions for greatest-width integer types */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if @GNULIB_IMAXABS@
+# if !@HAVE_DECL_IMAXABS@
+extern intmax_t imaxabs (intmax_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef imaxabs
+# if HAVE_RAW_DECL_IMAXABS
+_GL_WARN_ON_USE (imaxabs, "imaxabs is unportable - "
+ "use gnulib module imaxabs for portability");
+# endif
+#endif
+
+#if @GNULIB_IMAXDIV@
+# if !@HAVE_IMAXDIV_T@
+# if !GNULIB_defined_imaxdiv_t
+typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t;
+# define GNULIB_defined_imaxdiv_t 1
+# endif
+# endif
+# if !@HAVE_DECL_IMAXDIV@
+extern imaxdiv_t imaxdiv (intmax_t, intmax_t);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef imaxdiv
+# if HAVE_RAW_DECL_IMAXDIV
+_GL_WARN_ON_USE (imaxdiv, "imaxdiv is unportable - "
+ "use gnulib module imaxdiv for portability");
+# endif
+#endif
+
+#if @GNULIB_STRTOIMAX@
+# if @REPLACE_STRTOIMAX@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef strtoimax
+# define strtoimax rpl_strtoimax
+# endif
+_GL_FUNCDECL_RPL (strtoimax, intmax_t,
+ (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoimax, intmax_t, (const char *, char **, int));
+# else
+# if !@HAVE_DECL_STRTOIMAX@
+# undef strtoimax
+_GL_FUNCDECL_SYS (strtoimax, intmax_t,
+ (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtoimax, intmax_t, (const char *, char **, int));
+# endif
+_GL_CXXALIASWARN (strtoimax);
+#elif defined GNULIB_POSIXCHECK
+# undef strtoimax
+# if HAVE_RAW_DECL_STRTOIMAX
+_GL_WARN_ON_USE (strtoimax, "strtoimax is unportable - "
+ "use gnulib module strtoimax for portability");
+# endif
+#endif
+
+#if @GNULIB_STRTOUMAX@
+# if @REPLACE_STRTOUMAX@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef strtoumax
+# define strtoumax rpl_strtoumax
+# endif
+_GL_FUNCDECL_RPL (strtoumax, uintmax_t,
+ (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoumax, uintmax_t, (const char *, char **, int));
+# else
+# if !@HAVE_DECL_STRTOUMAX@
+# undef strtoumax
+_GL_FUNCDECL_SYS (strtoumax, uintmax_t,
+ (const char *, char **, int) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtoumax, uintmax_t, (const char *, char **, int));
+# endif
+_GL_CXXALIASWARN (strtoumax);
+#elif defined GNULIB_POSIXCHECK
+# undef strtoumax
+# if HAVE_RAW_DECL_STRTOUMAX
+_GL_WARN_ON_USE (strtoumax, "strtoumax is unportable - "
+ "use gnulib module strtoumax for portability");
+# endif
+#endif
+
+/* Don't bother defining or declaring wcstoimax and wcstoumax, since
+ wide-character functions like this are hardly ever useful. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined INTTYPES_H && !defined _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H */
diff --git a/lib/isblank.c b/lib/isblank.c
index df4b4aa..4899404 100644
--- a/lib/isblank.c
+++ b/lib/isblank.c
@@ -1,6 +1,6 @@
/* Test whether a character is a blank.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
diff --git a/lib/langinfo.in.h b/lib/langinfo.in.h
index 96c237a..e912cd3 100644
--- a/lib/langinfo.in.h
+++ b/lib/langinfo.in.h
@@ -1,5 +1,5 @@
/* Substitute for and wrapper around <langinfo.h>.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
@@ -16,7 +16,7 @@
/*
* POSIX <langinfo.h> for platforms that lack it or have an incomplete one.
- * <http://www.opengroup.org/onlinepubs/9699919799/basedefs/langinfo.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/langinfo.h.html>
*/
#ifndef _@GUARD_PREFIX@_LANGINFO_H
diff --git a/lib/lc-charset-dispatch.c b/lib/lc-charset-dispatch.c
new file mode 100644
index 0000000..79057d4
--- /dev/null
+++ b/lib/lc-charset-dispatch.c
@@ -0,0 +1,82 @@
+/* Dispatching based on the current locale's character encoding.
+ Copyright (C) 2018-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 Bruno Haible <bruno@clisp.org>, 2018. */
+
+#include <config.h>
+
+/* Specification. */
+#include "lc-charset-dispatch.h"
+
+#if GNULIB_defined_mbstate_t
+
+# include "localcharset.h"
+# include "streq.h"
+
+# if GNULIB_WCHAR_SINGLE
+/* When we know that the locale does not change, provide a speedup by
+ caching the value of locale_encoding_classification. */
+# define locale_encoding_classification_cached locale_encoding_classification
+# else
+/* By default, don't make assumptions, hence no caching. */
+# define locale_encoding_classification_uncached locale_encoding_classification
+# endif
+
+# if GNULIB_WCHAR_SINGLE
+static inline
+# endif
+enc_t
+locale_encoding_classification_uncached (void)
+{
+ const char *encoding = locale_charset ();
+ if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
+ return enc_utf8;
+ if (STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
+ return enc_eucjp;
+ if (STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
+ || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
+ || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
+ return enc_94;
+ if (STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
+ return enc_euctw;
+ if (STREQ_OPT (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
+ return enc_gb18030;
+ if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
+ return enc_sjis;
+ return enc_other;
+}
+
+# if GNULIB_WCHAR_SINGLE
+
+static int cached_locale_enc = -1;
+
+enc_t
+locale_encoding_classification_cached (void)
+{
+ if (cached_locale_enc < 0)
+ cached_locale_enc = locale_encoding_classification_uncached ();
+ return cached_locale_enc;
+}
+
+# endif
+
+#else
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
+
+#endif
diff --git a/lib/lc-charset-dispatch.h b/lib/lc-charset-dispatch.h
new file mode 100644
index 0000000..95c2316
--- /dev/null
+++ b/lib/lc-charset-dispatch.h
@@ -0,0 +1,40 @@
+/* Dispatching based on the current locale's character encoding.
+ Copyright (C) 2018-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 Bruno Haible <bruno@clisp.org>, 2018. */
+
+#include <wchar.h>
+
+#if GNULIB_defined_mbstate_t
+
+/* A classification of special values of the encoding of the current locale. */
+typedef enum
+ {
+ enc_other, /* other */
+ enc_utf8, /* UTF-8 */
+ enc_eucjp, /* EUC-JP */
+ enc_94, /* EUC-KR, GB2312, BIG5 */
+ enc_euctw, /* EUC-TW */
+ enc_gb18030, /* GB18030 */
+ enc_sjis /* SJIS */
+ }
+ enc_t;
+
+/* Returns a classification of special values of the encoding of the current
+ locale. */
+extern enc_t locale_encoding_classification (void);
+
+#endif
diff --git a/lib/libc-config.h b/lib/libc-config.h
index d7b4093..aef1f79 100644
--- a/lib/libc-config.h
+++ b/lib/libc-config.h
@@ -1,6 +1,6 @@
/* System definitions for code taken from the GNU C Library
- Copyright 2017-2018 Free Software Foundation, Inc.
+ Copyright 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
diff --git a/lib/limits.in.h b/lib/limits.in.h
index 89d7195..90c273f 100644
--- a/lib/limits.in.h
+++ b/lib/limits.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <limits.h>.
- Copyright 2016-2018 Free Software Foundation, Inc.
+ Copyright 2016-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
diff --git a/lib/local.mk b/lib/local.mk
index 1ef14b4..5deae8a 100644
--- a/lib/local.mk
+++ b/lib/local.mk
@@ -1,4 +1,4 @@
-# Copyright 1997-2018 Free Software Foundation, Inc.
+# Copyright 1997-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
diff --git a/lib/localcharset.c b/lib/localcharset.c
index 58c5718..721c8a9 100644
--- a/lib/localcharset.c
+++ b/lib/localcharset.c
@@ -1,6 +1,6 @@
/* Determine a canonical name for the current locale's character encoding.
- Copyright (C) 2000-2006, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2000-2006, 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
@@ -58,6 +58,9 @@
#elif defined WINDOWS_NATIVE
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
+ /* For the use of setlocale() below, the Gnulib override in setlocale.c is
+ not needed; see the platform lists in setlocale_null.m4. */
+# undef setlocale
#endif
#if defined OS2
# define INCL_DOS
@@ -150,7 +153,8 @@ static const struct table_entry alias_table[] =
{ "ISO8859-2", "ISO-8859-2" },
{ "ISO8859-4", "ISO-8859-4" },
{ "ISO8859-5", "ISO-8859-5" },
- { "ISO8859-7", "ISO-8859-7" }
+ { "ISO8859-7", "ISO-8859-7" },
+ { "US-ASCII", "ASCII" }
# define alias_table_defined
# endif
# if defined __APPLE__ && defined __MACH__ /* Mac OS X */
@@ -377,27 +381,164 @@ static const struct table_entry alias_table[] =
/* The list of encodings is taken from "List of OS/2 Codepages"
by Alex Taylor:
<http://altsan.org/os2/toolkits/uls/index.html#codepages>.
- See also "IBM Globalization - Code page identifiers":
- <https://www-01.ibm.com/software/globalization/cp/cp_cpgid.html>. */
- { "CP1089", "ISO-8859-6" },
- { "CP1208", "UTF-8" },
- { "CP1381", "GB2312" },
- { "CP1386", "GBK" },
- { "CP3372", "EUC-JP" },
- { "CP813", "ISO-8859-7" },
- { "CP819", "ISO-8859-1" },
- { "CP878", "KOI8-R" },
- { "CP912", "ISO-8859-2" },
- { "CP913", "ISO-8859-3" },
- { "CP914", "ISO-8859-4" },
- { "CP915", "ISO-8859-5" },
- { "CP916", "ISO-8859-8" },
- { "CP920", "ISO-8859-9" },
- { "CP921", "ISO-8859-13" },
- { "CP923", "ISO-8859-15" },
- { "CP954", "EUC-JP" },
- { "CP964", "EUC-TW" },
- { "CP970", "EUC-KR" }
+ See also "__convcp() of kLIBC":
+ <https://github.com/bitwiseworks/libc/blob/master/src/emx/src/lib/locale/__convcp.c>. */
+ { "CP1004", "CP1252" },
+ /*{ "CP1041", "CP943" },*/
+ /*{ "CP1088", "CP949" },*/
+ { "CP1089", "ISO-8859-6" },
+ /*{ "CP1114", "CP950" },*/
+ /*{ "CP1115", "GB2312" },*/
+ { "CP1208", "UTF-8" },
+ /*{ "CP1380", "GB2312" },*/
+ { "CP1381", "GB2312" },
+ { "CP1383", "GB2312" },
+ { "CP1386", "GBK" },
+ /*{ "CP301", "CP943" },*/
+ { "CP3372", "EUC-JP" },
+ { "CP4946", "CP850" },
+ /*{ "CP5048", "JIS_X0208-1990" },*/
+ /*{ "CP5049", "JIS_X0212-1990" },*/
+ /*{ "CP5067", "KS_C_5601-1987" },*/
+ { "CP813", "ISO-8859-7" },
+ { "CP819", "ISO-8859-1" },
+ { "CP878", "KOI8-R" },
+ /*{ "CP897", "CP943" },*/
+ { "CP912", "ISO-8859-2" },
+ { "CP913", "ISO-8859-3" },
+ { "CP914", "ISO-8859-4" },
+ { "CP915", "ISO-8859-5" },
+ { "CP916", "ISO-8859-8" },
+ { "CP920", "ISO-8859-9" },
+ { "CP921", "ISO-8859-13" },
+ { "CP923", "ISO-8859-15" },
+ /*{ "CP941", "CP943" },*/
+ /*{ "CP947", "CP950" },*/
+ /*{ "CP951", "CP949" },*/
+ /*{ "CP952", "JIS_X0208-1990" },*/
+ /*{ "CP953", "JIS_X0212-1990" },*/
+ { "CP954", "EUC-JP" },
+ { "CP964", "EUC-TW" },
+ { "CP970", "EUC-KR" },
+ /*{ "CP971", "KS_C_5601-1987" },*/
+ { "IBM-1004", "CP1252" },
+ /*{ "IBM-1006", "?" },*/
+ /*{ "IBM-1008", "?" },*/
+ /*{ "IBM-1041", "CP943" },*/
+ /*{ "IBM-1051", "?" },*/
+ /*{ "IBM-1088", "CP949" },*/
+ { "IBM-1089", "ISO-8859-6" },
+ /*{ "IBM-1098", "?" },*/
+ /*{ "IBM-1114", "CP950" },*/
+ /*{ "IBM-1115", "GB2312" },*/
+ /*{ "IBM-1116", "?" },*/
+ /*{ "IBM-1117", "?" },*/
+ /*{ "IBM-1118", "?" },*/
+ /*{ "IBM-1119", "?" },*/
+ { "IBM-1124", "CP1124" },
+ { "IBM-1125", "CP1125" },
+ { "IBM-1131", "CP1131" },
+ { "IBM-1208", "UTF-8" },
+ { "IBM-1250", "CP1250" },
+ { "IBM-1251", "CP1251" },
+ { "IBM-1252", "CP1252" },
+ { "IBM-1253", "CP1253" },
+ { "IBM-1254", "CP1254" },
+ { "IBM-1255", "CP1255" },
+ { "IBM-1256", "CP1256" },
+ { "IBM-1257", "CP1257" },
+ /*{ "IBM-1275", "?" },*/
+ /*{ "IBM-1276", "?" },*/
+ /*{ "IBM-1277", "?" },*/
+ /*{ "IBM-1280", "?" },*/
+ /*{ "IBM-1281", "?" },*/
+ /*{ "IBM-1282", "?" },*/
+ /*{ "IBM-1283", "?" },*/
+ /*{ "IBM-1380", "GB2312" },*/
+ { "IBM-1381", "GB2312" },
+ { "IBM-1383", "GB2312" },
+ { "IBM-1386", "GBK" },
+ /*{ "IBM-301", "CP943" },*/
+ { "IBM-3372", "EUC-JP" },
+ { "IBM-367", "ASCII" },
+ { "IBM-437", "CP437" },
+ { "IBM-4946", "CP850" },
+ /*{ "IBM-5048", "JIS_X0208-1990" },*/
+ /*{ "IBM-5049", "JIS_X0212-1990" },*/
+ /*{ "IBM-5067", "KS_C_5601-1987" },*/
+ { "IBM-813", "ISO-8859-7" },
+ { "IBM-819", "ISO-8859-1" },
+ { "IBM-850", "CP850" },
+ /*{ "IBM-851", "?" },*/
+ { "IBM-852", "CP852" },
+ { "IBM-855", "CP855" },
+ { "IBM-856", "CP856" },
+ { "IBM-857", "CP857" },
+ /*{ "IBM-859", "?" },*/
+ { "IBM-860", "CP860" },
+ { "IBM-861", "CP861" },
+ { "IBM-862", "CP862" },
+ { "IBM-863", "CP863" },
+ { "IBM-864", "CP864" },
+ { "IBM-865", "CP865" },
+ { "IBM-866", "CP866" },
+ /*{ "IBM-868", "?" },*/
+ { "IBM-869", "CP869" },
+ { "IBM-874", "CP874" },
+ { "IBM-878", "KOI8-R" },
+ /*{ "IBM-895", "?" },*/
+ /*{ "IBM-897", "CP943" },*/
+ /*{ "IBM-907", "?" },*/
+ /*{ "IBM-909", "?" },*/
+ { "IBM-912", "ISO-8859-2" },
+ { "IBM-913", "ISO-8859-3" },
+ { "IBM-914", "ISO-8859-4" },
+ { "IBM-915", "ISO-8859-5" },
+ { "IBM-916", "ISO-8859-8" },
+ { "IBM-920", "ISO-8859-9" },
+ { "IBM-921", "ISO-8859-13" },
+ { "IBM-922", "CP922" },
+ { "IBM-923", "ISO-8859-15" },
+ { "IBM-932", "CP932" },
+ /*{ "IBM-941", "CP943" },*/
+ /*{ "IBM-942", "?" },*/
+ { "IBM-943", "CP943" },
+ /*{ "IBM-947", "CP950" },*/
+ { "IBM-949", "CP949" },
+ { "IBM-950", "CP950" },
+ /*{ "IBM-951", "CP949" },*/
+ /*{ "IBM-952", "JIS_X0208-1990" },*/
+ /*{ "IBM-953", "JIS_X0212-1990" },*/
+ { "IBM-954", "EUC-JP" },
+ /*{ "IBM-955", "?" },*/
+ { "IBM-964", "EUC-TW" },
+ { "IBM-970", "EUC-KR" },
+ /*{ "IBM-971", "KS_C_5601-1987" },*/
+ { "IBM-eucCN", "GB2312" },
+ { "IBM-eucJP", "EUC-JP" },
+ { "IBM-eucKR", "EUC-KR" },
+ { "IBM-eucTW", "EUC-TW" },
+ { "IBM33722", "EUC-JP" },
+ { "ISO8859-1", "ISO-8859-1" },
+ { "ISO8859-2", "ISO-8859-2" },
+ { "ISO8859-3", "ISO-8859-3" },
+ { "ISO8859-4", "ISO-8859-4" },
+ { "ISO8859-5", "ISO-8859-5" },
+ { "ISO8859-6", "ISO-8859-6" },
+ { "ISO8859-7", "ISO-8859-7" },
+ { "ISO8859-8", "ISO-8859-8" },
+ { "ISO8859-9", "ISO-8859-9" },
+ /*{ "JISX0201-1976", "JISX0201-1976" },*/
+ /*{ "JISX0208-1978", "?" },*/
+ /*{ "JISX0208-1983", "JIS_X0208-1983" },*/
+ /*{ "JISX0208-1990", "JIS_X0208-1990" },*/
+ /*{ "JISX0212-1990", "JIS_X0212-1990" },*/
+ /*{ "KSC5601-1987", "KS_C_5601-1987" },*/
+ { "SJIS-1", "CP943" },
+ { "SJIS-2", "CP943" },
+ { "eucJP", "EUC-JP" },
+ { "eucKR", "EUC-KR" },
+ { "eucTW-1993", "EUC-TW" }
# define alias_table_defined
# endif
# if defined VMS /* OpenVMS */
@@ -675,8 +816,11 @@ static const struct table_entry locale_table[] =
/* Determine the current locale's character encoding, and canonicalize it
- into one of the canonical names listed in localcharset.h.
- The result must not be freed; it is statically allocated.
+ into one of the canonical names listed below.
+ The result must not be freed; it is statically allocated. The result
+ becomes invalid when setlocale() is used to change the global locale, or
+ when the value of one of the environment variables LC_ALL, LC_CTYPE, LANG
+ is changed; threads in multithreaded programs should not do this.
If the canonical name cannot be determined, the result is a non-canonical
name. */
@@ -688,6 +832,13 @@ locale_charset (void)
{
const char *codeset;
+ /* This function must be multithread-safe. To achieve this without using
+ thread-local storage, we use a simple strcpy or memcpy to fill this static
+ buffer. Filling it through, for example, strcpy + strcat would not be
+ guaranteed to leave the buffer's contents intact if another thread is
+ currently accessing it. If necessary, the contents is first assembled in
+ a stack-allocated buffer. */
+
#if HAVE_LANGINFO_CODESET || defined WINDOWS_NATIVE || defined OS2
# if HAVE_LANGINFO_CODESET
@@ -702,7 +853,7 @@ locale_charset (void)
if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
{
const char *locale;
- static char buf[2 + 10 + 1];
+ static char resultbuf[2 + 10 + 1];
locale = getenv ("LC_ALL");
if (locale == NULL || locale[0] == '\0')
@@ -726,11 +877,12 @@ locale_charset (void)
modifier = strchr (dot, '@');
if (modifier == NULL)
return dot;
- if (modifier - dot < sizeof (buf))
+ if (modifier - dot < sizeof (resultbuf))
{
- memcpy (buf, dot, modifier - dot);
- buf [modifier - dot] = '\0';
- return buf;
+ /* This way of filling resultbuf is multithread-safe. */
+ memcpy (resultbuf, dot, modifier - dot);
+ resultbuf [modifier - dot] = '\0';
+ return resultbuf;
}
}
}
@@ -746,8 +898,13 @@ locale_charset (void)
converting to GetConsoleOutputCP(). This leads to correct results,
except when SetConsoleOutputCP has been called and a raster font is
in use. */
- sprintf (buf, "CP%u", GetACP ());
- codeset = buf;
+ {
+ char buf[2 + 10 + 1];
+
+ sprintf (buf, "CP%u", GetACP ());
+ strcpy (resultbuf, buf);
+ codeset = resultbuf;
+ }
}
# endif
@@ -757,42 +914,44 @@ locale_charset (void)
# elif defined WINDOWS_NATIVE
- static char buf[2 + 10 + 1];
+ char buf[2 + 10 + 1];
+ static char resultbuf[2 + 10 + 1];
/* The Windows API has a function returning the locale's codepage as
a number, but the value doesn't change according to what the
'setlocale' call specified. So we use it as a last resort, in
case the string returned by 'setlocale' doesn't specify the
codepage. */
- char *current_locale = setlocale (LC_ALL, NULL);
- char *pdot;
+ char *current_locale = setlocale (LC_CTYPE, NULL);
+ char *pdot = strrchr (current_locale, '.');
- /* If they set different locales for different categories,
- 'setlocale' will return a semi-colon separated list of locale
- values. To make sure we use the correct one, we choose LC_CTYPE. */
- if (strchr (current_locale, ';'))
- current_locale = setlocale (LC_CTYPE, NULL);
-
- pdot = strrchr (current_locale, '.');
if (pdot && 2 + strlen (pdot + 1) + 1 <= sizeof (buf))
sprintf (buf, "CP%s", pdot + 1);
else
{
/* The Windows API has a function returning the locale's codepage as a
- number: GetACP().
- When the output goes to a console window, it needs to be provided in
- GetOEMCP() encoding if the console is using a raster font, or in
- GetConsoleOutputCP() encoding if it is using a TrueType font.
- But in GUI programs and for output sent to files and pipes, GetACP()
- encoding is the best bet. */
+ number: GetACP().
+ When the output goes to a console window, it needs to be provided in
+ GetOEMCP() encoding if the console is using a raster font, or in
+ GetConsoleOutputCP() encoding if it is using a TrueType font.
+ But in GUI programs and for output sent to files and pipes, GetACP()
+ encoding is the best bet. */
sprintf (buf, "CP%u", GetACP ());
}
- codeset = buf;
+ /* For a locale name such as "French_France.65001", in Windows 10,
+ setlocale now returns "French_France.utf8" instead. */
+ if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0)
+ codeset = "UTF-8";
+ else
+ {
+ strcpy (resultbuf, buf);
+ codeset = resultbuf;
+ }
# elif defined OS2
const char *locale;
- static char buf[2 + 10 + 1];
+ static char resultbuf[2 + 10 + 1];
ULONG cp[3];
ULONG cplen;
@@ -821,11 +980,12 @@ locale_charset (void)
modifier = strchr (dot, '@');
if (modifier == NULL)
return dot;
- if (modifier - dot < sizeof (buf))
+ if (modifier - dot < sizeof (resultbuf))
{
- memcpy (buf, dot, modifier - dot);
- buf [modifier - dot] = '\0';
- return buf;
+ /* This way of filling resultbuf is multithread-safe. */
+ memcpy (resultbuf, dot, modifier - dot);
+ resultbuf [modifier - dot] = '\0';
+ return resultbuf;
}
}
@@ -841,8 +1001,11 @@ locale_charset (void)
codeset = "";
else
{
+ char buf[2 + 10 + 1];
+
sprintf (buf, "CP%u", cp[0]);
- codeset = buf;
+ strcpy (resultbuf, buf);
+ codeset = resultbuf;
}
}
diff --git a/lib/localcharset.h b/lib/localcharset.h
index e4ba296..aa623be 100644
--- a/lib/localcharset.h
+++ b/lib/localcharset.h
@@ -1,5 +1,5 @@
/* Determine a canonical name for the current locale's character encoding.
- Copyright (C) 2000-2003, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2000-2003, 2009-2020 Free Software Foundation, Inc.
This file is part of the GNU CHARSET Library.
This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,10 @@ extern "C" {
/* Determine the current locale's character encoding, and canonicalize it
into one of the canonical names listed below.
- The result must not be freed; it is statically allocated.
+ The result must not be freed; it is statically allocated. The result
+ becomes invalid when setlocale() is used to change the global locale, or
+ when the value of one of the environment variables LC_ALL, LC_CTYPE, LANG
+ is changed; threads in multithreaded programs should not do this.
If the canonical name cannot be determined, the result is a non-canonical
name. */
extern const char * locale_charset (void);
@@ -45,15 +48,15 @@ extern const char * locale_charset (void);
(darwin = Mac OS X, windows = native Windows)
ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin minix cygwin
- ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
- ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+ ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
+ ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
ISO-8859-3 Y glibc solaris cygwin
ISO-8859-4 Y hpux osf solaris freebsd netbsd openbsd darwin
- ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+ ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
ISO-8859-6 Y glibc aix hpux solaris cygwin
- ISO-8859-7 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
- ISO-8859-8 Y glibc aix hpux osf solaris cygwin
- ISO-8859-9 Y glibc aix hpux irix osf solaris freebsd darwin cygwin
+ ISO-8859-7 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos
+ ISO-8859-8 Y glibc aix hpux osf solaris cygwin zos
+ ISO-8859-9 Y glibc aix hpux irix osf solaris freebsd darwin cygwin zos
ISO-8859-13 glibc hpux solaris freebsd netbsd openbsd darwin cygwin
ISO-8859-14 glibc cygwin
ISO-8859-15 glibc aix irix osf solaris freebsd netbsd openbsd darwin cygwin
@@ -76,7 +79,7 @@ extern const char * locale_charset (void);
CP874 windows dos
CP922 aix
CP932 aix cygwin windows dos
- CP943 aix
+ CP943 aix zos
CP949 osf darwin windows dos
CP950 windows dos
CP1046 aix
@@ -92,17 +95,17 @@ extern const char * locale_charset (void);
CP1255 glibc windows
CP1256 windows
CP1257 windows
- GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin cygwin
+ GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin cygwin zos
EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
- EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
+ EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin zos
EUC-TW glibc aix hpux irix osf solaris netbsd
- BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin
+ BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin zos
BIG5-HKSCS glibc hpux solaris netbsd darwin
GBK glibc aix osf solaris freebsd darwin cygwin windows dos
GB18030 glibc hpux solaris freebsd netbsd darwin
SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin
JOHAB glibc solaris windows
- TIS-620 glibc aix hpux osf solaris cygwin
+ TIS-620 glibc aix hpux osf solaris cygwin zos
VISCII Y glibc
TCVN5712-1 glibc
ARMSCII-8 glibc freebsd netbsd darwin
@@ -116,7 +119,7 @@ extern const char * locale_charset (void);
HP-KANA8 hpux
DEC-KANJI osf
DEC-HANYU osf
- UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin
+ UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin zos
Note: Names which are not marked as being a MIME name should not be used in
Internet protocols for information interchange (mail, news, etc.).
diff --git a/lib/locale.in.h b/lib/locale.in.h
index 123df7a..4e9b3f3 100644
--- a/lib/locale.in.h
+++ b/lib/locale.in.h
@@ -1,5 +1,5 @@
/* A POSIX <locale.h>.
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
@@ -64,6 +64,18 @@
# define LC_MESSAGES 1729
#endif
+/* On native Windows with MSVC, 'struct lconv' lacks the members int_p_* and
+ int_n_*. Instead of overriding 'struct lconv', merely define these member
+ names as macros. This avoids trouble in C++ mode. */
+#if defined _MSC_VER
+# define int_p_cs_precedes p_cs_precedes
+# define int_p_sign_posn p_sign_posn
+# define int_p_sep_by_space p_sep_by_space
+# define int_n_cs_precedes n_cs_precedes
+# define int_n_sign_posn n_sign_posn
+# define int_n_sep_by_space n_sep_by_space
+#endif
+
/* Bionic libc's 'struct lconv' is just a dummy. */
#if @REPLACE_STRUCT_LCONV@
# define lconv rpl_lconv
@@ -72,7 +84,7 @@ struct lconv
/* All 'char *' are actually 'const char *'. */
/* Members that depend on the LC_NUMERIC category of the locale. See
- <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_04> */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_04> */
/* Symbol used as decimal point. */
char *decimal_point;
@@ -84,7 +96,7 @@ struct lconv
char *grouping;
/* Members that depend on the LC_MONETARY category of the locale. See
- <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03> */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03> */
/* Symbol used as decimal point. */
char *mon_decimal_point;
@@ -156,7 +168,9 @@ _GL_CXXALIAS_RPL (localeconv, struct lconv *, (void));
# else
_GL_CXXALIAS_SYS (localeconv, struct lconv *, (void));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (localeconv);
+# endif
#elif @REPLACE_STRUCT_LCONV@
# undef localeconv
# define localeconv localeconv_used_without_requesting_gnulib_module_localeconv
@@ -181,7 +195,9 @@ _GL_CXXALIAS_RPL (setlocale, char *, (int category, const char *locale));
# else
_GL_CXXALIAS_SYS (setlocale, char *, (int category, const char *locale));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (setlocale);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef setlocale
# if HAVE_RAW_DECL_SETLOCALE
@@ -190,6 +206,11 @@ _GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - "
# endif
#endif
+#if @GNULIB_SETLOCALE_NULL@
+/* Included here for convenience. */
+# include "setlocale_null.h"
+#endif
+
#if /*@GNULIB_NEWLOCALE@ ||*/ (@GNULIB_LOCALENAME@ && @HAVE_NEWLOCALE@)
# if @REPLACE_NEWLOCALE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -211,6 +232,11 @@ _GL_CXXALIAS_SYS (newlocale, locale_t,
# if @HAVE_NEWLOCALE@
_GL_CXXALIASWARN (newlocale);
# endif
+# if @HAVE_NEWLOCALE@ || @REPLACE_NEWLOCALE@
+# ifndef HAVE_WORKING_NEWLOCALE
+# define HAVE_WORKING_NEWLOCALE 1
+# endif
+# endif
#elif defined GNULIB_POSIXCHECK
# undef newlocale
# if HAVE_RAW_DECL_NEWLOCALE
@@ -235,6 +261,11 @@ _GL_CXXALIAS_SYS (duplocale, locale_t, (locale_t locale));
# if @HAVE_DUPLOCALE@
_GL_CXXALIASWARN (duplocale);
# endif
+# if @HAVE_DUPLOCALE@ || @REPLACE_DUPLOCALE@
+# ifndef HAVE_WORKING_DUPLOCALE
+# define HAVE_WORKING_DUPLOCALE 1
+# endif
+# endif
#elif defined GNULIB_POSIXCHECK
# undef duplocale
# if HAVE_RAW_DECL_DUPLOCALE
@@ -254,7 +285,9 @@ _GL_FUNCDECL_RPL (freelocale, void, (locale_t locale) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (freelocale, void, (locale_t locale));
# else
# if @HAVE_FREELOCALE@
-_GL_CXXALIAS_SYS (freelocale, void, (locale_t locale));
+/* Need to cast, because on FreeBSD and Mac OS X 10.13, the return type is
+ int. */
+_GL_CXXALIAS_SYS_CAST (freelocale, void, (locale_t locale));
# endif
# endif
# if @HAVE_FREELOCALE@
diff --git a/lib/localeconv.c b/lib/localeconv.c
index 87cface..8aa9bbe 100644
--- a/lib/localeconv.c
+++ b/lib/localeconv.c
@@ -1,5 +1,5 @@
/* Query locale dependent information for formatting numbers.
- Copyright (C) 2012-2018 Free Software Foundation, Inc.
+ Copyright (C) 2012-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
diff --git a/lib/localeinfo.c b/lib/localeinfo.c
index 4fdeeb4..a6dfaf8 100644
--- a/lib/localeinfo.c
+++ b/lib/localeinfo.c
@@ -1,6 +1,6 @@
/* locale information
- Copyright 2016-2018 Free Software Foundation, Inc.
+ Copyright 2016-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
@@ -44,17 +44,55 @@ is_using_utf8 (void)
return mbrtowc (&wc, "\xc4\x80", 2, &mbs) == 2 && wc == 0x100;
}
+/* Return true if the locale is compatible enough with the C locale so
+ that the locale is single-byte, bytes are in collating-sequence
+ order, and there are no multi-character collating elements. */
+
+static bool
+using_simple_locale (bool multibyte)
+{
+ /* The native character set is known to be compatible with
+ the C locale. The following test isn't perfect, but it's good
+ enough in practice, as only ASCII and EBCDIC are in common use
+ and this test correctly accepts ASCII and rejects EBCDIC. */
+ enum { native_c_charset =
+ ('\b' == 8 && '\t' == 9 && '\n' == 10 && '\v' == 11 && '\f' == 12
+ && '\r' == 13 && ' ' == 32 && '!' == 33 && '"' == 34 && '#' == 35
+ && '%' == 37 && '&' == 38 && '\'' == 39 && '(' == 40 && ')' == 41
+ && '*' == 42 && '+' == 43 && ',' == 44 && '-' == 45 && '.' == 46
+ && '/' == 47 && '0' == 48 && '9' == 57 && ':' == 58 && ';' == 59
+ && '<' == 60 && '=' == 61 && '>' == 62 && '?' == 63 && 'A' == 65
+ && 'Z' == 90 && '[' == 91 && '\\' == 92 && ']' == 93 && '^' == 94
+ && '_' == 95 && 'a' == 97 && 'z' == 122 && '{' == 123 && '|' == 124
+ && '}' == 125 && '~' == 126)
+ };
+
+ if (!native_c_charset || multibyte)
+ return false;
+
+ /* As a heuristic, use strcoll to compare native character order.
+ If this agrees with byte order the locale should be simple.
+ This heuristic should work for all known practical locales,
+ although it would be invalid for artificially-constructed locales
+ where the native order is the collating-sequence order but there
+ are multi-character collating elements. */
+ for (int i = 0; i < UCHAR_MAX; i++)
+ if (0 <= strcoll (((char []) {i, 0}), ((char []) {i + 1, 0})))
+ return false;
+
+ return true;
+}
+
/* Initialize *LOCALEINFO from the current locale. */
void
init_localeinfo (struct localeinfo *localeinfo)
{
- int i;
-
localeinfo->multibyte = MB_CUR_MAX > 1;
+ localeinfo->simple = using_simple_locale (localeinfo->multibyte);
localeinfo->using_utf8 = is_using_utf8 ();
- for (i = CHAR_MIN; i <= CHAR_MAX; i++)
+ for (int i = CHAR_MIN; i <= CHAR_MAX; i++)
{
char c = i;
unsigned char uc = i;
diff --git a/lib/localeinfo.h b/lib/localeinfo.h
index fcd5311..16f5129 100644
--- a/lib/localeinfo.h
+++ b/lib/localeinfo.h
@@ -1,6 +1,6 @@
/* locale information
- Copyright 2016-2018 Free Software Foundation, Inc.
+ Copyright 2016-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
@@ -28,6 +28,12 @@ struct localeinfo
/* MB_CUR_MAX > 1. */
bool multibyte;
+ /* The locale is simple, like the C locale. These locales can be
+ processed more efficiently, as they are single-byte, their native
+ character set is in collating-sequence order, and they do not
+ have multi-character collating elements. */
+ bool simple;
+
/* The locale uses UTF-8. */
bool using_utf8;
diff --git a/lib/localtime-buffer.c b/lib/localtime-buffer.c
index 910c8bc..141849c 100644
--- a/lib/localtime-buffer.c
+++ b/lib/localtime-buffer.c
@@ -1,6 +1,6 @@
/* Provide access to the last buffer returned by localtime() or gmtime().
- Copyright (C) 2001-2003, 2005-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2007, 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
diff --git a/lib/localtime-buffer.h b/lib/localtime-buffer.h
index f381ff0..3801742 100644
--- a/lib/localtime-buffer.h
+++ b/lib/localtime-buffer.h
@@ -1,6 +1,6 @@
/* Provide access to the last buffer returned by localtime() or gmtime().
- Copyright (C) 2001-2003, 2005-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2007, 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
diff --git a/lib/lstat.c b/lib/lstat.c
index 5873bbd..f74392b 100644
--- a/lib/lstat.c
+++ b/lib/lstat.c
@@ -1,6 +1,6 @@
/* Work around a bug of lstat on some systems
- Copyright (C) 1997-2006, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 1997-2006, 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
@@ -42,10 +42,14 @@ orig_lstat (const char *filename, struct stat *buf)
}
/* Specification. */
+# ifdef __osf__
/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
eliminates this include because of the preliminary #include <sys/stat.h>
above. */
-# include "sys/stat.h"
+# include "sys/stat.h"
+# else
+# include <sys/stat.h>
+# endif
# include "stat-time.h"
diff --git a/lib/malloc.c b/lib/malloc.c
index 471c3ab..7232f1e 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -1,6 +1,6 @@
/* malloc() function that is glibc compatible.
- Copyright (C) 1997-1998, 2006-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1997-1998, 2006-2007, 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
diff --git a/lib/malloca.c b/lib/malloca.c
index c54e1e0..975b166 100644
--- a/lib/malloca.c
+++ b/lib/malloca.c
@@ -1,5 +1,5 @@
/* Safe automatic memory allocation.
- Copyright (C) 2003, 2006-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2006-2007, 2009-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003, 2018.
This program is free software; you can redistribute it and/or modify
diff --git a/lib/malloca.h b/lib/malloca.h
index 1e47813..cfcd4de 100644
--- a/lib/malloca.h
+++ b/lib/malloca.h
@@ -1,5 +1,5 @@
/* Safe automatic memory allocation.
- Copyright (C) 2003-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2003-2007, 2009-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2003.
This program is free software; you can redistribute it and/or modify
@@ -112,14 +112,10 @@ enum
among all elementary types. */
sa_alignment_long = sa_alignof (long),
sa_alignment_double = sa_alignof (double),
-#if HAVE_LONG_LONG_INT
sa_alignment_longlong = sa_alignof (long long),
-#endif
sa_alignment_longdouble = sa_alignof (long double),
sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
-#if HAVE_LONG_LONG_INT
| (sa_alignment_longlong - 1)
-#endif
| (sa_alignment_longdouble - 1)
) + 1
};
diff --git a/lib/mbrlen.c b/lib/mbrlen.c
index 2812a2e..cacc9c8 100644
--- a/lib/mbrlen.c
+++ b/lib/mbrlen.c
@@ -1,5 +1,5 @@
/* Recognize multibyte character.
- Copyright (C) 1999-2000, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2000, 2008-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/mbrtowc-impl-utf8.h b/lib/mbrtowc-impl-utf8.h
new file mode 100644
index 0000000..a826b1b
--- /dev/null
+++ b/lib/mbrtowc-impl-utf8.h
@@ -0,0 +1,138 @@
+/* Convert multibyte character to wide character.
+ Copyright (C) 1999-2002, 2005-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 Bruno Haible <bruno@clisp.org>, 2008. */
+
+/* This file contains the part of the body of the mbrtowc and mbrtoc32 functions
+ that handles the special case of the UTF-8 encoding. */
+
+ /* Cf. unistr/u8-mbtouc.c. */
+ unsigned char c = (unsigned char) p[0];
+
+ if (c < 0x80)
+ {
+ if (pwc != NULL)
+ *pwc = c;
+ res = (c == 0 ? 0 : 1);
+ goto success;
+ }
+ if (c >= 0xc2)
+ {
+ if (c < 0xe0)
+ {
+ if (m == 1)
+ goto incomplete;
+ else /* m >= 2 */
+ {
+ unsigned char c2 = (unsigned char) p[1];
+
+ if ((c2 ^ 0x80) < 0x40)
+ {
+ if (pwc != NULL)
+ *pwc = ((unsigned int) (c & 0x1f) << 6)
+ | (unsigned int) (c2 ^ 0x80);
+ res = 2;
+ goto success;
+ }
+ }
+ }
+ else if (c < 0xf0)
+ {
+ if (m == 1)
+ goto incomplete;
+ else
+ {
+ unsigned char c2 = (unsigned char) p[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xe1 || c2 >= 0xa0)
+ && (c != 0xed || c2 < 0xa0))
+ {
+ if (m == 2)
+ goto incomplete;
+ else /* m >= 3 */
+ {
+ unsigned char c3 = (unsigned char) p[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ unsigned int wc =
+ (((unsigned int) (c & 0x0f) << 12)
+ | ((unsigned int) (c2 ^ 0x80) << 6)
+ | (unsigned int) (c3 ^ 0x80));
+
+ if (FITS_IN_CHAR_TYPE (wc))
+ {
+ if (pwc != NULL)
+ *pwc = wc;
+ res = 3;
+ goto success;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (c <= 0xf4)
+ {
+ if (m == 1)
+ goto incomplete;
+ else
+ {
+ unsigned char c2 = (unsigned char) p[1];
+
+ if ((c2 ^ 0x80) < 0x40
+ && (c >= 0xf1 || c2 >= 0x90)
+ && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ {
+ if (m == 2)
+ goto incomplete;
+ else
+ {
+ unsigned char c3 = (unsigned char) p[2];
+
+ if ((c3 ^ 0x80) < 0x40)
+ {
+ if (m == 3)
+ goto incomplete;
+ else /* m >= 4 */
+ {
+ unsigned char c4 = (unsigned char) p[3];
+
+ if ((c4 ^ 0x80) < 0x40)
+ {
+ unsigned int wc =
+ (((unsigned int) (c & 0x07) << 18)
+ | ((unsigned int) (c2 ^ 0x80) << 12)
+ | ((unsigned int) (c3 ^ 0x80) << 6)
+ | (unsigned int) (c4 ^ 0x80));
+
+ if (FITS_IN_CHAR_TYPE (wc))
+ {
+ if (pwc != NULL)
+ *pwc = wc;
+ res = 4;
+ goto success;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ goto invalid;
diff --git a/lib/mbrtowc-impl.h b/lib/mbrtowc-impl.h
new file mode 100644
index 0000000..c970439
--- /dev/null
+++ b/lib/mbrtowc-impl.h
@@ -0,0 +1,262 @@
+/* Convert multibyte character to wide character.
+ Copyright (C) 1999-2002, 2005-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 Bruno Haible <bruno@clisp.org>, 2008. */
+
+/* This file contains the body of the mbrtowc and mbrtoc32 functions,
+ when GNULIB_defined_mbstate_t is defined. */
+
+ char *pstate = (char *)ps;
+
+ if (s == NULL)
+ {
+ pwc = NULL;
+ s = "";
+ n = 1;
+ }
+
+ if (n == 0)
+ return (size_t)(-2);
+
+ /* Here n > 0. */
+
+ if (pstate == NULL)
+ pstate = internal_state;
+
+ {
+ size_t nstate = pstate[0];
+ char buf[4];
+ const char *p;
+ size_t m;
+ enc_t enc;
+ int res;
+
+ switch (nstate)
+ {
+ case 0:
+ p = s;
+ m = n;
+ break;
+ case 3:
+ buf[2] = pstate[3];
+ FALLTHROUGH;
+ case 2:
+ buf[1] = pstate[2];
+ FALLTHROUGH;
+ case 1:
+ buf[0] = pstate[1];
+ p = buf;
+ m = nstate;
+ buf[m++] = s[0];
+ if (n >= 2 && m < 4)
+ {
+ buf[m++] = s[1];
+ if (n >= 3 && m < 4)
+ buf[m++] = s[2];
+ }
+ break;
+ default:
+ errno = EINVAL;
+ return (size_t)(-1);
+ }
+
+ /* Here m > 0. */
+
+ enc = locale_encoding_classification ();
+
+ if (enc == enc_utf8) /* UTF-8 */
+ {
+ /* Achieve
+ - multi-thread safety and
+ - the ability to produce wide character values > WCHAR_MAX
+ by not calling mbtowc() at all. */
+#include "mbrtowc-impl-utf8.h"
+ }
+ else
+ {
+ /* The hidden internal state of mbtowc would make this function not
+ multi-thread safe. Achieve multi-thread safety through a lock. */
+ wchar_t wc;
+ res = mbtowc_with_lock (&wc, p, m);
+
+ if (res >= 0)
+ {
+ if ((wc == 0) != (res == 0))
+ abort ();
+ if (pwc != NULL)
+ *pwc = wc;
+ goto success;
+ }
+
+ /* mbtowc does not distinguish between invalid and incomplete multibyte
+ sequences. But mbrtowc needs to make this distinction.
+ There are two possible approaches:
+ - Use iconv() and its return value.
+ - Use built-in knowledge about the possible encodings.
+ Given the low quality of implementation of iconv() on the systems
+ that lack mbrtowc(), we use the second approach.
+ The possible encodings are:
+ - 8-bit encodings,
+ - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
+ - UTF-8 (already handled above).
+ Use specialized code for each. */
+ if (m >= 4 || m >= MB_CUR_MAX)
+ goto invalid;
+ /* Here MB_CUR_MAX > 1 and 0 < m < 4. */
+ switch (enc)
+ {
+ /* As a reference for this code, you can use the GNU libiconv
+ implementation. Look for uses of the RET_TOOFEW macro. */
+
+ case enc_eucjp: /* EUC-JP */
+ {
+ if (m == 1)
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
+ goto incomplete;
+ }
+ if (m == 2)
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if (c == 0x8f)
+ {
+ unsigned char c2 = (unsigned char) p[1];
+
+ if (c2 >= 0xa1 && c2 < 0xff)
+ goto incomplete;
+ }
+ }
+ goto invalid;
+ }
+
+ case enc_94: /* EUC-KR, GB2312, BIG5 */
+ {
+ if (m == 1)
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if (c >= 0xa1 && c < 0xff)
+ goto incomplete;
+ }
+ goto invalid;
+ }
+
+ case enc_euctw: /* EUC-TW */
+ {
+ if (m == 1)
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
+ goto incomplete;
+ }
+ else /* m == 2 || m == 3 */
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if (c == 0x8e)
+ goto incomplete;
+ }
+ goto invalid;
+ }
+
+ case enc_gb18030: /* GB18030 */
+ {
+ if (m == 1)
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
+ goto incomplete;
+ }
+ else /* m == 2 || m == 3 */
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if (c >= 0x90 && c <= 0xe3)
+ {
+ unsigned char c2 = (unsigned char) p[1];
+
+ if (c2 >= 0x30 && c2 <= 0x39)
+ {
+ if (m == 2)
+ goto incomplete;
+ else /* m == 3 */
+ {
+ unsigned char c3 = (unsigned char) p[2];
+
+ if (c3 >= 0x81 && c3 <= 0xfe)
+ goto incomplete;
+ }
+ }
+ }
+ }
+ goto invalid;
+ }
+
+ case enc_sjis: /* SJIS */
+ {
+ if (m == 1)
+ {
+ unsigned char c = (unsigned char) p[0];
+
+ if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
+ || (c >= 0xf0 && c <= 0xf9))
+ goto incomplete;
+ }
+ goto invalid;
+ }
+
+ default:
+ /* An unknown multibyte encoding. */
+ goto incomplete;
+ }
+ }
+
+ success:
+ /* res >= 0 is the corrected return value of
+ mbtowc_with_lock (&wc, p, m). */
+ if (nstate >= (res > 0 ? res : 1))
+ abort ();
+ res -= nstate;
+ pstate[0] = 0;
+ return res;
+
+ incomplete:
+ {
+ size_t k = nstate;
+ /* Here 0 <= k < m < 4. */
+ pstate[++k] = s[0];
+ if (k < m)
+ {
+ pstate[++k] = s[1];
+ if (k < m)
+ pstate[++k] = s[2];
+ }
+ if (k != m)
+ abort ();
+ }
+ pstate[0] = m;
+ return (size_t)(-2);
+
+ invalid:
+ errno = EILSEQ;
+ /* The conversion state is undefined, says POSIX. */
+ return (size_t)(-1);
+ }
diff --git a/lib/mbrtowc.c b/lib/mbrtowc.c
index 2f6df28..6cb5267 100644
--- a/lib/mbrtowc.c
+++ b/lib/mbrtowc.c
@@ -1,5 +1,5 @@
/* Convert multibyte character to wide character.
- Copyright (C) 1999-2002, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-2002, 2005-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
@@ -20,20 +20,39 @@
/* Specification. */
#include <wchar.h>
-#if C_LOCALE_MAYBE_EILSEQ
-# include "hard-locale.h"
-# include <locale.h>
-#endif
-
#if GNULIB_defined_mbstate_t
-/* Implement mbrtowc() on top of mbtowc(). */
+/* Implement mbrtowc() on top of mbtowc() for the non-UTF-8 locales
+ and directly for the UTF-8 locales. */
# include <errno.h>
+# include <stdint.h>
# include <stdlib.h>
-# include "localcharset.h"
-# include "streq.h"
+# if defined _WIN32 && !defined __CYGWIN__
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# elif HAVE_PTHREAD_API
+
+# include <pthread.h>
+# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
+# include <threads.h>
+# pragma weak thrd_exit
+# define c11_threads_in_use() (thrd_exit != NULL)
+# else
+# define c11_threads_in_use() 0
+# endif
+
+# elif HAVE_THREADS_H
+
+# include <threads.h>
+
+# endif
+
# include "verify.h"
+# include "lc-charset-dispatch.h"
+# include "mbtowc-lock.h"
# ifndef FALLTHROUGH
# if __GNUC__ < 7
@@ -43,342 +62,24 @@
# endif
# endif
-/* Returns a classification of special values of the encoding of the current
- locale. */
-typedef enum {
- enc_other, /* other */
- enc_utf8, /* UTF-8 */
- enc_eucjp, /* EUC-JP */
- enc_94, /* EUC-KR, GB2312, BIG5 */
- enc_euctw, /* EUC-TW */
- enc_gb18030, /* GB18030 */
- enc_sjis /* SJIS */
-} enc_t;
-static inline enc_t
-locale_enc (void)
-{
- const char *encoding = locale_charset ();
- if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
- return enc_utf8;
- if (STREQ_OPT (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
- return enc_eucjp;
- if (STREQ_OPT (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
- || STREQ_OPT (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
- || STREQ_OPT (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
- return enc_94;
- if (STREQ_OPT (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
- return enc_euctw;
- if (STREQ_OPT (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
- return enc_gb18030;
- if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
- return enc_sjis;
- return enc_other;
-}
-
-#if GNULIB_WCHAR_SINGLE
-/* When we know that the locale does not change, provide a speedup by
- caching the value of locale_enc. */
-static int cached_locale_enc = -1;
-static inline enc_t
-locale_enc_cached (void)
-{
- if (cached_locale_enc < 0)
- cached_locale_enc = locale_enc ();
- return cached_locale_enc;
-}
-#else
-/* By default, don't make assumptions, hence no caching. */
-# define locale_enc_cached locale_enc
-#endif
-
verify (sizeof (mbstate_t) >= 4);
-
static char internal_state[4];
size_t
mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
- char *pstate = (char *)ps;
-
- if (s == NULL)
- {
- pwc = NULL;
- s = "";
- n = 1;
- }
-
- if (n == 0)
- return (size_t)(-2);
-
- /* Here n > 0. */
-
- if (pstate == NULL)
- pstate = internal_state;
-
- {
- size_t nstate = pstate[0];
- char buf[4];
- const char *p;
- size_t m;
-
- switch (nstate)
- {
- case 0:
- p = s;
- m = n;
- break;
- case 3:
- buf[2] = pstate[3];
- FALLTHROUGH;
- case 2:
- buf[1] = pstate[2];
- FALLTHROUGH;
- case 1:
- buf[0] = pstate[1];
- p = buf;
- m = nstate;
- buf[m++] = s[0];
- if (n >= 2 && m < 4)
- {
- buf[m++] = s[1];
- if (n >= 3 && m < 4)
- buf[m++] = s[2];
- }
- break;
- default:
- errno = EINVAL;
- return (size_t)(-1);
- }
-
- /* Here m > 0. */
-
-# if __GLIBC__ || defined __UCLIBC__
- /* Work around bug <https://sourceware.org/bugzilla/show_bug.cgi?id=9674> */
- mbtowc (NULL, NULL, 0);
-# endif
- {
- int res = mbtowc (pwc, p, m);
-
- if (res >= 0)
- {
- if (pwc != NULL && ((*pwc == 0) != (res == 0)))
- abort ();
- if (nstate >= (res > 0 ? res : 1))
- abort ();
- res -= nstate;
- pstate[0] = 0;
- return res;
- }
-
- /* mbtowc does not distinguish between invalid and incomplete multibyte
- sequences. But mbrtowc needs to make this distinction.
- There are two possible approaches:
- - Use iconv() and its return value.
- - Use built-in knowledge about the possible encodings.
- Given the low quality of implementation of iconv() on the systems that
- lack mbrtowc(), we use the second approach.
- The possible encodings are:
- - 8-bit encodings,
- - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
- - UTF-8.
- Use specialized code for each. */
- if (m >= 4 || m >= MB_CUR_MAX)
- goto invalid;
- /* Here MB_CUR_MAX > 1 and 0 < m < 4. */
- switch (locale_enc_cached ())
- {
- case enc_utf8: /* UTF-8 */
- {
- /* Cf. unistr/u8-mblen.c. */
- unsigned char c = (unsigned char) p[0];
-
- if (c >= 0xc2)
- {
- if (c < 0xe0)
- {
- if (m == 1)
- goto incomplete;
- }
- else if (c < 0xf0)
- {
- if (m == 1)
- goto incomplete;
- if (m == 2)
- {
- unsigned char c2 = (unsigned char) p[1];
-
- if ((c2 ^ 0x80) < 0x40
- && (c >= 0xe1 || c2 >= 0xa0)
- && (c != 0xed || c2 < 0xa0))
- goto incomplete;
- }
- }
- else if (c <= 0xf4)
- {
- if (m == 1)
- goto incomplete;
- else /* m == 2 || m == 3 */
- {
- unsigned char c2 = (unsigned char) p[1];
-
- if ((c2 ^ 0x80) < 0x40
- && (c >= 0xf1 || c2 >= 0x90)
- && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
- {
- if (m == 2)
- goto incomplete;
- else /* m == 3 */
- {
- unsigned char c3 = (unsigned char) p[2];
-
- if ((c3 ^ 0x80) < 0x40)
- goto incomplete;
- }
- }
- }
- }
- }
- goto invalid;
- }
-
- /* As a reference for this code, you can use the GNU libiconv
- implementation. Look for uses of the RET_TOOFEW macro. */
-
- case enc_eucjp: /* EUC-JP */
- {
- if (m == 1)
- {
- unsigned char c = (unsigned char) p[0];
-
- if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
- goto incomplete;
- }
- if (m == 2)
- {
- unsigned char c = (unsigned char) p[0];
-
- if (c == 0x8f)
- {
- unsigned char c2 = (unsigned char) p[1];
-
- if (c2 >= 0xa1 && c2 < 0xff)
- goto incomplete;
- }
- }
- goto invalid;
- }
-
- case enc_94: /* EUC-KR, GB2312, BIG5 */
- {
- if (m == 1)
- {
- unsigned char c = (unsigned char) p[0];
-
- if (c >= 0xa1 && c < 0xff)
- goto incomplete;
- }
- goto invalid;
- }
-
- case enc_euctw: /* EUC-TW */
- {
- if (m == 1)
- {
- unsigned char c = (unsigned char) p[0];
-
- if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
- goto incomplete;
- }
- else /* m == 2 || m == 3 */
- {
- unsigned char c = (unsigned char) p[0];
-
- if (c == 0x8e)
- goto incomplete;
- }
- goto invalid;
- }
-
- case enc_gb18030: /* GB18030 */
- {
- if (m == 1)
- {
- unsigned char c = (unsigned char) p[0];
-
- if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
- goto incomplete;
- }
- else /* m == 2 || m == 3 */
- {
- unsigned char c = (unsigned char) p[0];
-
- if (c >= 0x90 && c <= 0xe3)
- {
- unsigned char c2 = (unsigned char) p[1];
-
- if (c2 >= 0x30 && c2 <= 0x39)
- {
- if (m == 2)
- goto incomplete;
- else /* m == 3 */
- {
- unsigned char c3 = (unsigned char) p[2];
-
- if (c3 >= 0x81 && c3 <= 0xfe)
- goto incomplete;
- }
- }
- }
- }
- goto invalid;
- }
-
- case enc_sjis: /* SJIS */
- {
- if (m == 1)
- {
- unsigned char c = (unsigned char) p[0];
-
- if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
- || (c >= 0xf0 && c <= 0xf9))
- goto incomplete;
- }
- goto invalid;
- }
-
- default:
- /* An unknown multibyte encoding. */
- goto incomplete;
- }
-
- incomplete:
- {
- size_t k = nstate;
- /* Here 0 <= k < m < 4. */
- pstate[++k] = s[0];
- if (k < m)
- {
- pstate[++k] = s[1];
- if (k < m)
- pstate[++k] = s[2];
- }
- if (k != m)
- abort ();
- }
- pstate[0] = m;
- return (size_t)(-2);
-
- invalid:
- errno = EILSEQ;
- /* The conversion state is undefined, says POSIX. */
- return (size_t)(-1);
- }
- }
+# define FITS_IN_CHAR_TYPE(wc) ((wc) <= WCHAR_MAX)
+# include "mbrtowc-impl.h"
}
#else
/* Override the system's mbrtowc() function. */
+# if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
+# include "hard-locale.h"
+# include <locale.h>
+# endif
+
# undef mbrtowc
size_t
@@ -436,14 +137,20 @@ rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
}
# endif
+# if MBRTOWC_STORES_INCOMPLETE_BUG
+ ret = mbrtowc (&wc, s, n, ps);
+ if (ret < (size_t) -2 && pwc != NULL)
+ *pwc = wc;
+# else
ret = mbrtowc (pwc, s, n, ps);
+# endif
# if MBRTOWC_NUL_RETVAL_BUG
if (ret < (size_t) -2 && !*pwc)
return 0;
# endif
-# if C_LOCALE_MAYBE_EILSEQ
+# if MBRTOWC_IN_C_LOCALE_MAYBE_EILSEQ
if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
{
unsigned char uc = *s;
diff --git a/lib/mbsinit.c b/lib/mbsinit.c
index e23a5ad..981a894 100644
--- a/lib/mbsinit.c
+++ b/lib/mbsinit.c
@@ -1,5 +1,5 @@
/* Test for initial conversion state.
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2008-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
@@ -56,13 +56,10 @@ mbsinit (const mbstate_t *ps)
{
# if defined _WIN32 && !defined __CYGWIN__
/* Native Windows. */
-# ifdef __MINGW32__
- /* On mingw, 'mbstate_t' is defined as 'int'. */
- return ps == NULL || *ps == 0;
-# else
- /* MSVC defines 'mbstate_t' as an 8-byte struct; the first 4-bytes matter. */
+ /* MSVC defines 'mbstate_t' as an 8-byte struct; the first 4 bytes matter.
+ On mingw, 'mbstate_t' is sometimes defined as 'int', sometimes defined as
+ an 8-byte struct, of which the first 4 bytes matter. */
return ps == NULL || *(const unsigned int *)ps == 0;
-# endif
# else
/* Minix, HP-UX 11.00, Solaris 2.6, Interix, ... */
/* Maybe this definition works, maybe not... */
diff --git a/lib/mbtowc-impl.h b/lib/mbtowc-impl.h
index 633832f..22e414a 100644
--- a/lib/mbtowc-impl.h
+++ b/lib/mbtowc-impl.h
@@ -1,5 +1,5 @@
/* Convert multibyte character to wide character.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2011.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/mbtowc-lock.c b/lib/mbtowc-lock.c
new file mode 100644
index 0000000..85ad3c4
--- /dev/null
+++ b/lib/mbtowc-lock.c
@@ -0,0 +1,150 @@
+/* Return the internal lock used by mbrtowc and mbrtoc32.
+ Copyright (C) 2019-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 Bruno Haible <bruno@clisp.org>, 2019-2020. */
+
+#include <config.h>
+
+/* When it is known that the gl_get_mbtowc_lock function is defined
+ by a dependency library, it should not be defined here. */
+#if OMIT_MBTOWC_LOCK
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
+
+#else
+
+/* This file defines the internal lock used by mbrtowc and mbrtoc32.
+ It is a separate compilation unit, so that only one copy of it is
+ present when linking statically. */
+
+/* Prohibit renaming this symbol. */
+# undef gl_get_mbtowc_lock
+
+/* Macro for exporting a symbol (function, not variable) defined in this file,
+ when compiled into a shared library. */
+# ifndef DLL_EXPORTED
+# if HAVE_VISIBILITY
+ /* Override the effect of the compiler option '-fvisibility=hidden'. */
+# define DLL_EXPORTED __attribute__((__visibility__("default")))
+# elif defined _WIN32 || defined __CYGWIN__
+# define DLL_EXPORTED __declspec(dllexport)
+# else
+# define DLL_EXPORTED
+# endif
+# endif
+
+# if defined _WIN32 && !defined __CYGWIN__
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# include "windows-initguard.h"
+
+/* The return type is a 'CRITICAL_SECTION *', not a 'glwthread_mutex_t *',
+ because the latter is not guaranteed to be a stable ABI in the future. */
+
+/* Make sure the function gets exported from DLLs. */
+DLL_EXPORTED CRITICAL_SECTION *gl_get_mbtowc_lock (void);
+
+static glwthread_initguard_t guard = GLWTHREAD_INITGUARD_INIT;
+static CRITICAL_SECTION lock;
+
+/* Returns the internal lock used by mbrtowc and mbrtoc32. */
+CRITICAL_SECTION *
+gl_get_mbtowc_lock (void)
+{
+ if (!guard.done)
+ {
+ if (InterlockedIncrement (&guard.started) == 0)
+ {
+ /* This thread is the first one to need the lock. Initialize it. */
+ InitializeCriticalSection (&lock);
+ guard.done = 1;
+ }
+ else
+ {
+ /* Don't let guard.started grow and wrap around. */
+ InterlockedDecrement (&guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this mutex. */
+ while (!guard.done)
+ Sleep (0);
+ }
+ }
+ return &lock;
+}
+
+# elif HAVE_PTHREAD_API
+
+# include <pthread.h>
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Make sure the function gets exported from shared libraries. */
+DLL_EXPORTED pthread_mutex_t *gl_get_mbtowc_lock (void);
+
+/* Returns the internal lock used by mbrtowc and mbrtoc32. */
+pthread_mutex_t *
+gl_get_mbtowc_lock (void)
+{
+ return &mutex;
+}
+
+# elif HAVE_THREADS_H
+
+# include <threads.h>
+# include <stdlib.h>
+
+static int volatile init_needed = 1;
+static once_flag init_once = ONCE_FLAG_INIT;
+static mtx_t mutex;
+
+static void
+atomic_init (void)
+{
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ abort ();
+ init_needed = 0;
+}
+
+/* Make sure the function gets exported from shared libraries. */
+DLL_EXPORTED mtx_t *gl_get_mbtowc_lock (void);
+
+/* Returns the internal lock used by mbrtowc and mbrtoc32. */
+mtx_t *
+gl_get_mbtowc_lock (void)
+{
+ if (init_needed)
+ call_once (&init_once, atomic_init);
+ return &mutex;
+}
+
+# endif
+
+# if (defined _WIN32 || defined __CYGWIN__) && !defined _MSC_VER
+/* Make sure the '__declspec(dllimport)' in mbrtowc.c and mbrtoc32.c does not
+ cause a link failure when no DLLs are involved. */
+# if defined _WIN64 || defined _LP64
+# define IMP(x) __imp_##x
+# else
+# define IMP(x) _imp__##x
+# endif
+void * IMP(gl_get_mbtowc_lock) = &gl_get_mbtowc_lock;
+# endif
+
+#endif
diff --git a/lib/mbtowc-lock.h b/lib/mbtowc-lock.h
new file mode 100644
index 0000000..e101978
--- /dev/null
+++ b/lib/mbtowc-lock.h
@@ -0,0 +1,115 @@
+/* Use the internal lock used by mbrtowc and mbrtoc32.
+ Copyright (C) 2019-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 Bruno Haible <bruno@clisp.org>, 2019-2020. */
+
+/* Use a lock, so that no two threads can invoke mbtowc at the same time. */
+
+static inline int
+mbtowc_unlocked (wchar_t *pwc, const char *p, size_t m)
+{
+ /* Put the hidden internal state of mbtowc into its initial state.
+ This is needed at least with glibc, uClibc, and MSVC CRT.
+ See <https://sourceware.org/bugzilla/show_bug.cgi?id=9674>. */
+ mbtowc (NULL, NULL, 0);
+
+ return mbtowc (pwc, p, m);
+}
+
+/* Prohibit renaming this symbol. */
+#undef gl_get_mbtowc_lock
+
+#if defined _WIN32 && !defined __CYGWIN__
+
+extern __declspec(dllimport) CRITICAL_SECTION *gl_get_mbtowc_lock (void);
+
+static int
+mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
+{
+ CRITICAL_SECTION *lock = gl_get_mbtowc_lock ();
+ int ret;
+
+ EnterCriticalSection (lock);
+ ret = mbtowc_unlocked (pwc, p, m);
+ LeaveCriticalSection (lock);
+
+ return ret;
+}
+
+#elif HAVE_PTHREAD_API /* AIX, IRIX, Cygwin */
+
+extern
+# if defined _WIN32 || defined __CYGWIN__
+ __declspec(dllimport)
+# endif
+ pthread_mutex_t *gl_get_mbtowc_lock (void);
+
+# if HAVE_WEAK_SYMBOLS /* IRIX */
+
+ /* Avoid the need to link with '-lpthread'. */
+# pragma weak pthread_mutex_lock
+# pragma weak pthread_mutex_unlock
+
+ /* Determine whether libpthread is in use. */
+# pragma weak pthread_mutexattr_gettype
+ /* See the comments in lock.h. */
+# define pthread_in_use() \
+ (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
+
+# else
+# define pthread_in_use() 1
+# endif
+
+static int
+mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
+{
+ if (pthread_in_use())
+ {
+ pthread_mutex_t *lock = gl_get_mbtowc_lock ();
+ int ret;
+
+ if (pthread_mutex_lock (lock))
+ abort ();
+ ret = mbtowc_unlocked (pwc, p, m);
+ if (pthread_mutex_unlock (lock))
+ abort ();
+
+ return ret;
+ }
+ else
+ return mbtowc_unlocked (pwc, p, m);
+}
+
+#elif HAVE_THREADS_H
+
+extern mtx_t *gl_get_mbtowc_lock (void);
+
+static int
+mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
+{
+ mtx_t *lock = gl_get_mbtowc_lock ();
+ int ret;
+
+ if (mtx_lock (lock) != thrd_success)
+ abort ();
+ ret = mbtowc_unlocked (pwc, p, m);
+ if (mtx_unlock (lock) != thrd_success)
+ abort ();
+
+ return ret;
+}
+
+#endif
diff --git a/lib/mbtowc.c b/lib/mbtowc.c
index a212b22..5fc2d28 100644
--- a/lib/mbtowc.c
+++ b/lib/mbtowc.c
@@ -1,5 +1,5 @@
/* Convert multibyte character to wide character.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2011.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/memchr.c b/lib/memchr.c
index 0b47546..bff63da 100644
--- a/lib/memchr.c
+++ b/lib/memchr.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2018
+/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2020
Free Software Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
diff --git a/lib/memchr.valgrind b/lib/memchr.valgrind
index 60f247e..f6dd209 100644
--- a/lib/memchr.valgrind
+++ b/lib/memchr.valgrind
@@ -1,4 +1,20 @@
# Suppress a valgrind message about use of uninitialized memory in memchr().
+
+# Copyright (C) 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/>.
+
# POSIX states that when the character is found, memchr must not read extra
# bytes in an overestimated length (for example, where memchr is used to
# implement strnlen). However, we use a safe word read to provide a speedup.
diff --git a/lib/memrchr.c b/lib/memrchr.c
index 2efc7cb..7ff32e1 100644
--- a/lib/memrchr.c
+++ b/lib/memrchr.c
@@ -1,6 +1,6 @@
/* memrchr -- find the last occurrence of a byte in a memory block
- Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2018 Free Software
+ Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2020 Free Software
Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
diff --git a/lib/minmax.h b/lib/minmax.h
index 33a5305..b947776 100644
--- a/lib/minmax.h
+++ b/lib/minmax.h
@@ -1,5 +1,5 @@
/* MIN, MAX macros.
- Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2018 Free Software
+ Copyright (C) 1995, 1998, 2001, 2003, 2005, 2009-2020 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
diff --git a/lib/mkdir.c b/lib/mkdir.c
index 37d5a0f..c0d4b61 100644
--- a/lib/mkdir.c
+++ b/lib/mkdir.c
@@ -1,7 +1,7 @@
/* On some systems, mkdir ("foo/", 0700) fails because of the trailing
slash. On those systems, this wrapper removes the trailing slash.
- Copyright (C) 2001, 2003, 2006, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2006, 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
diff --git a/lib/mkostemp.c b/lib/mkostemp.c
index df9ecf8..46b58e1 100644
--- a/lib/mkostemp.c
+++ b/lib/mkostemp.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2018 Free Software
+/* Copyright (C) 1998-1999, 2001, 2005-2007, 2009-2020 Free Software
Foundation, Inc.
This file is derived from the one in the GNU C Library.
diff --git a/lib/msvc-inval.c b/lib/msvc-inval.c
index 0f19a09..8636688 100644
--- a/lib/msvc-inval.c
+++ b/lib/msvc-inval.c
@@ -1,5 +1,5 @@
/* Invalid parameter handler for MSVC runtime libraries.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-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
diff --git a/lib/msvc-inval.h b/lib/msvc-inval.h
index 8e7ff30..93ee785 100644
--- a/lib/msvc-inval.h
+++ b/lib/msvc-inval.h
@@ -1,5 +1,5 @@
/* Invalid parameter handler for MSVC runtime libraries.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-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
@@ -95,7 +95,7 @@ extern void gl_msvc_inval_ensure_handler (void);
/* Gnulib can define its own status codes, as described in the page
"Raising Software Exceptions" on microsoft.com
- <https://msdn.microsoft.com/en-us/library/het71c37.aspx>.
+ <https://docs.microsoft.com/en-us/cpp/cpp/raising-software-exceptions>.
Our status codes are composed of
- 0xE0000000, mandatory for all user-defined status codes,
- 0x474E550, a API identifier ("GNU"),
@@ -106,7 +106,7 @@ extern void gl_msvc_inval_ensure_handler (void);
# if defined _MSC_VER
/* A compiler that supports __try/__except, as described in the page
"try-except statement" on microsoft.com
- <https://msdn.microsoft.com/en-us/library/s58ftw19.aspx>.
+ <https://docs.microsoft.com/en-us/cpp/cpp/try-except-statement>.
With __try/__except, we can use the multithread-safe exception handling. */
# ifdef __cplusplus
diff --git a/lib/msvc-nothrow.c b/lib/msvc-nothrow.c
index 785733e..bf93b88 100644
--- a/lib/msvc-nothrow.c
+++ b/lib/msvc-nothrow.c
@@ -1,6 +1,6 @@
/* Wrappers that don't throw invalid parameter notifications
with MSVC runtime libraries.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-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
diff --git a/lib/msvc-nothrow.h b/lib/msvc-nothrow.h
index a9671c3..fca5415 100644
--- a/lib/msvc-nothrow.h
+++ b/lib/msvc-nothrow.h
@@ -1,6 +1,6 @@
/* Wrappers that don't throw invalid parameter notifications
with MSVC runtime libraries.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-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
diff --git a/lib/nl_langinfo.c b/lib/nl_langinfo.c
index ea26730..23299cb 100644
--- a/lib/nl_langinfo.c
+++ b/lib/nl_langinfo.c
@@ -1,6 +1,6 @@
/* nl_langinfo() replacement: query locale dependent information.
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
@@ -28,16 +28,33 @@
# include <stdio.h>
#endif
+/* nl_langinfo() must be multithread-safe. To achieve this without using
+ thread-local storage:
+ 1. We use a specific static buffer for each possible argument.
+ So that different threads can call nl_langinfo with different arguments,
+ without interfering.
+ 2. We use a simple strcpy or memcpy to fill this static buffer. Filling it
+ through, for example, strcpy + strcat would not be guaranteed to leave
+ the buffer's contents intact if another thread is currently accessing
+ it. If necessary, the contents is first assembled in a stack-allocated
+ buffer. */
+
#if !REPLACE_NL_LANGINFO || GNULIB_defined_CODESET
/* Return the codeset of the current locale, if this is easily deducible.
Otherwise, return "". */
static char *
ctype_codeset (void)
{
- static char buf[2 + 10 + 1];
- char const *locale = setlocale (LC_CTYPE, NULL);
- char *codeset = buf;
+ static char result[2 + 10 + 1];
+ char buf[2 + 10 + 1];
+ char locale[SETLOCALE_NULL_MAX];
+ char *codeset;
size_t codesetlen;
+
+ if (setlocale_null_r (LC_CTYPE, locale, sizeof (locale)))
+ locale[0] = '\0';
+
+ codeset = buf;
codeset[0] = '\0';
if (locale && locale[0])
@@ -76,9 +93,20 @@ ctype_codeset (void)
memmove (buf + 2, codeset, codesetlen + 1);
else
sprintf (buf + 2, "%u", GetACP ());
- codeset = memcpy (buf, "CP", 2);
-# endif
- return codeset;
+ /* For a locale name such as "French_France.65001", in Windows 10,
+ setlocale now returns "French_France.utf8" instead. */
+ if (strcmp (buf + 2, "65001") == 0 || strcmp (buf + 2, "utf8") == 0)
+ return (char *) "UTF-8";
+ else
+ {
+ memcpy (buf, "CP", 2);
+ strcpy (result, buf);
+ return result;
+ }
+# else
+ strcpy (result, codeset);
+ return result;
+#endif
}
#endif
@@ -169,7 +197,7 @@ rpl_nl_langinfo (nl_item item)
char *
nl_langinfo (nl_item item)
{
- static char nlbuf[100];
+ char buf[100];
struct tm tmm = { 0 };
switch (item)
@@ -209,14 +237,22 @@ nl_langinfo (nl_item item)
case T_FMT_AMPM:
return (char *) "%I:%M:%S %p";
case AM_STR:
- if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm))
- return (char *) "AM";
- return nlbuf;
+ {
+ static char result[80];
+ if (!strftime (buf, sizeof result, "%p", &tmm))
+ return (char *) "AM";
+ strcpy (result, buf);
+ return result;
+ }
case PM_STR:
- tmm.tm_hour = 12;
- if (!strftime (nlbuf, sizeof nlbuf, "%p", &tmm))
- return (char *) "PM";
- return nlbuf;
+ {
+ static char result[80];
+ tmm.tm_hour = 12;
+ if (!strftime (buf, sizeof result, "%p", &tmm))
+ return (char *) "PM";
+ strcpy (result, buf);
+ return result;
+ }
case DAY_1:
case DAY_2:
case DAY_3:
@@ -225,14 +261,16 @@ nl_langinfo (nl_item item)
case DAY_6:
case DAY_7:
{
+ static char result[7][50];
static char const days[][sizeof "Wednesday"] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"
};
tmm.tm_wday = item - DAY_1;
- if (!strftime (nlbuf, sizeof nlbuf, "%A", &tmm))
+ if (!strftime (buf, sizeof result[0], "%A", &tmm))
return (char *) days[item - DAY_1];
- return nlbuf;
+ strcpy (result[item - DAY_1], buf);
+ return result[item - DAY_1];
}
case ABDAY_1:
case ABDAY_2:
@@ -242,13 +280,15 @@ nl_langinfo (nl_item item)
case ABDAY_6:
case ABDAY_7:
{
+ static char result[7][30];
static char const abdays[][sizeof "Sun"] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
tmm.tm_wday = item - ABDAY_1;
- if (!strftime (nlbuf, sizeof nlbuf, "%a", &tmm))
+ if (!strftime (buf, sizeof result[0], "%a", &tmm))
return (char *) abdays[item - ABDAY_1];
- return nlbuf;
+ strcpy (result[item - ABDAY_1], buf);
+ return result[item - ABDAY_1];
}
{
static char const months[][sizeof "September"] = {
@@ -267,10 +307,14 @@ nl_langinfo (nl_item item)
case MON_10:
case MON_11:
case MON_12:
- tmm.tm_mon = item - MON_1;
- if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm))
- return (char *) months[item - MON_1];
- return nlbuf;
+ {
+ static char result[12][50];
+ tmm.tm_mon = item - MON_1;
+ if (!strftime (buf, sizeof result[0], "%B", &tmm))
+ return (char *) months[item - MON_1];
+ strcpy (result[item - MON_1], buf);
+ return result[item - MON_1];
+ }
case ALTMON_1:
case ALTMON_2:
case ALTMON_3:
@@ -283,15 +327,19 @@ nl_langinfo (nl_item item)
case ALTMON_10:
case ALTMON_11:
case ALTMON_12:
- tmm.tm_mon = item - ALTMON_1;
- /* The platforms without nl_langinfo() don't support strftime with %OB.
- We don't even need to try. */
- #if 0
- if (!strftime (nlbuf, sizeof nlbuf, "%OB", &tmm))
- #endif
- if (!strftime (nlbuf, sizeof nlbuf, "%B", &tmm))
- return (char *) months[item - ALTMON_1];
- return nlbuf;
+ {
+ static char result[12][50];
+ tmm.tm_mon = item - ALTMON_1;
+ /* The platforms without nl_langinfo() don't support strftime with
+ %OB. We don't even need to try. */
+ #if 0
+ if (!strftime (buf, sizeof result[0], "%OB", &tmm))
+ #endif
+ if (!strftime (buf, sizeof result[0], "%B", &tmm))
+ return (char *) months[item - ALTMON_1];
+ strcpy (result[item - ALTMON_1], buf);
+ return result[item - ALTMON_1];
+ }
}
case ABMON_1:
case ABMON_2:
@@ -306,14 +354,16 @@ nl_langinfo (nl_item item)
case ABMON_11:
case ABMON_12:
{
+ static char result[12][30];
static char const abmonths[][sizeof "Jan"] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
"Sep", "Oct", "Nov", "Dec"
};
tmm.tm_mon = item - ABMON_1;
- if (!strftime (nlbuf, sizeof nlbuf, "%b", &tmm))
+ if (!strftime (buf, sizeof result[0], "%b", &tmm))
return (char *) abmonths[item - ABMON_1];
- return nlbuf;
+ strcpy (result[item - ABMON_1], buf);
+ return result[item - ABMON_1];
}
case ERA:
return (char *) "";
diff --git a/lib/obstack.c b/lib/obstack.c
index 02be6cf..a6757b8 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -1,5 +1,5 @@
/* obstack.c - subroutines used implicitly by object stack macros
- Copyright (C) 1988-2018 Free Software Foundation, Inc.
+ Copyright (C) 1988-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
diff --git a/lib/obstack.h b/lib/obstack.h
index cff4205..f1c1d00 100644
--- a/lib/obstack.h
+++ b/lib/obstack.h
@@ -1,5 +1,5 @@
/* obstack.h - object stack macros
- Copyright (C) 1988-2018 Free Software Foundation, Inc.
+ Copyright (C) 1988-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
diff --git a/lib/pathmax.h b/lib/pathmax.h
index 7052e6a..15a236f 100644
--- a/lib/pathmax.h
+++ b/lib/pathmax.h
@@ -1,5 +1,5 @@
/* Define PATH_MAX somehow. Requires sys/types.h.
- Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2018 Free Software
+ Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2020 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -20,7 +20,7 @@
/* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename,
including the terminating NUL byte.
- <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html>
+ <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html>
PATH_MAX is not defined on systems which have no limit on filename length,
such as GNU/Hurd.
@@ -68,7 +68,7 @@
# if defined _WIN32 && ! defined __CYGWIN__
/* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com,
section "Maximum Path Length Limitation",
- <https://msdn.microsoft.com/en-us/library/aa365247.aspx#maxpath>
+ <https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation>
explains that the maximum size of a filename, including the terminating
NUL byte, is 260 = 3 + 256 + 1.
This is the same value as
diff --git a/lib/progname.c b/lib/progname.c
index 382f503..d59d969 100644
--- a/lib/progname.c
+++ b/lib/progname.c
@@ -1,5 +1,5 @@
/* Program name management.
- Copyright (C) 2001-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/progname.h b/lib/progname.h
index adc6b01..bc276cc 100644
--- a/lib/progname.h
+++ b/lib/progname.h
@@ -1,5 +1,5 @@
/* Program name management.
- Copyright (C) 2001-2004, 2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 2006, 2009-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2001.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/qcopy-acl.c b/lib/qcopy-acl.c
index ee482ef..5408b0f 100644
--- a/lib/qcopy-acl.c
+++ b/lib/qcopy-acl.c
@@ -1,6 +1,6 @@
/* Copy access control list from one file to another. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/qset-acl.c b/lib/qset-acl.c
index e2d4cc5..db895a3 100644
--- a/lib/qset-acl.c
+++ b/lib/qset-acl.c
@@ -1,6 +1,6 @@
/* qset-acl.c - set access control list equivalent to a mode
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/quote.h b/lib/quote.h
index eedc283..391ff1a 100644
--- a/lib/quote.h
+++ b/lib/quote.h
@@ -1,6 +1,6 @@
/* quote.h - prototypes for quote.c
- Copyright (C) 1998-2001, 2003, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-2001, 2003, 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
diff --git a/lib/quotearg.c b/lib/quotearg.c
index fe68dca..c78fc16 100644
--- a/lib/quotearg.c
+++ b/lib/quotearg.c
@@ -1,6 +1,6 @@
/* quotearg.c - quote arguments for output
- Copyright (C) 1998-2002, 2004-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-2002, 2004-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
diff --git a/lib/quotearg.h b/lib/quotearg.h
index 0584c56..d30fdd1 100644
--- a/lib/quotearg.h
+++ b/lib/quotearg.h
@@ -1,6 +1,6 @@
/* quotearg.h - quote arguments for output
- Copyright (C) 1998-2002, 2004, 2006, 2008-2018 Free Software Foundation,
+ Copyright (C) 1998-2002, 2004, 2006, 2008-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/readlink.c b/lib/readlink.c
index 924e00d..4d392ef 100644
--- a/lib/readlink.c
+++ b/lib/readlink.c
@@ -1,5 +1,5 @@
/* Stub for readlink().
- Copyright (C) 2003-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2003-2007, 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
diff --git a/lib/regcomp.c b/lib/regcomp.c
index 0b05a63..84044be 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -233,9 +233,7 @@ re_compile_pattern (const char *pattern, size_t length,
return NULL;
return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
}
-#ifdef _LIBC
weak_alias (__re_compile_pattern, re_compile_pattern)
-#endif
/* Set by 're_set_syntax' to the current regexp syntax to recognize. Can
also be assigned to arbitrarily: each pattern buffer stores its own
@@ -260,9 +258,7 @@ re_set_syntax (reg_syntax_t syntax)
re_syntax_options = syntax;
return ret;
}
-#ifdef _LIBC
weak_alias (__re_set_syntax, re_set_syntax)
-#endif
int
re_compile_fastmap (struct re_pattern_buffer *bufp)
@@ -281,9 +277,7 @@ re_compile_fastmap (struct re_pattern_buffer *bufp)
bufp->fastmap_accurate = 1;
return 0;
}
-#ifdef _LIBC
weak_alias (__re_compile_fastmap, re_compile_fastmap)
-#endif
static inline void
__attribute__ ((always_inline))
@@ -464,7 +458,7 @@ re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
the return codes and their meanings.) */
int
-regcomp (regex_t *_Restrict_ preg, const char *_Restrict_ pattern, int cflags)
+regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags)
{
reg_errcode_t ret;
reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
@@ -515,16 +509,14 @@ regcomp (regex_t *_Restrict_ preg, const char *_Restrict_ pattern, int cflags)
return (int) ret;
}
-#ifdef _LIBC
libc_hidden_def (__regcomp)
weak_alias (__regcomp, regcomp)
-#endif
/* Returns a message corresponding to an error code, ERRCODE, returned
from either regcomp or regexec. We don't use PREG here. */
size_t
-regerror (int errcode, const regex_t *_Restrict_ preg, char *_Restrict_ errbuf,
+regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf,
size_t errbuf_size)
{
const char *msg;
@@ -555,9 +547,7 @@ regerror (int errcode, const regex_t *_Restrict_ preg, char *_Restrict_ errbuf,
return msg_size;
}
-#ifdef _LIBC
weak_alias (__regerror, regerror)
-#endif
#ifdef RE_ENABLE_I18N
@@ -657,10 +647,8 @@ regfree (regex_t *preg)
re_free (preg->translate);
preg->translate = NULL;
}
-#ifdef _LIBC
libc_hidden_def (__regfree)
weak_alias (__regfree, regfree)
-#endif
/* Entry points compatible with 4.2 BSD regex library. We don't define
them unless specifically requested. */
@@ -1448,7 +1436,7 @@ link_nfa_nodes (void *extra, bin_tree_t *node)
break;
case END_OF_RE:
- assert (node->next == NULL);
+ DEBUG_ASSERT (node->next == NULL);
break;
case OP_DUP_ASTERISK:
@@ -1464,8 +1452,8 @@ link_nfa_nodes (void *extra, bin_tree_t *node)
right = node->right->first->node_idx;
else
right = node->next->node_idx;
- assert (left > -1);
- assert (right > -1);
+ DEBUG_ASSERT (left > -1);
+ DEBUG_ASSERT (right > -1);
err = re_node_set_init_2 (dfa->edests + idx, left, right);
}
break;
@@ -1483,7 +1471,7 @@ link_nfa_nodes (void *extra, bin_tree_t *node)
break;
default:
- assert (!IS_EPSILON_NODE (node->token.type));
+ DEBUG_ASSERT (!IS_EPSILON_NODE (node->token.type));
dfa->nexts[idx] = node->next->node_idx;
break;
}
@@ -1665,9 +1653,7 @@ calc_eclosure (re_dfa_t *dfa)
{
Idx node_idx;
bool incomplete;
-#ifdef DEBUG
- assert (dfa->nodes_len > 0);
-#endif
+ DEBUG_ASSERT (dfa->nodes_len > 0);
incomplete = false;
/* For each nodes, calculate epsilon closure. */
for (node_idx = 0; ; ++node_idx)
@@ -1682,9 +1668,7 @@ calc_eclosure (re_dfa_t *dfa)
node_idx = 0;
}
-#ifdef DEBUG
- assert (dfa->eclosures[node_idx].nelem != -1);
-#endif
+ DEBUG_ASSERT (dfa->eclosures[node_idx].nelem != -1);
/* If we have already calculated, skip it. */
if (dfa->eclosures[node_idx].nelem != 0)
@@ -1812,8 +1796,8 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
token->word_char = 0;
#ifdef RE_ENABLE_I18N
token->mb_partial = 0;
- if (input->mb_cur_max > 1 &&
- !re_string_first_byte (input, re_string_cur_idx (input)))
+ if (input->mb_cur_max > 1
+ && !re_string_first_byte (input, re_string_cur_idx (input)))
{
token->type = CHARACTER;
token->mb_partial = 1;
@@ -2000,8 +1984,8 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
token->type = OP_PERIOD;
break;
case '^':
- if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&
- re_string_cur_idx (input) != 0)
+ if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE))
+ && re_string_cur_idx (input) != 0)
{
char prev = re_string_peek_byte (input, -1);
if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
@@ -2011,8 +1995,8 @@ peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
token->opr.ctx_type = LINE_FIRST;
break;
case '$':
- if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
- re_string_cur_idx (input) + 1 != re_string_length (input))
+ if (!(syntax & RE_CONTEXT_INDEP_ANCHORS)
+ && re_string_cur_idx (input) + 1 != re_string_length (input))
{
re_token_t next;
re_string_skip_bytes (input, 1);
@@ -2046,8 +2030,8 @@ peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
token->opr.c = c;
#ifdef RE_ENABLE_I18N
- if (input->mb_cur_max > 1 &&
- !re_string_first_byte (input, re_string_cur_idx (input)))
+ if (input->mb_cur_max > 1
+ && !re_string_first_byte (input, re_string_cur_idx (input)))
{
token->type = CHARACTER;
return 1;
@@ -2345,8 +2329,8 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
}
FALLTHROUGH;
case OP_CLOSE_SUBEXP:
- if ((token->type == OP_CLOSE_SUBEXP) &&
- !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
+ if ((token->type == OP_CLOSE_SUBEXP)
+ && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
{
*err = REG_ERPAREN;
return NULL;
@@ -2454,9 +2438,7 @@ parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
default:
/* Must not happen? */
-#ifdef DEBUG
- assert (0);
-#endif
+ DEBUG_ASSERT (false);
return NULL;
}
fetch_token (token, regexp, syntax);
@@ -3318,7 +3300,7 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
goto parse_bracket_exp_free_return;
break;
default:
- assert (0);
+ DEBUG_ASSERT (false);
break;
}
}
@@ -3674,7 +3656,6 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
Idx alloc = 0;
#endif /* not RE_ENABLE_I18N */
reg_errcode_t ret;
- re_token_t br_token;
bin_tree_t *tree;
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
@@ -3725,11 +3706,7 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
#endif
/* Build a tree for simple bracket. */
-#if defined GCC_LINT || defined lint
- memset (&br_token, 0, sizeof br_token);
-#endif
- br_token.type = SIMPLE_BRACKET;
- br_token.opr.sbcset = sbcset;
+ re_token_t br_token = { .type = SIMPLE_BRACKET, .opr.sbcset = sbcset };
tree = create_token_tree (dfa, NULL, NULL, &br_token);
if (__glibc_unlikely (tree == NULL))
goto build_word_op_espace;
@@ -3820,11 +3797,7 @@ static bin_tree_t *
create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
re_token_type_t type)
{
- re_token_t t;
-#if defined GCC_LINT || defined lint
- memset (&t, 0, sizeof t);
-#endif
- t.type = type;
+ re_token_t t = { .type = type };
return create_token_tree (dfa, left, right, &t);
}
diff --git a/lib/regex.c b/lib/regex.c
index 2a86e10..6bdd77f 100644
--- a/lib/regex.c
+++ b/lib/regex.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -20,10 +20,10 @@
#ifndef _LIBC
# include <libc-config.h>
-# if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
+# if __GNUC_PREREQ (4, 6)
# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
# endif
-# if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__
+# if __GNUC_PREREQ (4, 3)
# pragma GCC diagnostic ignored "-Wold-style-definition"
# pragma GCC diagnostic ignored "-Wtype-limits"
# endif
diff --git a/lib/regex.h b/lib/regex.h
index f2ac950..76ff4e3 100644
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -1,6 +1,6 @@
/* Definitions for data structures and routines for the regular
expression library.
- Copyright (C) 1985, 1989-2018 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1989-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
diff --git a/lib/regex_internal.c b/lib/regex_internal.c
index f13def3..2e21729 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -212,7 +212,7 @@ build_wcs_buffer (re_string_t *pstr)
{
#ifdef _LIBC
unsigned char buf[MB_LEN_MAX];
- assert (MB_LEN_MAX >= pstr->mb_cur_max);
+ DEBUG_ASSERT (MB_LEN_MAX >= pstr->mb_cur_max);
#else
unsigned char buf[64];
#endif
@@ -285,7 +285,7 @@ build_wcs_upper_buffer (re_string_t *pstr)
size_t mbclen;
#ifdef _LIBC
char buf[MB_LEN_MAX];
- assert (MB_LEN_MAX >= pstr->mb_cur_max);
+ DEBUG_ASSERT (pstr->mb_cur_max <= MB_LEN_MAX);
#else
char buf[64];
#endif
@@ -685,9 +685,7 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags)
pstr->valid_len - offset);
pstr->valid_len -= offset;
pstr->valid_raw_len -= offset;
-#if defined DEBUG && DEBUG
- assert (pstr->valid_len > 0);
-#endif
+ DEBUG_ASSERT (pstr->valid_len > 0);
}
}
else
@@ -941,10 +939,7 @@ re_string_context_at (const re_string_t *input, Idx idx, int eflags)
Idx wc_idx = idx;
while(input->wcs[wc_idx] == WEOF)
{
-#if defined DEBUG && DEBUG
- /* It must not happen. */
- assert (wc_idx >= 0);
-#endif
+ DEBUG_ASSERT (wc_idx >= 0);
--wc_idx;
if (wc_idx < 0)
return input->tip_context;
@@ -1311,7 +1306,6 @@ re_node_set_insert (re_node_set *set, Idx elem)
first element separately to skip a check in the inner loop. */
if (elem < set->elems[0])
{
- idx = 0;
for (idx = set->nelem; idx > 0; idx--)
set->elems[idx] = set->elems[idx - 1];
}
@@ -1716,15 +1710,19 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
{
if (newstate->entrance_nodes == &newstate->nodes)
{
- newstate->entrance_nodes = re_malloc (re_node_set, 1);
- if (__glibc_unlikely (newstate->entrance_nodes == NULL))
+ re_node_set *entrance_nodes = re_malloc (re_node_set, 1);
+ if (__glibc_unlikely (entrance_nodes == NULL))
{
free_state (newstate);
return NULL;
}
+ newstate->entrance_nodes = entrance_nodes;
if (re_node_set_init_copy (newstate->entrance_nodes, nodes)
!= REG_NOERROR)
- return NULL;
+ {
+ free_state (newstate);
+ return NULL;
+ }
nctx_nodes = 0;
newstate->has_constraint = 1;
}
diff --git a/lib/regex_internal.h b/lib/regex_internal.h
index b0e49cd..5c9cbf3 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -20,7 +20,6 @@
#ifndef _REGEX_INTERNAL_H
#define _REGEX_INTERNAL_H 1
-#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,6 +33,14 @@
#include <stdint.h>
#include <intprops.h>
+#include <verify.h>
+
+#if defined DEBUG && DEBUG != 0
+# include <assert.h>
+# define DEBUG_ASSERT(x) assert (x)
+#else
+# define DEBUG_ASSERT(x) assume (x)
+#endif
#ifdef _LIBC
# include <libc-lock.h>
@@ -44,22 +51,7 @@
# define lock_unlock(lock) __libc_lock_unlock (lock)
#elif defined GNULIB_LOCK && !defined USE_UNLOCKED_IO
# include "glthread/lock.h"
- /* Use gl_lock_define if empty macro arguments are known to work.
- Otherwise, fall back on less-portable substitutes. */
-# if ((defined __GNUC__ && !defined __STRICT_ANSI__) \
- || (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__))
-# define lock_define(name) gl_lock_define (, name)
-# elif USE_POSIX_THREADS
-# define lock_define(name) pthread_mutex_t name;
-# elif USE_PTH_THREADS
-# define lock_define(name) pth_mutex_t name;
-# elif USE_SOLARIS_THREADS
-# define lock_define(name) mutex_t name;
-# elif USE_WINDOWS_THREADS
-# define lock_define(name) gl_lock_t name;
-# else
-# define lock_define(name)
-# endif
+# define lock_define(name) gl_lock_define (, name)
# define lock_init(lock) glthread_lock_init (&(lock))
# define lock_fini(lock) glthread_lock_destroy (&(lock))
# define lock_lock(lock) glthread_lock_lock (&(lock))
@@ -144,13 +136,8 @@
# define __mbrtowc mbrtowc
# define __wcrtomb wcrtomb
# define __regfree regfree
-# define attribute_hidden
#endif /* not _LIBC */
-#if __GNUC__ < 3 + (__GNUC_MINOR__ < 1)
-# define __attribute__(arg)
-#endif
-
#ifndef SSIZE_MAX
# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
#endif
@@ -623,11 +610,7 @@ typedef struct
{
/* The string object corresponding to the input string. */
re_string_t input;
-#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
const re_dfa_t *const dfa;
-#else
- const re_dfa_t *dfa;
-#endif
/* EFLAGS of the argument of regexec. */
int eflags;
/* Where the matching ends. */
@@ -868,23 +851,6 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
}
#endif /* RE_ENABLE_I18N */
-#ifndef __GNUC_PREREQ
-# if defined __GNUC__ && defined __GNUC_MINOR__
-# define __GNUC_PREREQ(maj, min) \
- ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-# else
-# define __GNUC_PREREQ(maj, min) 0
-# endif
-#endif
-
-#if __GNUC_PREREQ (3,4)
-# undef __attribute_warn_unused_result__
-# define __attribute_warn_unused_result__ \
- __attribute__ ((__warn_unused_result__))
-#else
-# define __attribute_warn_unused_result__ /* empty */
-#endif
-
#ifndef FALLTHROUGH
# if __GNUC__ < 7
# define FALLTHROUGH ((void) 0)
diff --git a/lib/regexec.c b/lib/regexec.c
index c7d099c..395e37d 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -1,5 +1,5 @@
/* Extended regular expression matching and search library.
- Copyright (C) 2002-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
@@ -189,7 +189,7 @@ static reg_errcode_t extend_buffers (re_match_context_t *mctx, int min_len);
We return 0 if we find a match and REG_NOMATCH if not. */
int
-regexec (const regex_t *_Restrict_ preg, const char *_Restrict_ string,
+regexec (const regex_t *__restrict preg, const char *__restrict string,
size_t nmatch, regmatch_t pmatch[], int eflags)
{
reg_errcode_t err;
@@ -232,8 +232,8 @@ __typeof__ (__regexec) __compat_regexec;
int
attribute_compat_text_section
-__compat_regexec (const regex_t *_Restrict_ preg,
- const char *_Restrict_ string, size_t nmatch,
+__compat_regexec (const regex_t *__restrict preg,
+ const char *__restrict string, size_t nmatch,
regmatch_t pmatch[], int eflags)
{
return regexec (preg, string, nmatch, pmatch,
@@ -443,7 +443,7 @@ re_search_stub (struct re_pattern_buffer *bufp, const char *string, Idx length,
{
if (ret_len)
{
- assert (pmatch[0].rm_so == start);
+ DEBUG_ASSERT (pmatch[0].rm_so == start);
rval = pmatch[0].rm_eo - start;
}
else
@@ -502,9 +502,9 @@ re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs,
}
else
{
- assert (regs_allocated == REGS_FIXED);
+ DEBUG_ASSERT (regs_allocated == REGS_FIXED);
/* This function may not be called with REGS_FIXED and nregs too big. */
- assert (regs->num_regs >= nregs);
+ DEBUG_ASSERT (nregs <= regs->num_regs);
rval = REGS_FIXED;
}
@@ -597,21 +597,12 @@ re_search_internal (const regex_t *preg, const char *string, Idx length,
Idx extra_nmatch;
bool sb;
int ch;
-#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
re_match_context_t mctx = { .dfa = dfa };
-#else
- re_match_context_t mctx;
-#endif
char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate
&& start != last_start && !preg->can_be_null)
? preg->fastmap : NULL);
RE_TRANSLATE_TYPE t = preg->translate;
-#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
- memset (&mctx, '\0', sizeof (re_match_context_t));
- mctx.dfa = dfa;
-#endif
-
extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
nmatch -= extra_nmatch;
@@ -622,10 +613,8 @@ re_search_internal (const regex_t *preg, const char *string, Idx length,
|| dfa->init_state_begbuf == NULL))
return REG_NOMATCH;
-#ifdef DEBUG
/* We assume front-end functions already check them. */
- assert (0 <= last_start && last_start <= length);
-#endif
+ DEBUG_ASSERT (0 <= last_start && last_start <= length);
/* If initial states with non-begbuf contexts have no elements,
the regex must be anchored. If preg->newline_anchor is set,
@@ -677,8 +666,6 @@ re_search_internal (const regex_t *preg, const char *string, Idx length,
goto free_return;
}
}
- else
- mctx.state_log = NULL;
match_first = start;
mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
@@ -838,10 +825,8 @@ re_search_internal (const regex_t *preg, const char *string, Idx length,
match_ctx_clean (&mctx);
}
-#ifdef DEBUG
- assert (match_last != -1);
- assert (err == REG_NOERROR);
-#endif
+ DEBUG_ASSERT (match_last != -1);
+ DEBUG_ASSERT (err == REG_NOERROR);
/* Set pmatch[] if we need. */
if (nmatch > 0)
@@ -886,7 +871,7 @@ re_search_internal (const regex_t *preg, const char *string, Idx length,
: mctx.input.offsets[pmatch[reg_idx].rm_eo]);
}
#else
- assert (mctx.input.offsets_needed == 0);
+ DEBUG_ASSERT (mctx.input.offsets_needed == 0);
#endif
pmatch[reg_idx].rm_so += match_first;
pmatch[reg_idx].rm_eo += match_first;
@@ -926,9 +911,7 @@ prune_impossible_nodes (re_match_context_t *mctx)
re_dfastate_t **sifted_states;
re_dfastate_t **lim_states = NULL;
re_sift_context_t sctx;
-#ifdef DEBUG
- assert (mctx->state_log != NULL);
-#endif
+ DEBUG_ASSERT (mctx->state_log != NULL);
match_last = mctx->match_last;
halt_node = mctx->last_node;
@@ -1074,7 +1057,7 @@ check_matching (re_match_context_t *mctx, bool fl_longest_match,
/* An initial state must not be NULL (invalid). */
if (__glibc_unlikely (cur_state == NULL))
{
- assert (err == REG_ESPACE);
+ DEBUG_ASSERT (err == REG_ESPACE);
return -2;
}
@@ -1129,7 +1112,7 @@ check_matching (re_match_context_t *mctx, bool fl_longest_match,
err = extend_buffers (mctx, next_char_idx + 1);
if (__glibc_unlikely (err != REG_NOERROR))
{
- assert (err == REG_ESPACE);
+ DEBUG_ASSERT (err == REG_ESPACE);
return -2;
}
}
@@ -1212,9 +1195,7 @@ check_halt_state_context (const re_match_context_t *mctx,
{
Idx i;
unsigned int context;
-#ifdef DEBUG
- assert (state->halt);
-#endif
+ DEBUG_ASSERT (state->halt);
context = re_string_context_at (&mctx->input, idx, mctx->eflags);
for (i = 0; i < state->nodes.nelem; ++i)
if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))
@@ -1285,16 +1266,21 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
if (type == OP_BACK_REF)
{
Idx subexp_idx = dfa->nodes[node].opr.idx + 1;
- naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
+ if (subexp_idx < nregs)
+ naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
if (fs != NULL)
{
- if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
+ if (subexp_idx >= nregs
+ || regs[subexp_idx].rm_so == -1
+ || regs[subexp_idx].rm_eo == -1)
return -1;
else if (naccepted)
{
char *buf = (char *) re_string_get_buffer (&mctx->input);
- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
- naccepted) != 0)
+ if (mctx->input.valid_len - *pidx < naccepted
+ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
+ naccepted)
+ != 0))
return -1;
}
}
@@ -1360,7 +1346,7 @@ pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
regmatch_t *regs, re_node_set *eps_via_nodes)
{
Idx num = --fs->num;
- assert (num >= 0);
+ DEBUG_ASSERT (num >= 0);
*pidx = fs->stack[num].idx;
memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
re_node_set_free (eps_via_nodes);
@@ -1387,10 +1373,8 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
regmatch_t *prev_idx_match;
bool prev_idx_match_malloced = false;
-#ifdef DEBUG
- assert (nmatch > 1);
- assert (mctx->state_log != NULL);
-#endif
+ DEBUG_ASSERT (nmatch > 1);
+ DEBUG_ASSERT (mctx->state_log != NULL);
if (fl_backtrack)
{
fs = &fs_body;
@@ -1576,9 +1560,7 @@ sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
Idx str_idx = sctx->last_str_idx;
re_node_set cur_dest;
-#ifdef DEBUG
- assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
-#endif
+ DEBUG_ASSERT (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
/* Build sifted state_log[str_idx]. It has the nodes which can epsilon
transit to the last_node and the last_node itself. */
@@ -1646,11 +1628,8 @@ build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
Idx prev_node = cur_src->elems[i];
int naccepted = 0;
bool ok;
+ DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[prev_node].type));
-#ifdef DEBUG
- re_token_type_t type = dfa->nodes[prev_node].type;
- assert (!IS_EPSILON_NODE (type));
-#endif
#ifdef RE_ENABLE_I18N
/* If the node may accept "multi byte". */
if (dfa->nodes[prev_node].accept_mb)
@@ -2202,12 +2181,12 @@ sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
int naccepted;
/* Check the node can accept "multi byte". */
naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
- if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
- !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
- dfa->nexts[node_idx]))
+ if (naccepted > 0 && str_idx + naccepted <= max_str_idx
+ && !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
+ dfa->nexts[node_idx]))
/* The node can't accept the "multi byte", or the
destination was already thrown away, then the node
- could't accept the current input "multi byte". */
+ couldn't accept the current input "multi byte". */
naccepted = 0;
/* Otherwise, it is sure that the node could accept
'naccepted' bytes input. */
@@ -2503,9 +2482,7 @@ transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
err = clean_state_log_if_needed (mctx, dest_idx);
if (__glibc_unlikely (err != REG_NOERROR))
return err;
-#ifdef DEBUG
- assert (dfa->nexts[cur_node_idx] != -1);
-#endif
+ DEBUG_ASSERT (dfa->nexts[cur_node_idx] != -1);
new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
dest_state = mctx->state_log[dest_idx];
@@ -2569,9 +2546,7 @@ transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
/* And add the epsilon closures (which is 'new_dest_nodes') of
the backreference to appropriate state_log. */
-#ifdef DEBUG
- assert (dfa->nexts[node_idx] != -1);
-#endif
+ DEBUG_ASSERT (dfa->nexts[node_idx] != -1);
for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
{
Idx subexp_len;
@@ -3030,10 +3005,8 @@ check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx,
{
int naccepted = 0;
Idx cur_node = cur_nodes->elems[cur_idx];
-#ifdef DEBUG
- re_token_type_t type = dfa->nodes[cur_node].type;
- assert (!IS_EPSILON_NODE (type));
-#endif
+ DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[cur_node].type));
+
#ifdef RE_ENABLE_I18N
/* If the node may accept "multi byte". */
if (dfa->nodes[cur_node].accept_mb)
@@ -3101,9 +3074,7 @@ check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
reg_errcode_t err;
Idx idx, outside_node;
re_node_set new_nodes;
-#ifdef DEBUG
- assert (cur_nodes->nelem);
-#endif
+ DEBUG_ASSERT (cur_nodes->nelem);
err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
if (__glibc_unlikely (err != REG_NOERROR))
return err;
@@ -3693,6 +3664,7 @@ group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
bitset_empty (accepts);
}
}
+ assume (ndests <= SBC_MAX);
return ndests;
error_return:
for (j = 0; j < ndests; ++j)
@@ -3780,10 +3752,10 @@ check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
/* FIXME: I don't think this if is needed, as both '\n'
and '\0' are char_len == 1. */
/* '.' accepts any one character except the following two cases. */
- if ((!(dfa->syntax & RE_DOT_NEWLINE) &&
- re_string_byte_at (input, str_idx) == '\n') ||
- ((dfa->syntax & RE_DOT_NOT_NULL) &&
- re_string_byte_at (input, str_idx) == '\0'))
+ if ((!(dfa->syntax & RE_DOT_NEWLINE)
+ && re_string_byte_at (input, str_idx) == '\n')
+ || ((dfa->syntax & RE_DOT_NOT_NULL)
+ && re_string_byte_at (input, str_idx) == '\0'))
return 0;
return char_len;
}
@@ -4270,10 +4242,8 @@ static reg_errcode_t
__attribute_warn_unused_result__
match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx)
{
-#ifdef DEBUG
- assert (mctx->sub_tops != NULL);
- assert (mctx->asub_tops > 0);
-#endif
+ DEBUG_ASSERT (mctx->sub_tops != NULL);
+ DEBUG_ASSERT (mctx->asub_tops > 0);
if (__glibc_unlikely (mctx->nsub_tops == mctx->asub_tops))
{
Idx new_asub_tops = mctx->asub_tops * 2;
diff --git a/lib/rename.c b/lib/rename.c
index 0b457aa..09881e8 100644
--- a/lib/rename.c
+++ b/lib/rename.c
@@ -1,6 +1,6 @@
/* Work around rename bugs in some systems.
- Copyright (C) 2001-2003, 2005-2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2003, 2005-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
diff --git a/lib/rmdir.c b/lib/rmdir.c
index 7dc7aec..2f517cc 100644
--- a/lib/rmdir.c
+++ b/lib/rmdir.c
@@ -1,6 +1,6 @@
/* Work around rmdir bugs.
- Copyright (C) 1988, 1990, 1999, 2003-2006, 2009-2018 Free Software
+ Copyright (C) 1988, 1990, 1999, 2003-2006, 2009-2020 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/same-inode.h b/lib/same-inode.h
index 6837795..09c339a 100644
--- a/lib/same-inode.h
+++ b/lib/same-inode.h
@@ -1,6 +1,6 @@
/* Determine whether two stat buffers are known to refer to the same file.
- Copyright (C) 2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
diff --git a/lib/se-selinux.in.h b/lib/se-selinux.in.h
index f7610b3..05a766c 100644
--- a/lib/se-selinux.in.h
+++ b/lib/se-selinux.in.h
@@ -1,5 +1,5 @@
/* Replacement <selinux/selinux.h> for platforms that lack it.
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/set-acl.c b/lib/set-acl.c
index 830beb1..b68268f 100644
--- a/lib/set-acl.c
+++ b/lib/set-acl.c
@@ -1,6 +1,6 @@
/* set-acl.c - set access control list equivalent to a mode
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/set-permissions.c b/lib/set-permissions.c
index a415e13..b22ccfd 100644
--- a/lib/set-permissions.c
+++ b/lib/set-permissions.c
@@ -1,6 +1,6 @@
/* Set permissions of a file. -*- coding: utf-8 -*-
- Copyright (C) 2002-2003, 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2002-2003, 2005-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
diff --git a/lib/setlocale-lock.c b/lib/setlocale-lock.c
new file mode 100644
index 0000000..7dde32d
--- /dev/null
+++ b/lib/setlocale-lock.c
@@ -0,0 +1,150 @@
+/* Return the internal lock used by setlocale_null_r.
+ Copyright (C) 2019-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 Bruno Haible <bruno@clisp.org>, 2019. */
+
+#include <config.h>
+
+/* When it is known that the gl_get_setlocale_null_lock function is defined
+ by a dependency library, it should not be defined here. */
+#if OMIT_SETLOCALE_LOCK
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
+
+#else
+
+/* This file defines the internal lock used by setlocale_null_r.
+ It is a separate compilation unit, so that only one copy of it is
+ present when linking statically. */
+
+/* Prohibit renaming this symbol. */
+# undef gl_get_setlocale_null_lock
+
+/* Macro for exporting a symbol (function, not variable) defined in this file,
+ when compiled into a shared library. */
+# ifndef DLL_EXPORTED
+# if HAVE_VISIBILITY
+ /* Override the effect of the compiler option '-fvisibility=hidden'. */
+# define DLL_EXPORTED __attribute__((__visibility__("default")))
+# elif defined _WIN32 || defined __CYGWIN__
+# define DLL_EXPORTED __declspec(dllexport)
+# else
+# define DLL_EXPORTED
+# endif
+# endif
+
+# if defined _WIN32 && !defined __CYGWIN__
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# include "windows-initguard.h"
+
+/* The return type is a 'CRITICAL_SECTION *', not a 'glwthread_mutex_t *',
+ because the latter is not guaranteed to be a stable ABI in the future. */
+
+/* Make sure the function gets exported from DLLs. */
+DLL_EXPORTED CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
+
+static glwthread_initguard_t guard = GLWTHREAD_INITGUARD_INIT;
+static CRITICAL_SECTION lock;
+
+/* Returns the internal lock used by setlocale_null_r. */
+CRITICAL_SECTION *
+gl_get_setlocale_null_lock (void)
+{
+ if (!guard.done)
+ {
+ if (InterlockedIncrement (&guard.started) == 0)
+ {
+ /* This thread is the first one to need the lock. Initialize it. */
+ InitializeCriticalSection (&lock);
+ guard.done = 1;
+ }
+ else
+ {
+ /* Don't let guard.started grow and wrap around. */
+ InterlockedDecrement (&guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this mutex. */
+ while (!guard.done)
+ Sleep (0);
+ }
+ }
+ return &lock;
+}
+
+# elif HAVE_PTHREAD_API
+
+# include <pthread.h>
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Make sure the function gets exported from shared libraries. */
+DLL_EXPORTED pthread_mutex_t *gl_get_setlocale_null_lock (void);
+
+/* Returns the internal lock used by setlocale_null_r. */
+pthread_mutex_t *
+gl_get_setlocale_null_lock (void)
+{
+ return &mutex;
+}
+
+# elif HAVE_THREADS_H
+
+# include <threads.h>
+# include <stdlib.h>
+
+static int volatile init_needed = 1;
+static once_flag init_once = ONCE_FLAG_INIT;
+static mtx_t mutex;
+
+static void
+atomic_init (void)
+{
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ abort ();
+ init_needed = 0;
+}
+
+/* Make sure the function gets exported from shared libraries. */
+DLL_EXPORTED mtx_t *gl_get_setlocale_null_lock (void);
+
+/* Returns the internal lock used by setlocale_null_r. */
+mtx_t *
+gl_get_setlocale_null_lock (void)
+{
+ if (init_needed)
+ call_once (&init_once, atomic_init);
+ return &mutex;
+}
+
+# endif
+
+# if (defined _WIN32 || defined __CYGWIN__) && !defined _MSC_VER
+/* Make sure the '__declspec(dllimport)' in setlocale_null.c does not cause
+ a link failure when no DLLs are involved. */
+# if defined _WIN64 || defined _LP64
+# define IMP(x) __imp_##x
+# else
+# define IMP(x) _imp__##x
+# endif
+void * IMP(gl_get_setlocale_null_lock) = &gl_get_setlocale_null_lock;
+# endif
+
+#endif
diff --git a/lib/setlocale_null.c b/lib/setlocale_null.c
new file mode 100644
index 0000000..abe55b5
--- /dev/null
+++ b/lib/setlocale_null.c
@@ -0,0 +1,411 @@
+/* Query the name of the current global locale.
+ Copyright (C) 2019-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 Bruno Haible <bruno@clisp.org>, 2019. */
+
+#include <config.h>
+
+/* Specification. */
+#include "setlocale_null.h"
+
+#include <errno.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#if defined _WIN32 && !defined __CYGWIN__
+# include <wchar.h>
+#endif
+
+#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
+# if defined _WIN32 && !defined __CYGWIN__
+
+# define WIN32_LEAN_AND_MEAN /* avoid including junk */
+# include <windows.h>
+
+# elif HAVE_PTHREAD_API
+
+# include <pthread.h>
+# if HAVE_THREADS_H && HAVE_WEAK_SYMBOLS
+# include <threads.h>
+# pragma weak thrd_exit
+# define c11_threads_in_use() (thrd_exit != NULL)
+# else
+# define c11_threads_in_use() 0
+# endif
+
+# elif HAVE_THREADS_H
+
+# include <threads.h>
+
+# endif
+#endif
+
+/* Use the system's setlocale() function, not the gnulib override, here. */
+#undef setlocale
+
+static const char *
+setlocale_null_androidfix (int category)
+{
+ const char *result = setlocale (category, NULL);
+
+#ifdef __ANDROID__
+ if (result == NULL)
+ switch (category)
+ {
+ case LC_CTYPE:
+ case LC_NUMERIC:
+ case LC_TIME:
+ case LC_COLLATE:
+ case LC_MONETARY:
+ case LC_MESSAGES:
+ case LC_ALL:
+ case LC_PAPER:
+ case LC_NAME:
+ case LC_ADDRESS:
+ case LC_TELEPHONE:
+ case LC_MEASUREMENT:
+ result = "C";
+ break;
+ default:
+ break;
+ }
+#endif
+
+ return result;
+}
+
+static int
+setlocale_null_unlocked (int category, char *buf, size_t bufsize)
+{
+#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
+ /* On native Windows, nowadays, the setlocale() implementation is based
+ on _wsetlocale() and uses malloc() for the result. We are better off
+ using _wsetlocale() directly. */
+ const wchar_t *result = _wsetlocale (category, NULL);
+
+ if (result == NULL)
+ {
+ /* CATEGORY is invalid. */
+ if (bufsize > 0)
+ /* Return an empty string in BUF.
+ This is a convenience for callers that don't want to write explicit
+ code for handling EINVAL. */
+ buf[0] = '\0';
+ return EINVAL;
+ }
+ else
+ {
+ size_t length = wcslen (result);
+ if (length < bufsize)
+ {
+ size_t i;
+
+ /* Convert wchar_t[] -> char[], assuming plain ASCII. */
+ for (i = 0; i <= length; i++)
+ buf[i] = result[i];
+
+ return 0;
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ /* Return a truncated result in BUF.
+ This is a convenience for callers that don't want to write
+ explicit code for handling ERANGE. */
+ size_t i;
+
+ /* Convert wchar_t[] -> char[], assuming plain ASCII. */
+ for (i = 0; i < bufsize; i++)
+ buf[i] = result[i];
+ buf[bufsize - 1] = '\0';
+ }
+ return ERANGE;
+ }
+ }
+#else
+ const char *result = setlocale_null_androidfix (category);
+
+ if (result == NULL)
+ {
+ /* CATEGORY is invalid. */
+ if (bufsize > 0)
+ /* Return an empty string in BUF.
+ This is a convenience for callers that don't want to write explicit
+ code for handling EINVAL. */
+ buf[0] = '\0';
+ return EINVAL;
+ }
+ else
+ {
+ size_t length = strlen (result);
+ if (length < bufsize)
+ {
+ memcpy (buf, result, length + 1);
+ return 0;
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ /* Return a truncated result in BUF.
+ This is a convenience for callers that don't want to write
+ explicit code for handling ERANGE. */
+ memcpy (buf, result, bufsize - 1);
+ buf[bufsize - 1] = '\0';
+ }
+ return ERANGE;
+ }
+ }
+#endif
+}
+
+#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
+
+/* Use a lock, so that no two threads can invoke setlocale_null_unlocked
+ at the same time. */
+
+/* Prohibit renaming this symbol. */
+# undef gl_get_setlocale_null_lock
+
+# if defined _WIN32 && !defined __CYGWIN__
+
+extern __declspec(dllimport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
+
+static int
+setlocale_null_with_lock (int category, char *buf, size_t bufsize)
+{
+ CRITICAL_SECTION *lock = gl_get_setlocale_null_lock ();
+ int ret;
+
+ EnterCriticalSection (lock);
+ ret = setlocale_null_unlocked (category, buf, bufsize);
+ LeaveCriticalSection (lock);
+
+ return ret;
+}
+
+# elif HAVE_PTHREAD_API /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
+
+extern
+# if defined _WIN32 || defined __CYGWIN__
+ __declspec(dllimport)
+# endif
+ pthread_mutex_t *gl_get_setlocale_null_lock (void);
+
+# if HAVE_WEAK_SYMBOLS /* musl libc, FreeBSD, NetBSD, OpenBSD, Haiku */
+
+ /* Avoid the need to link with '-lpthread'. */
+# pragma weak pthread_mutex_lock
+# pragma weak pthread_mutex_unlock
+
+ /* Determine whether libpthread is in use. */
+# pragma weak pthread_mutexattr_gettype
+ /* See the comments in lock.h. */
+# define pthread_in_use() \
+ (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
+
+# else
+# define pthread_in_use() 1
+# endif
+
+static int
+setlocale_null_with_lock (int category, char *buf, size_t bufsize)
+{
+ if (pthread_in_use())
+ {
+ pthread_mutex_t *lock = gl_get_setlocale_null_lock ();
+ int ret;
+
+ if (pthread_mutex_lock (lock))
+ abort ();
+ ret = setlocale_null_unlocked (category, buf, bufsize);
+ if (pthread_mutex_unlock (lock))
+ abort ();
+
+ return ret;
+ }
+ else
+ return setlocale_null_unlocked (category, buf, bufsize);
+}
+
+# elif HAVE_THREADS_H
+
+extern mtx_t *gl_get_setlocale_null_lock (void);
+
+static int
+setlocale_null_with_lock (int category, char *buf, size_t bufsize)
+{
+ mtx_t *lock = gl_get_setlocale_null_lock ();
+ int ret;
+
+ if (mtx_lock (lock) != thrd_success)
+ abort ();
+ ret = setlocale_null_unlocked (category, buf, bufsize);
+ if (mtx_unlock (lock) != thrd_success)
+ abort ();
+
+ return ret;
+}
+
+# endif
+
+#endif
+
+int
+setlocale_null_r (int category, char *buf, size_t bufsize)
+{
+#if SETLOCALE_NULL_ALL_MTSAFE
+# if SETLOCALE_NULL_ONE_MTSAFE
+
+ return setlocale_null_unlocked (category, buf, bufsize);
+
+# else
+
+ if (category == LC_ALL)
+ return setlocale_null_unlocked (category, buf, bufsize);
+ else
+ return setlocale_null_with_lock (category, buf, bufsize);
+
+# endif
+#else
+# if SETLOCALE_NULL_ONE_MTSAFE
+
+ if (category == LC_ALL)
+ return setlocale_null_with_lock (category, buf, bufsize);
+ else
+ return setlocale_null_unlocked (category, buf, bufsize);
+
+# else
+
+ return setlocale_null_with_lock (category, buf, bufsize);
+
+# endif
+#endif
+}
+
+const char *
+setlocale_null (int category)
+{
+#if SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE
+ return setlocale_null_androidfix (category);
+#else
+
+ /* This call must be multithread-safe. To achieve this without using
+ thread-local storage:
+ 1. We use a specific static buffer for each possible CATEGORY
+ argument. So that different threads can call setlocale_mtsafe
+ with different CATEGORY arguments, without interfering.
+ 2. We use a simple strcpy or memcpy to fill this static buffer.
+ Filling it through, for example, strcpy + strcat would not be
+ guaranteed to leave the buffer's contents intact if another thread
+ is currently accessing it. If necessary, the contents is first
+ assembled in a stack-allocated buffer. */
+ if (category == LC_ALL)
+ {
+# if SETLOCALE_NULL_ALL_MTSAFE
+ return setlocale_null_androidfix (LC_ALL);
+# else
+ char buf[SETLOCALE_NULL_ALL_MAX];
+ static char resultbuf[SETLOCALE_NULL_ALL_MAX];
+
+ if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
+ return "C";
+ strcpy (resultbuf, buf);
+ return resultbuf;
+# endif
+ }
+ else
+ {
+# if SETLOCALE_NULL_ONE_MTSAFE
+ return setlocale_null_androidfix (category);
+# else
+ enum
+ {
+ LC_CTYPE_INDEX,
+ LC_NUMERIC_INDEX,
+ LC_TIME_INDEX,
+ LC_COLLATE_INDEX,
+ LC_MONETARY_INDEX,
+ LC_MESSAGES_INDEX,
+# ifdef LC_PAPER
+ LC_PAPER_INDEX,
+# endif
+# ifdef LC_NAME
+ LC_NAME_INDEX,
+# endif
+# ifdef LC_ADDRESS
+ LC_ADDRESS_INDEX,
+# endif
+# ifdef LC_TELEPHONE
+ LC_TELEPHONE_INDEX,
+# endif
+# ifdef LC_MEASUREMENT
+ LC_MEASUREMENT_INDEX,
+# endif
+# ifdef LC_IDENTIFICATION
+ LC_IDENTIFICATION_INDEX,
+# endif
+ LC_INDICES_COUNT
+ }
+ i;
+ char buf[SETLOCALE_NULL_MAX];
+ static char resultbuf[LC_INDICES_COUNT][SETLOCALE_NULL_MAX];
+ int err;
+
+ err = setlocale_null_r (category, buf, sizeof (buf));
+ if (err == EINVAL)
+ return NULL;
+ if (err)
+ return "C";
+
+ switch (category)
+ {
+ case LC_CTYPE: i = LC_CTYPE_INDEX; break;
+ case LC_NUMERIC: i = LC_NUMERIC_INDEX; break;
+ case LC_TIME: i = LC_TIME_INDEX; break;
+ case LC_COLLATE: i = LC_COLLATE_INDEX; break;
+ case LC_MONETARY: i = LC_MONETARY_INDEX; break;
+ case LC_MESSAGES: i = LC_MESSAGES_INDEX; break;
+# ifdef LC_PAPER
+ case LC_PAPER: i = LC_PAPER_INDEX; break;
+# endif
+# ifdef LC_NAME
+ case LC_NAME: i = LC_NAME_INDEX; break;
+# endif
+# ifdef LC_ADDRESS
+ case LC_ADDRESS: i = LC_ADDRESS_INDEX; break;
+# endif
+# ifdef LC_TELEPHONE
+ case LC_TELEPHONE: i = LC_TELEPHONE_INDEX; break;
+# endif
+# ifdef LC_MEASUREMENT
+ case LC_MEASUREMENT: i = LC_MEASUREMENT_INDEX; break;
+# endif
+# ifdef LC_IDENTIFICATION
+ case LC_IDENTIFICATION: i = LC_IDENTIFICATION_INDEX; break;
+# endif
+ default:
+ /* If you get here, a #ifdef LC_xxx is missing. */
+ abort ();
+ }
+
+ strcpy (resultbuf[i], buf);
+ return resultbuf[i];
+# endif
+ }
+#endif
+}
diff --git a/lib/setlocale_null.h b/lib/setlocale_null.h
new file mode 100644
index 0000000..6844be5
--- /dev/null
+++ b/lib/setlocale_null.h
@@ -0,0 +1,82 @@
+/* Query the name of the current global locale.
+ Copyright (C) 2019-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 Bruno Haible <bruno@clisp.org>, 2019. */
+
+#ifndef _SETLOCALE_NULL_H
+#define _SETLOCALE_NULL_H
+
+#include <stddef.h>
+
+#include "arg-nonnull.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Recommended size of a buffer for a locale name for a single category.
+ On glibc systems, you can have locale names that are relative file names;
+ assume a maximum length 256.
+ In native Windows, in 2018 the longest locale name was of length 58
+ ("FYRO Macedonian_Former Yugoslav Republic of Macedonia.1251"). */
+#define SETLOCALE_NULL_MAX (256+1)
+
+/* Recommended size of a buffer for a locale name with all categories.
+ On glibc systems, you can have locale names that are relative file names;
+ assume maximum length 256 for each. There are 12 categories; so, the
+ maximum total length is 148+12*256.
+ In native Windows, there are 5 categories, and the maximum total length is
+ 55+5*58. */
+#define SETLOCALE_NULL_ALL_MAX (148+12*256+1)
+
+/* setlocale_null_r (CATEGORY, BUF, BUFSIZE) is like setlocale (CATEGORY, NULL),
+ except that
+ - it is guaranteed to be multithread-safe,
+ - it returns the resulting locale category name or locale name in the
+ user-supplied buffer BUF, which must be BUFSIZE bytes long.
+ The recommended minimum buffer size is
+ - SETLOCALE_NULL_MAX for CATEGORY != LC_ALL, and
+ - SETLOCALE_NULL_ALL_MAX for CATEGORY == LC_ALL.
+ The return value is an error code: 0 if the call is successful, EINVAL if
+ CATEGORY is invalid, or ERANGE if BUFSIZE is smaller than the length needed
+ size (including the trailing NUL byte). In the latter case, a truncated
+ result is returned in BUF, but still NUL-terminated if BUFSIZE > 0.
+ For this call to be multithread-safe, *all* calls to
+ setlocale (CATEGORY, NULL) in all other threads must have been converted
+ to use setlocale_null_r or setlocale_null as well, and the other threads
+ must not make other setlocale invocations (since changing the global locale
+ has side effects on all threads). */
+extern int setlocale_null_r (int category, char *buf, size_t bufsize)
+ _GL_ARG_NONNULL ((2));
+
+/* setlocale_null (CATEGORY) is like setlocale (CATEGORY, NULL), except that
+ it is guaranteed to be multithread-safe.
+ The return value is NULL if CATEGORY is invalid.
+ For this call to be multithread-safe, *all* calls to
+ setlocale (CATEGORY, NULL) in all other threads must have been converted
+ to use setlocale_null_r or setlocale_null as well, and the other threads
+ must not make other setlocale invocations (since changing the global locale
+ has side effects on all threads). */
+extern const char *setlocale_null (int category);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SETLOCALE_NULL_H */
diff --git a/lib/stat-time.h b/lib/stat-time.h
index 69ebe85..884ffd8 100644
--- a/lib/stat-time.h
+++ b/lib/stat-time.h
@@ -1,6 +1,6 @@
/* stat-related time functions.
- Copyright (C) 2005, 2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2007, 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
@@ -171,7 +171,7 @@ get_stat_birthtime (struct stat const *st _GL_UNUSED)
#elif defined _WIN32 && ! defined __CYGWIN__
/* Native Windows platforms (but not Cygwin) put the "file creation
time" in st_ctime (!). See
- <https://msdn.microsoft.com/en-us/library/14h5k7ff(VS.80).aspx>. */
+ <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions>. */
# if _GL_WINDOWS_STAT_TIMESPEC
t = st->st_ctim;
# else
diff --git a/lib/stat-w32.c b/lib/stat-w32.c
index c7a53f9..296ccf1 100644
--- a/lib/stat-w32.c
+++ b/lib/stat-w32.c
@@ -1,5 +1,5 @@
/* Core of implementation of fstat and stat for native Windows.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ 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
@@ -80,7 +80,7 @@ struct timespec
_gl_convert_FILETIME_to_timespec (const FILETIME *ft)
{
struct timespec result;
- /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
+ /* FILETIME: <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
unsigned long long since_1601 =
((unsigned long long) ft->dwHighDateTime << 32)
| (unsigned long long) ft->dwLowDateTime;
@@ -104,7 +104,7 @@ _gl_convert_FILETIME_to_timespec (const FILETIME *ft)
time_t
_gl_convert_FILETIME_to_POSIX (const FILETIME *ft)
{
- /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
+ /* FILETIME: <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-filetime> */
unsigned long long since_1601 =
((unsigned long long) ft->dwHighDateTime << 32)
| (unsigned long long) ft->dwLowDateTime;
@@ -128,7 +128,7 @@ int
_gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
{
/* GetFileType
- <https://msdn.microsoft.com/en-us/library/aa364960.aspx> */
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype> */
DWORD type = GetFileType (h);
if (type == FILE_TYPE_DISK)
{
@@ -137,16 +137,16 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
/* st_mode can be determined through
GetFileAttributesEx
- <https://msdn.microsoft.com/en-us/library/aa364946.aspx>
- <https://msdn.microsoft.com/en-us/library/aa365739.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileattributesexa>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_win32_file_attribute_data>
or through
GetFileInformationByHandle
- <https://msdn.microsoft.com/en-us/library/aa364952.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363788.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information>
or through
GetFileInformationByHandleEx with argument FileBasicInfo
- <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
- <https://msdn.microsoft.com/en-us/library/aa364217.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_basic_info>
The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
BY_HANDLE_FILE_INFORMATION info;
if (! GetFileInformationByHandle (h, &info))
@@ -162,12 +162,12 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
#if _GL_WINDOWS_STAT_INODES
/* st_ino can be determined through
GetFileInformationByHandle
- <https://msdn.microsoft.com/en-us/library/aa364952.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363788.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information>
as 64 bits, or through
GetFileInformationByHandleEx with argument FileIdInfo
- <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
- <https://msdn.microsoft.com/en-us/library/hh802691.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_id_info>
as 128 bits.
The latter requires -D_WIN32_WINNT=_WIN32_WINNT_WIN8 or higher. */
/* Experiments show that GetFileInformationByHandleEx does not provide
@@ -238,11 +238,11 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
If the file name is already known, use it. Otherwise, for
non-empty files, it can be determined through
GetFinalPathNameByHandle
- <https://msdn.microsoft.com/en-us/library/aa364962.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfinalpathnamebyhandlea>
or through
GetFileInformationByHandleEx with argument FileNameInfo
- <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
- <https://msdn.microsoft.com/en-us/library/aa364388.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_name_info>
Both require -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0)
{
@@ -277,12 +277,12 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
/* st_nlink can be determined through
GetFileInformationByHandle
- <https://msdn.microsoft.com/en-us/library/aa364952.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363788.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information>
or through
GetFileInformationByHandleEx with argument FileStandardInfo
- <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
- <https://msdn.microsoft.com/en-us/library/aa364401.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_standard_info>
The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
buf->st_nlink = (info.nNumberOfLinks > SHRT_MAX ? SHRT_MAX : info.nNumberOfLinks);
@@ -295,19 +295,19 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
/* st_size can be determined through
GetFileSizeEx
- <https://msdn.microsoft.com/en-us/library/aa364957.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfilesizeex>
or through
GetFileAttributesEx
- <https://msdn.microsoft.com/en-us/library/aa364946.aspx>
- <https://msdn.microsoft.com/en-us/library/aa365739.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileattributesexa>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_win32_file_attribute_data>
or through
GetFileInformationByHandle
- <https://msdn.microsoft.com/en-us/library/aa364952.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363788.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information>
or through
GetFileInformationByHandleEx with argument FileStandardInfo
- <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
- <https://msdn.microsoft.com/en-us/library/aa364401.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_standard_info>
The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
if (sizeof (buf->st_size) <= 4)
/* Range check already done above. */
@@ -317,19 +317,19 @@ _gl_fstat_by_handle (HANDLE h, const char *path, struct stat *buf)
/* st_atime, st_mtime, st_ctime can be determined through
GetFileTime
- <https://msdn.microsoft.com/en-us/library/ms724320.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletime>
or through
GetFileAttributesEx
- <https://msdn.microsoft.com/en-us/library/aa364946.aspx>
- <https://msdn.microsoft.com/en-us/library/aa365739.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileattributesexa>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_win32_file_attribute_data>
or through
GetFileInformationByHandle
- <https://msdn.microsoft.com/en-us/library/aa364952.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363788.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information>
or through
GetFileInformationByHandleEx with argument FileBasicInfo
- <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
- <https://msdn.microsoft.com/en-us/library/aa364217.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getfileinformationbyhandleex>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_file_basic_info>
The latter requires -D_WIN32_WINNT=_WIN32_WINNT_VISTA or higher. */
#if _GL_WINDOWS_STAT_TIMESPEC
buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime);
diff --git a/lib/stat-w32.h b/lib/stat-w32.h
index 9a3ecc1..491a754 100644
--- a/lib/stat-w32.h
+++ b/lib/stat-w32.h
@@ -1,5 +1,5 @@
/* Core of implementation of fstat and stat for native Windows.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/stat.c b/lib/stat.c
index 18c0caa..e074e6a 100644
--- a/lib/stat.c
+++ b/lib/stat.c
@@ -1,5 +1,5 @@
/* Work around platform bugs in stat.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
@@ -42,10 +42,14 @@ orig_stat (const char *filename, struct stat *buf)
#endif
/* Specification. */
+#ifdef __osf__
/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
eliminates this include because of the preliminary #include <sys/stat.h>
above. */
-#include "sys/stat.h"
+# include "sys/stat.h"
+#else
+# include <sys/stat.h>
+#endif
#include "stat-time.h"
@@ -107,9 +111,9 @@ rpl_stat (char const *name, struct stat *buf)
<https://lists.gnu.org/r/bug-gnulib/2017-04/msg00134.html> */
/* XXX Should we convert to wchar_t* and prepend '\\?\', in order to work
around length limitations
- <https://msdn.microsoft.com/en-us/library/aa365247.aspx> ? */
+ <https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file> ? */
- /* POSIX <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>
+ /* POSIX <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13>
specifies: "More than two leading <slash> characters shall be treated as
a single <slash> character." */
if (ISSLASH (name[0]) && ISSLASH (name[1]) && ISSLASH (name[2]))
@@ -190,8 +194,8 @@ rpl_stat (char const *name, struct stat *buf)
/* Open a handle to the file.
CreateFile
- <https://msdn.microsoft.com/en-us/library/aa363858.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363874.aspx> */
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea>
+ <https://docs.microsoft.com/en-us/windows/desktop/FileIO/creating-and-opening-files> */
HANDLE h =
CreateFile (rname,
FILE_READ_ATTRIBUTES,
@@ -232,13 +236,13 @@ rpl_stat (char const *name, struct stat *buf)
/* Get the details about the directory entry. This can be done through
FindFirstFile
- <https://msdn.microsoft.com/en-us/library/aa364418.aspx>
- <https://msdn.microsoft.com/en-us/library/aa365740.aspx>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfilea>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-_win32_find_dataa>
or through
FindFirstFileEx with argument FindExInfoBasic
- <https://msdn.microsoft.com/en-us/library/aa364419.aspx>
- <https://msdn.microsoft.com/en-us/library/aa364415.aspx>
- <https://msdn.microsoft.com/en-us/library/aa365740.aspx> */
+ <https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfileexa>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ne-minwinbase-findex_info_levels>
+ <https://docs.microsoft.com/en-us/windows/desktop/api/minwinbase/ns-minwinbase-_win32_find_dataa> */
WIN32_FIND_DATA info;
HANDLE h = FindFirstFile (rname, &info);
if (h == INVALID_HANDLE_VALUE)
@@ -371,7 +375,7 @@ rpl_stat (char const *name, struct stat *buf)
case ERROR_ACCESS_DENIED: /* rname is such as 'C:\System Volume Information\foo'. */
case ERROR_SHARING_VIOLATION: /* rname is such as 'C:\pagefile.sys' (second approach only). */
- /* XXX map to EACCESS or EPERM? */
+ /* XXX map to EACCES or EPERM? */
errno = EACCES;
break;
@@ -394,7 +398,7 @@ rpl_stat (char const *name, struct stat *buf)
errno = ENAMETOOLONG;
break;
- case ERROR_DELETE_PENDING: /* XXX map to EACCESS or EPERM? */
+ case ERROR_DELETE_PENDING: /* XXX map to EACCES or EPERM? */
errno = EPERM;
break;
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
index bbfa9ac..cd786be 100644
--- a/lib/stdalign.in.h
+++ b/lib/stdalign.in.h
@@ -1,6 +1,6 @@
/* A substitute for ISO C11 <stdalign.h>.
- Copyright 2011-2018 Free Software Foundation, Inc.
+ Copyright 2011-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
@@ -102,7 +102,7 @@
# define _Alignas(a) alignas (a)
# elif ((defined __APPLE__ && defined __MACH__ \
? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
- : __GNUC__) \
+ : __GNUC__ && !defined __ibmxl__) \
|| (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
|| __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__)
# define _Alignas(a) __attribute__ ((__aligned__ (a)))
diff --git a/lib/stdarg.in.h b/lib/stdarg.in.h
index 46af0c2..8cdc685 100644
--- a/lib/stdarg.in.h
+++ b/lib/stdarg.in.h
@@ -1,5 +1,5 @@
/* Substitute for and wrapper around <stdarg.h>.
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/stdbool.in.h b/lib/stdbool.in.h
index ebf1a2f..baacf98 100644
--- a/lib/stdbool.in.h
+++ b/lib/stdbool.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2003, 2006-2018 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2003, 2006-2020 Free Software Foundation, Inc.
Written by Bruno Haible <haible@clisp.cons.org>, 2001.
This program is free software; you can redistribute it and/or modify
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index 8329a9b..2e50a1f 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -1,6 +1,6 @@
/* A substitute for POSIX 2008 <stddef.h>, for platforms that have issues.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
@@ -19,7 +19,7 @@
/*
* POSIX 2008 <stddef.h> for platforms that have issues.
- * <http://www.opengroup.org/susv3xbd/stddef.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html>
*/
#if __GNUC__ >= 3
@@ -83,20 +83,26 @@
/* Some platforms lack max_align_t. The check for _GCC_MAX_ALIGN_T is
a hack in case the configure-time test was done with g++ even though
- we are currently compiling with gcc. */
-#if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T)
-# if !GNULIB_defined_max_align_t
+ we are currently compiling with gcc.
+ On MSVC, max_align_t is defined only in C++ mode, after <cstddef> was
+ included. Its definition is good since it has an alignment of 8 (on x86
+ and x86_64). */
+#if defined _MSC_VER && defined __cplusplus
+# include <cstddef>
+#else
+# if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T)
+# if !GNULIB_defined_max_align_t
/* On the x86, the maximum storage alignment of double, long, etc. is 4,
but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8,
and the C11 standard allows this. Work around this problem by
using __alignof__ (which returns 8 for double) rather than _Alignof
(which returns 4), and align each union member accordingly. */
-# ifdef __GNUC__
-# define _GL_STDDEF_ALIGNAS(type) \
- __attribute__ ((__aligned__ (__alignof__ (type))))
-# else
-# define _GL_STDDEF_ALIGNAS(type) /* */
-# endif
+# ifdef __GNUC__
+# define _GL_STDDEF_ALIGNAS(type) \
+ __attribute__ ((__aligned__ (__alignof__ (type))))
+# else
+# define _GL_STDDEF_ALIGNAS(type) /* */
+# endif
typedef union
{
char *__p _GL_STDDEF_ALIGNAS (char *);
@@ -104,8 +110,9 @@ typedef union
long double __ld _GL_STDDEF_ALIGNAS (long double);
long int __i _GL_STDDEF_ALIGNAS (long int);
} rpl_max_align_t;
-# define max_align_t rpl_max_align_t
-# define GNULIB_defined_max_align_t 1
+# define max_align_t rpl_max_align_t
+# define GNULIB_defined_max_align_t 1
+# endif
# endif
#endif
diff --git a/lib/stdint.in.h b/lib/stdint.in.h
index 94e7c81..994c0c7 100644
--- a/lib/stdint.in.h
+++ b/lib/stdint.in.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2002, 2004-2018 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2002, 2004-2020 Free Software Foundation, Inc.
Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood.
This file is part of gnulib.
@@ -17,7 +17,7 @@
/*
* ISO C 99 <stdint.h> for platforms that lack it.
- * <http://www.opengroup.org/susv3xbd/stdint.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html>
*/
#ifndef _@GUARD_PREFIX@_STDINT_H
@@ -188,7 +188,7 @@ typedef long int gl_int64_t;
typedef __int64 gl_int64_t;
# define int64_t gl_int64_t
# define GL_INT64_T
-# elif @HAVE_LONG_LONG_INT@
+# else
# undef int64_t
typedef long long int gl_int64_t;
# define int64_t gl_int64_t
@@ -209,7 +209,7 @@ typedef unsigned long int gl_uint64_t;
typedef unsigned __int64 gl_uint64_t;
# define uint64_t gl_uint64_t
# define GL_UINT64_T
-# elif @HAVE_UNSIGNED_LONG_LONG_INT@
+# else
# undef uint64_t
typedef unsigned long long int gl_uint64_t;
# define uint64_t gl_uint64_t
@@ -299,16 +299,26 @@ typedef gl_uint_fast32_t gl_uint_fast16_t;
/* 7.18.1.4. Integer types capable of holding object pointers */
-/* kLIBC's stdint.h defines _INTPTR_T_DECLARED and needs its own
+/* kLIBC's <stdint.h> defines _INTPTR_T_DECLARED and needs its own
definitions of intptr_t and uintptr_t (which use int and unsigned)
- to avoid clashes with declarations of system functions like sbrk. */
-# ifndef _INTPTR_T_DECLARED
-# undef intptr_t
-# undef uintptr_t
+ to avoid clashes with declarations of system functions like sbrk.
+ Similarly, mingw 5.22 <crtdefs.h> defines _INTPTR_T_DEFINED and
+ _UINTPTR_T_DEFINED and needs its own definitions of intptr_t and
+ uintptr_t to avoid conflicting declarations of system functions like
+ _findclose in <io.h>. */
+# if !((defined __KLIBC__ && defined _INTPTR_T_DECLARED) \
+ || (defined __MINGW32__ && defined _INTPTR_T_DEFINED && defined _UINTPTR_T_DEFINED))
+# undef intptr_t
+# undef uintptr_t
+# ifdef _WIN64
+typedef long long int gl_intptr_t;
+typedef unsigned long long int gl_uintptr_t;
+# else
typedef long int gl_intptr_t;
typedef unsigned long int gl_uintptr_t;
-# define intptr_t gl_intptr_t
-# define uintptr_t gl_uintptr_t
+# endif
+# define intptr_t gl_intptr_t
+# define uintptr_t gl_uintptr_t
# endif
/* 7.18.1.5. Greatest-width integer types */
@@ -323,7 +333,7 @@ typedef unsigned long int gl_uintptr_t;
# ifndef INTMAX_MAX
# undef INTMAX_C
# undef intmax_t
-# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# if LONG_MAX >> 30 == 1
typedef long long int gl_intmax_t;
# define intmax_t gl_intmax_t
# elif defined GL_INT64_T
@@ -337,7 +347,7 @@ typedef long int gl_intmax_t;
# ifndef UINTMAX_MAX
# undef UINTMAX_C
# undef uintmax_t
-# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# if ULONG_MAX >> 31 == 1
typedef unsigned long long int gl_uintmax_t;
# define uintmax_t gl_uintmax_t
# elif defined GL_UINT64_T
@@ -485,9 +495,15 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
# undef INTPTR_MIN
# undef INTPTR_MAX
# undef UINTPTR_MAX
-# define INTPTR_MIN LONG_MIN
-# define INTPTR_MAX LONG_MAX
-# define UINTPTR_MAX ULONG_MAX
+# ifdef _WIN64
+# define INTPTR_MIN LLONG_MIN
+# define INTPTR_MAX LLONG_MAX
+# define UINTPTR_MAX ULLONG_MAX
+# else
+# define INTPTR_MIN LONG_MIN
+# define INTPTR_MAX LONG_MAX
+# define UINTPTR_MAX ULONG_MAX
+# endif
/* 7.18.2.5. Limits of greatest-width integer types */
@@ -586,17 +602,21 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
_STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@)
/* wint_t limits */
-# undef WINT_MIN
-# undef WINT_MAX
-# if @HAVE_SIGNED_WINT_T@
-# define WINT_MIN \
- _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
-# else
-# define WINT_MIN \
- _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
+/* If gnulib's <wchar.h> or <wctype.h> overrides wint_t, @WINT_T_SUFFIX@ is not
+ accurate, therefore use the definitions from above. */
+# if !@GNULIB_OVERRIDES_WINT_T@
+# undef WINT_MIN
+# undef WINT_MAX
+# if @HAVE_SIGNED_WINT_T@
+# define WINT_MIN \
+ _STDINT_SIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
+# else
+# define WINT_MIN \
+ _STDINT_UNSIGNED_MIN (@BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
+# endif
+# define WINT_MAX \
+ _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
# endif
-# define WINT_MAX \
- _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@)
/* 7.18.4. Macros for integer constants */
@@ -627,21 +647,21 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
# define INT64_C(x) x##L
# elif defined _MSC_VER
# define INT64_C(x) x##i64
-# elif @HAVE_LONG_LONG_INT@
+# else
# define INT64_C(x) x##LL
# endif
# if ULONG_MAX >> 31 >> 31 >> 1 == 1
# define UINT64_C(x) x##UL
# elif defined _MSC_VER
# define UINT64_C(x) x##ui64
-# elif @HAVE_UNSIGNED_LONG_LONG_INT@
+# else
# define UINT64_C(x) x##ULL
# endif
/* 7.18.4.2. Macros for greatest-width integer constants */
# ifndef INTMAX_C
-# if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1
+# if LONG_MAX >> 30 == 1
# define INTMAX_C(x) x##LL
# elif defined GL_INT64_T
# define INTMAX_C(x) INT64_C(x)
@@ -651,7 +671,7 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
# endif
# ifndef UINTMAX_C
-# if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1
+# if ULONG_MAX >> 31 == 1
# define UINTMAX_C(x) x##ULL
# elif defined GL_UINT64_T
# define UINTMAX_C(x) UINT64_C(x)
diff --git a/lib/stdio-impl.h b/lib/stdio-impl.h
index 393ef0c..067b95e 100644
--- a/lib/stdio-impl.h
+++ b/lib/stdio-impl.h
@@ -1,5 +1,5 @@
/* Implementation details of FILE streams.
- Copyright (C) 2007-2008, 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-2008, 2010-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
@@ -18,11 +18,16 @@
the same implementation of stdio extension API, except that some fields
have different naming conventions, or their access requires some casts. */
-/* Glibc 2.28 made _IO_IN_BACKUP private. For now, work around this
- problem by defining it ourselves. FIXME: Do not rely on glibc
+/* Glibc 2.28 made _IO_UNBUFFERED and _IO_IN_BACKUP private. For now, work
+ around this problem by defining them ourselves. FIXME: Do not rely on glibc
internals. */
-#if !defined _IO_IN_BACKUP && defined _IO_EOF_SEEN
-# define _IO_IN_BACKUP 0x100
+#if defined _IO_EOF_SEEN
+# if !defined _IO_UNBUFFERED
+# define _IO_UNBUFFERED 0x2
+# endif
+# if !defined _IO_IN_BACKUP
+# define _IO_IN_BACKUP 0x100
+# endif
#endif
/* BSD stdio derived implementations. */
@@ -61,6 +66,11 @@
# define _r pub._r
# define _w pub._w
# elif defined __ANDROID__ /* Android */
+# ifdef __LP64__
+# define _gl_flags_file_t int
+# else
+# define _gl_flags_file_t short
+# endif
/* Up to this commit from 2015-10-12
<https://android.googlesource.com/platform/bionic.git/+/f0141dfab10a4b332769d52fa76631a64741297a>
the innards of FILE were public, and fp_ub could be defined like for OpenBSD,
@@ -70,8 +80,8 @@
# define fp_ ((struct { unsigned char *_p; \
int _r; \
int _w; \
- int _flags; \
- int _file; \
+ _gl_flags_file_t _flags; \
+ _gl_flags_file_t _file; \
struct { unsigned char *_base; size_t _size; } _bf; \
int _lbfsize; \
void *_cookie; \
diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index ff7c9c8..ebcbfaf 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <stdio.h>.
- Copyright (C) 2004, 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2007-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
@@ -118,6 +118,13 @@
# include <unistd.h>
#endif
+/* Android 4.3 declares renameat in <sys/stat.h>, not in <stdio.h>. */
+/* But in any case avoid namespace pollution on glibc systems. */
+#if (@GNULIB_RENAMEAT@ || defined GNULIB_POSIXCHECK) && defined __ANDROID__ \
+ && ! defined __GLIBC__
+# include <sys/stat.h>
+#endif
+
/* MSVC declares 'perror' in <stdlib.h>, not in <stdio.h>. We must include
it before we #define perror rpl_perror. */
/* But in any case avoid namespace pollution on glibc systems. */
@@ -196,7 +203,9 @@ _GL_CXXALIAS_RPL (fclose, int, (FILE *stream));
# else
_GL_CXXALIAS_SYS (fclose, int, (FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fclose);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef fclose
/* Assume fclose is always declared. */
@@ -240,7 +249,9 @@ _GL_CXXALIAS_RPL (fflush, int, (FILE *gl_stream));
# else
_GL_CXXALIAS_SYS (fflush, int, (FILE *gl_stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fflush);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef fflush
/* Assume fflush is always declared. */
@@ -259,7 +270,9 @@ _GL_CXXALIAS_RPL (fgetc, int, (FILE *stream));
# else
_GL_CXXALIAS_SYS (fgetc, int, (FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fgetc);
+# endif
#endif
#if @GNULIB_FGETS@
@@ -274,7 +287,9 @@ _GL_CXXALIAS_RPL (fgets, char *, (char *s, int n, FILE *stream));
# else
_GL_CXXALIAS_SYS (fgets, char *, (char *s, int n, FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fgets);
+# endif
#endif
#if @GNULIB_FOPEN@
@@ -289,7 +304,9 @@ _GL_CXXALIAS_RPL (fopen, FILE *, (const char *filename, const char *mode));
# else
_GL_CXXALIAS_SYS (fopen, FILE *, (const char *filename, const char *mode));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fopen);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef fopen
/* Assume fopen is always declared. */
@@ -317,7 +334,9 @@ _GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...));
# else
_GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fprintf);
+# endif
#endif
#if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_fprintf
@@ -368,7 +387,9 @@ _GL_CXXALIAS_RPL (fputc, int, (int c, FILE *stream));
# else
_GL_CXXALIAS_SYS (fputc, int, (int c, FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fputc);
+# endif
#endif
#if @GNULIB_FPUTS@
@@ -383,7 +404,9 @@ _GL_CXXALIAS_RPL (fputs, int, (const char *string, FILE *stream));
# else
_GL_CXXALIAS_SYS (fputs, int, (const char *string, FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fputs);
+# endif
#endif
#if @GNULIB_FREAD@
@@ -398,7 +421,9 @@ _GL_CXXALIAS_RPL (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream));
# else
_GL_CXXALIAS_SYS (fread, size_t, (void *ptr, size_t s, size_t n, FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fread);
+# endif
#endif
#if @GNULIB_FREOPEN@
@@ -416,7 +441,9 @@ _GL_CXXALIAS_RPL (freopen, FILE *,
_GL_CXXALIAS_SYS (freopen, FILE *,
(const char *filename, const char *mode, FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (freopen);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef freopen
/* Assume freopen is always declared. */
@@ -438,7 +465,9 @@ _GL_CXXALIAS_RPL (fscanf, int, (FILE *stream, const char *format, ...));
# else
_GL_CXXALIAS_SYS (fscanf, int, (FILE *stream, const char *format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fscanf);
+# endif
#endif
@@ -489,7 +518,9 @@ _GL_CXXALIAS_RPL (fseek, int, (FILE *fp, long offset, int whence));
# else
_GL_CXXALIAS_SYS (fseek, int, (FILE *fp, long offset, int whence));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fseek);
+# endif
#endif
#if @GNULIB_FSEEKO@
@@ -552,7 +583,9 @@ _GL_CXXALIAS_RPL (ftell, long, (FILE *fp));
# else
_GL_CXXALIAS_SYS (ftell, long, (FILE *fp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (ftell);
+# endif
#endif
#if @GNULIB_FTELLO@
@@ -632,7 +665,9 @@ extern size_t __REDIRECT (rpl_fwrite_unlocked,
# define fwrite_unlocked rpl_fwrite_unlocked
# endif
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (fwrite);
+# endif
#endif
#if @GNULIB_GETC@
@@ -646,7 +681,9 @@ _GL_CXXALIAS_RPL_1 (getc, rpl_fgetc, int, (FILE *stream));
# else
_GL_CXXALIAS_SYS (getc, int, (FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (getc);
+# endif
#endif
#if @GNULIB_GETCHAR@
@@ -660,7 +697,9 @@ _GL_CXXALIAS_RPL (getchar, int, (void));
# else
_GL_CXXALIAS_SYS (getchar, int, (void));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (getchar);
+# endif
#endif
#if @GNULIB_GETDELIM@
@@ -825,7 +864,9 @@ _GL_CXXALIAS_RPL (perror, void, (const char *string));
# else
_GL_CXXALIAS_SYS (perror, void, (const char *string));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (perror);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef perror
/* Assume perror is always declared. */
@@ -896,7 +937,9 @@ _GL_CXXALIAS_RPL (printf, int, (const char *format, ...));
# else
_GL_CXXALIAS_SYS (printf, int, (const char *format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (printf);
+# endif
#endif
#if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_printf
@@ -919,7 +962,9 @@ _GL_CXXALIAS_RPL_1 (putc, rpl_fputc, int, (int c, FILE *stream));
# else
_GL_CXXALIAS_SYS (putc, int, (int c, FILE *stream));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (putc);
+# endif
#endif
#if @GNULIB_PUTCHAR@
@@ -933,7 +978,9 @@ _GL_CXXALIAS_RPL (putchar, int, (int c));
# else
_GL_CXXALIAS_SYS (putchar, int, (int c));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (putchar);
+# endif
#endif
#if @GNULIB_PUTS@
@@ -947,7 +994,9 @@ _GL_CXXALIAS_RPL (puts, int, (const char *string));
# else
_GL_CXXALIAS_SYS (puts, int, (const char *string));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (puts);
+# endif
#endif
#if @GNULIB_REMOVE@
@@ -961,7 +1010,9 @@ _GL_CXXALIAS_RPL (remove, int, (const char *name));
# else
_GL_CXXALIAS_SYS (remove, int, (const char *name));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (remove);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef remove
/* Assume remove is always declared. */
@@ -984,7 +1035,9 @@ _GL_CXXALIAS_RPL (rename, int,
_GL_CXXALIAS_SYS (rename, int,
(const char *old_filename, const char *new_filename));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (rename);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef rename
/* Assume rename is always declared. */
@@ -1049,7 +1102,9 @@ _GL_CXXALIAS_RPL (scanf, int, (const char *format, ...));
# else
_GL_CXXALIAS_SYS (scanf, int, (const char *format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (scanf);
+# endif
#endif
#if @GNULIB_SNPRINTF@
@@ -1103,7 +1158,9 @@ _GL_CXXALIAS_RPL (sprintf, int, (char *str, const char *format, ...));
# else
_GL_CXXALIAS_SYS (sprintf, int, (char *str, const char *format, ...));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (sprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef sprintf
/* Assume sprintf is always declared. */
@@ -1122,7 +1179,9 @@ _GL_CXXALIAS_RPL (tmpfile, FILE *, (void));
# else
_GL_CXXALIAS_SYS (tmpfile, FILE *, (void));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (tmpfile);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef tmpfile
# if HAVE_RAW_DECL_TMPFILE
@@ -1200,7 +1259,9 @@ _GL_FUNCDECL_SYS (vdprintf, int, (int fd, const char *format, va_list args)
_GL_CXXALIAS_SYS_CAST (vdprintf, int,
(int fd, const char *format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vdprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef vdprintf
# if HAVE_RAW_DECL_VDPRINTF
@@ -1233,7 +1294,9 @@ _GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args));
_GL_CXXALIAS_SYS_CAST (vfprintf, int,
(FILE *fp, const char *format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vfprintf);
+# endif
#endif
#if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_vfprintf
@@ -1287,7 +1350,9 @@ _GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args));
and GCC's fixincludes did not change this to __gnuc_va_list. */
_GL_CXXALIAS_SYS_CAST (vprintf, int, (const char *format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vprintf);
+# endif
#endif
#if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK
# if !GNULIB_overrides_vprintf
@@ -1363,7 +1428,9 @@ _GL_CXXALIAS_RPL (vsprintf, int,
_GL_CXXALIAS_SYS_CAST (vsprintf, int,
(char *str, const char *format, va_list args));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (vsprintf);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef vsprintf
/* Assume vsprintf is always declared. */
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 441c018..49bbf6f 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <stdlib.h>.
- Copyright (C) 1995, 2001-2004, 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 1995, 2001-2004, 2006-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
@@ -176,7 +176,9 @@ _GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t size));
# else
_GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (calloc);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef calloc
/* Assume calloc is always declared. */
@@ -199,6 +201,10 @@ _GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name)
# endif
_GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name));
# endif
+# ifndef GNULIB_defined_canonicalize_file_name
+# define GNULIB_defined_canonicalize_file_name \
+ (!@HAVE_CANONICALIZE_FILE_NAME@ || @REPLACE_CANONICALIZE_FILE_NAME@)
+# endif
_GL_CXXALIASWARN (canonicalize_file_name);
#elif defined GNULIB_POSIXCHECK
# undef canonicalize_file_name
@@ -238,8 +244,8 @@ _GL_WARN_ON_USE (getloadavg, "getloadavg is not portable - "
element (or NULL if it doesn't contain an "=" sign),
- It returns the index of the "token" in the given array of tokens.
Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined.
- For more details see the POSIX:2001 specification.
- http://www.opengroup.org/susv3xsh/getsubopt.html */
+ For more details see the POSIX specification.
+ https://pubs.opengroup.org/onlinepubs/9699919799/functions/getsubopt.html */
# if !@HAVE_GETSUBOPT@
_GL_FUNCDECL_SYS (getsubopt, int,
(char **optionp, char *const *tokens, char **valuep)
@@ -288,7 +294,9 @@ _GL_CXXALIAS_RPL (malloc, void *, (size_t size));
# else
_GL_CXXALIAS_SYS (malloc, void *, (size_t size));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (malloc);
+# endif
#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
# undef malloc
/* Assume malloc is always declared. */
@@ -306,9 +314,20 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - "
_GL_FUNCDECL_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
_GL_CXXALIAS_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
# else
+# if !@HAVE_MBTOWC@
+_GL_FUNCDECL_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
+# endif
_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbtowc);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef mbtowc
+# if HAVE_RAW_DECL_MBTOWC
+_GL_WARN_ON_USE (mbtowc, "mbtowc is not portable - "
+ "use gnulib module mbtowc for portability");
+# endif
#endif
#if @GNULIB_MKDTEMP@
@@ -501,6 +520,9 @@ _GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len));
# endif
_GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len));
# endif
+# ifndef GNULIB_defined_ptsname_r
+# define GNULIB_defined_ptsname_r (!@HAVE_PTSNAME_R@ || @REPLACE_PTSNAME_R@)
+# endif
_GL_CXXALIASWARN (ptsname_r);
#elif defined GNULIB_POSIXCHECK
# undef ptsname_r
@@ -573,10 +595,21 @@ _GL_WARN_ON_USE (qsort_r, "qsort_r is not portable - "
#if @GNULIB_RANDOM@
-# if !@HAVE_RANDOM@
+# if @REPLACE_RANDOM@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef random
+# define random rpl_random
+# endif
+_GL_FUNCDECL_RPL (random, long, (void));
+_GL_CXXALIAS_RPL (random, long, (void));
+# else
+# if !@HAVE_RANDOM@
_GL_FUNCDECL_SYS (random, long, (void));
+# endif
+/* Need to cast, because on Haiku, the return type is
+ int. */
+_GL_CXXALIAS_SYS_CAST (random, long, (void));
# endif
-_GL_CXXALIAS_SYS (random, long, (void));
_GL_CXXALIASWARN (random);
#elif defined GNULIB_POSIXCHECK
# undef random
@@ -587,10 +620,21 @@ _GL_WARN_ON_USE (random, "random is unportable - "
#endif
#if @GNULIB_RANDOM@
-# if !@HAVE_RANDOM@
+# if @REPLACE_RANDOM@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef srandom
+# define srandom rpl_srandom
+# endif
+_GL_FUNCDECL_RPL (srandom, void, (unsigned int seed));
+_GL_CXXALIAS_RPL (srandom, void, (unsigned int seed));
+# else
+# if !@HAVE_RANDOM@
_GL_FUNCDECL_SYS (srandom, void, (unsigned int seed));
+# endif
+/* Need to cast, because on FreeBSD, the first parameter is
+ unsigned long seed. */
+_GL_CXXALIAS_SYS_CAST (srandom, void, (unsigned int seed));
# endif
-_GL_CXXALIAS_SYS (srandom, void, (unsigned int seed));
_GL_CXXALIASWARN (srandom);
#elif defined GNULIB_POSIXCHECK
# undef srandom
@@ -601,31 +645,56 @@ _GL_WARN_ON_USE (srandom, "srandom is unportable - "
#endif
#if @GNULIB_RANDOM@
-# if !@HAVE_RANDOM@ || !@HAVE_DECL_INITSTATE@
+# if @REPLACE_INITSTATE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef initstate
+# define initstate rpl_initstate
+# endif
+_GL_FUNCDECL_RPL (initstate, char *,
+ (unsigned int seed, char *buf, size_t buf_size)
+ _GL_ARG_NONNULL ((2)));
+_GL_CXXALIAS_RPL (initstate, char *,
+ (unsigned int seed, char *buf, size_t buf_size));
+# else
+# if !@HAVE_INITSTATE@ || !@HAVE_DECL_INITSTATE@
_GL_FUNCDECL_SYS (initstate, char *,
(unsigned int seed, char *buf, size_t buf_size)
_GL_ARG_NONNULL ((2)));
+# endif
+/* Need to cast, because on FreeBSD, the first parameter is
+ unsigned long seed. */
+_GL_CXXALIAS_SYS_CAST (initstate, char *,
+ (unsigned int seed, char *buf, size_t buf_size));
# endif
-_GL_CXXALIAS_SYS (initstate, char *,
- (unsigned int seed, char *buf, size_t buf_size));
_GL_CXXALIASWARN (initstate);
#elif defined GNULIB_POSIXCHECK
# undef initstate
-# if HAVE_RAW_DECL_INITSTATE_R
+# if HAVE_RAW_DECL_INITSTATE
_GL_WARN_ON_USE (initstate, "initstate is unportable - "
"use gnulib module random for portability");
# endif
#endif
#if @GNULIB_RANDOM@
-# if !@HAVE_RANDOM@ || !@HAVE_DECL_SETSTATE@
+# if @REPLACE_SETSTATE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef setstate
+# define setstate rpl_setstate
+# endif
+_GL_FUNCDECL_RPL (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (setstate, char *, (char *arg_state));
+# else
+# if !@HAVE_SETSTATE@ || !@HAVE_DECL_SETSTATE@
_GL_FUNCDECL_SYS (setstate, char *, (char *arg_state) _GL_ARG_NONNULL ((1)));
+# endif
+/* Need to cast, because on Mac OS X 10.13, HP-UX, Solaris the first parameter
+ is const char *arg_state. */
+_GL_CXXALIAS_SYS_CAST (setstate, char *, (char *arg_state));
# endif
-_GL_CXXALIAS_SYS (setstate, char *, (char *arg_state));
_GL_CXXALIASWARN (setstate);
#elif defined GNULIB_POSIXCHECK
# undef setstate
-# if HAVE_RAW_DECL_SETSTATE_R
+# if HAVE_RAW_DECL_SETSTATE
_GL_WARN_ON_USE (setstate, "setstate is unportable - "
"use gnulib module random for portability");
# endif
@@ -706,9 +775,11 @@ _GL_FUNCDECL_SYS (initstate_r, int,
struct random_data *rand_state)
_GL_ARG_NONNULL ((2, 4)));
# endif
-_GL_CXXALIAS_SYS (initstate_r, int,
- (unsigned int seed, char *buf, size_t buf_size,
- struct random_data *rand_state));
+/* Need to cast, because on Haiku, the third parameter is
+ unsigned long buf_size. */
+_GL_CXXALIAS_SYS_CAST (initstate_r, int,
+ (unsigned int seed, char *buf, size_t buf_size,
+ struct random_data *rand_state));
# endif
_GL_CXXALIASWARN (initstate_r);
#elif defined GNULIB_POSIXCHECK
@@ -736,8 +807,10 @@ _GL_FUNCDECL_SYS (setstate_r, int,
(char *arg_state, struct random_data *rand_state)
_GL_ARG_NONNULL ((1, 2)));
# endif
-_GL_CXXALIAS_SYS (setstate_r, int,
- (char *arg_state, struct random_data *rand_state));
+/* Need to cast, because on Haiku, the first parameter is
+ void *arg_state. */
+_GL_CXXALIAS_SYS_CAST (setstate_r, int,
+ (char *arg_state, struct random_data *rand_state));
# endif
_GL_CXXALIASWARN (setstate_r);
#elif defined GNULIB_POSIXCHECK
@@ -761,7 +834,9 @@ _GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size));
# else
_GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (realloc);
+# endif
#elif defined GNULIB_POSIXCHECK && !_GL_USE_STDLIB_ALLOC
# undef realloc
/* Assume realloc is always declared. */
@@ -881,6 +956,7 @@ _GL_WARN_ON_USE (setenv, "setenv is unportable - "
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define strtod rpl_strtod
# endif
+# define GNULIB_defined_strtod_function 1
_GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp));
@@ -891,7 +967,9 @@ _GL_FUNCDECL_SYS (strtod, double, (const char *str, char **endp)
# endif
_GL_CXXALIAS_SYS (strtod, double, (const char *str, char **endp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strtod);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef strtod
# if HAVE_RAW_DECL_STRTOD
@@ -900,6 +978,32 @@ _GL_WARN_ON_USE (strtod, "strtod is unportable - "
# endif
#endif
+#if @GNULIB_STRTOLD@
+ /* Parse a 'long double' from STRING, updating ENDP if appropriate. */
+# if @REPLACE_STRTOLD@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtold rpl_strtold
+# endif
+# define GNULIB_defined_strtold_function 1
+_GL_FUNCDECL_RPL (strtold, long double, (const char *str, char **endp)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtold, long double, (const char *str, char **endp));
+# else
+# if !@HAVE_STRTOLD@
+_GL_FUNCDECL_SYS (strtold, long double, (const char *str, char **endp)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtold, long double, (const char *str, char **endp));
+# endif
+_GL_CXXALIASWARN (strtold);
+#elif defined GNULIB_POSIXCHECK
+# undef strtold
+# if HAVE_RAW_DECL_STRTOLD
+_GL_WARN_ON_USE (strtold, "strtold is unportable - "
+ "use gnulib module strtold for portability");
+# endif
+#endif
+
#if @GNULIB_STRTOLL@
/* Parse a signed integer whose textual representation starts at STRING.
The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
@@ -1004,7 +1108,9 @@ _GL_CXXALIAS_RPL (wctomb, int, (char *s, wchar_t wc));
# else
_GL_CXXALIAS_SYS (wctomb, int, (char *s, wchar_t wc));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wctomb);
+# endif
#endif
diff --git a/lib/streq.h b/lib/streq.h
index bde1b95..d06c272 100644
--- a/lib/streq.h
+++ b/lib/streq.h
@@ -1,5 +1,5 @@
/* Optimized string comparison.
- Copyright (C) 2001-2002, 2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2002, 2007, 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
diff --git a/lib/strerror-override.c b/lib/strerror-override.c
index d3ad21e..61b7689 100644
--- a/lib/strerror-override.c
+++ b/lib/strerror-override.c
@@ -1,6 +1,6 @@
/* strerror-override.c --- POSIX compatible system error routine
- Copyright (C) 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2010-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
diff --git a/lib/strerror-override.h b/lib/strerror-override.h
index a96fd08..062f51c 100644
--- a/lib/strerror-override.h
+++ b/lib/strerror-override.h
@@ -1,6 +1,6 @@
/* strerror-override.h --- POSIX compatible system error routine
- Copyright (C) 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2010-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
diff --git a/lib/strerror.c b/lib/strerror.c
index 36397bb..1a53a8b 100644
--- a/lib/strerror.c
+++ b/lib/strerror.c
@@ -1,6 +1,6 @@
/* strerror.c --- POSIX compatible system error routine
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
diff --git a/lib/string.in.h b/lib/string.in.h
index 29f4ba6..2c04e5f 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1,6 +1,6 @@
/* A GNU-like <string.h>.
- Copyright (C) 1995-1996, 2001-2018 Free Software Foundation, Inc.
+ Copyright (C) 1995-1996, 2001-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
@@ -149,7 +149,7 @@ _GL_CXXALIAS_SYS_CAST2 (memchr,
_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n));
_GL_CXXALIASWARN1 (memchr, void const *,
(void const *__s, int __c, size_t __n));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (memchr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -417,7 +417,9 @@ _GL_CXXALIAS_RPL (strncat, char *, (char *dest, const char *src, size_t n));
# else
_GL_CXXALIAS_SYS (strncat, char *, (char *dest, const char *src, size_t n));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strncat);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef strncat
# if HAVE_RAW_DECL_STRNCAT
@@ -512,7 +514,7 @@ _GL_CXXALIAS_SYS_CAST2 (strpbrk,
_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept));
_GL_CXXALIASWARN1 (strpbrk, char const *,
(char const *__s, char const *__accept));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (strpbrk);
# endif
# if defined GNULIB_POSIXCHECK
@@ -614,7 +616,7 @@ _GL_CXXALIAS_SYS_CAST2 (strstr,
_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle));
_GL_CXXALIASWARN1 (strstr, const char *,
(const char *haystack, const char *needle));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (strstr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -693,7 +695,7 @@ _GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character "
This is a variant of strtok() that is multithread-safe.
For the POSIX documentation for this function, see:
- http://www.opengroup.org/susv3xsh/strtok.html
+ https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtok.html
Caveat: It modifies the original string.
Caveat: These functions cannot be used on constant strings.
@@ -980,7 +982,9 @@ _GL_CXXALIAS_RPL (strerror, char *, (int));
# else
_GL_CXXALIAS_SYS (strerror, char *, (int));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strerror);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef strerror
/* Assume strerror is always declared. */
diff --git a/lib/stripslash.c b/lib/stripslash.c
index 60c6781..6818b30 100644
--- a/lib/stripslash.c
+++ b/lib/stripslash.c
@@ -1,6 +1,6 @@
/* stripslash.c -- remove redundant trailing slashes from a file name
- Copyright (C) 1990, 2001, 2003-2006, 2009-2018 Free Software Foundation,
+ Copyright (C) 1990, 2001, 2003-2006, 2009-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/strverscmp.c b/lib/strverscmp.c
index 4eac791..9e0a5bb 100644
--- a/lib/strverscmp.c
+++ b/lib/strverscmp.c
@@ -1,5 +1,5 @@
/* Compare strings while treating digits characters numerically.
- Copyright (C) 1997-2018 Free Software Foundation, Inc.
+ Copyright (C) 1997-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jean-François Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
@@ -17,10 +17,12 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#if !_LIBC
-# include <config.h>
+#ifndef _LIBC
+# include <libc-config.h>
+# define __strverscmp strverscmp
#endif
+#include <stdint.h>
#include <string.h>
#include <ctype.h>
@@ -35,9 +37,6 @@
#define CMP 2
#define LEN 3
-#ifndef weak_alias
-# define __strverscmp strverscmp
-#endif
/* Compare S1 and S2 as strings holding indices/version numbers,
returning less than, equal to or greater than zero if S1 is less than,
@@ -49,13 +48,10 @@ __strverscmp (const char *s1, const char *s2)
{
const unsigned char *p1 = (const unsigned char *) s1;
const unsigned char *p2 = (const unsigned char *) s2;
- unsigned char c1, c2;
- int state;
- int diff;
/* Symbol(s) 0 [1-9] others
Transition (10) 0 (01) d (00) x */
- static const unsigned char next_state[] =
+ static const uint_least8_t next_state[] =
{
/* state x d 0 */
/* S_N */ S_N, S_I, S_Z,
@@ -64,7 +60,7 @@ __strverscmp (const char *s1, const char *s2)
/* S_Z */ S_N, S_F, S_Z
};
- static const signed char result_type[] =
+ static const int_least8_t result_type[] =
{
/* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */
@@ -77,15 +73,16 @@ __strverscmp (const char *s1, const char *s2)
if (p1 == p2)
return 0;
- c1 = *p1++;
- c2 = *p2++;
+ unsigned char c1 = *p1++;
+ unsigned char c2 = *p2++;
/* Hint: '0' is a digit too. */
- state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
+ int state = S_N + ((c1 == '0') + (isdigit (c1) != 0));
+ int diff;
while ((diff = c1 - c2) == 0)
{
if (c1 == '\0')
- return diff;
+ return diff;
state = next_state[state];
c1 = *p1++;
@@ -96,22 +93,20 @@ __strverscmp (const char *s1, const char *s2)
state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
switch (state)
- {
+ {
case CMP:
return diff;
case LEN:
while (isdigit (*p1++))
- if (!isdigit (*p2++))
- return 1;
+ if (!isdigit (*p2++))
+ return 1;
return isdigit (*p2) ? -1 : diff;
default:
return state;
- }
+ }
}
-#ifdef weak_alias
libc_hidden_def (__strverscmp)
weak_alias (__strverscmp, strverscmp)
-#endif
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index 6ae6ac5..c1e3243 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -1,5 +1,5 @@
/* Provide a more complete sys/stat.h header file.
- Copyright (C) 2005-2018 Free Software Foundation, Inc.
+ Copyright (C) 2005-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
@@ -54,9 +54,16 @@
/* The definition of _GL_WARN_ON_USE is copied here. */
+/* Before doing "#define mknod rpl_mknod" below, we need to include all
+ headers that may declare mknod(). OS/2 kLIBC declares mknod() in
+ <unistd.h>, not in <sys/stat.h>. */
+#ifdef __KLIBC__
+# include <unistd.h>
+#endif
+
/* Before doing "#define mkdir rpl_mkdir" below, we need to include all
headers that may declare mkdir(). Native Windows platforms declare mkdir
- in <io.h> and/or <direct.h>, not in <unistd.h>. */
+ in <io.h> and/or <direct.h>, not in <sys/stat.h>. */
#if defined _WIN32 && ! defined __CYGWIN__
# include <io.h> /* mingw32, mingw64 */
# include <direct.h> /* mingw64, MSVC 9 */
diff --git a/lib/sys_time.in.h b/lib/sys_time.in.h
index b4a0e49..d30b267 100644
--- a/lib/sys_time.in.h
+++ b/lib/sys_time.in.h
@@ -1,6 +1,6 @@
/* Provide a more complete sys/time.h.
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
@@ -112,8 +112,12 @@ _GL_CXXALIASWARN (gettimeofday);
# if defined __cplusplus && defined GNULIB_NAMESPACE
namespace GNULIB_NAMESPACE {
typedef ::timeval
-#undef timeval
+# undef timeval
timeval;
+# if @REPLACE_STRUCT_TIMEVAL@
+# define timeval rpl_timeval
+ typedef ::timeval timeval;
+# endif
}
# endif
#elif defined GNULIB_POSIXCHECK
diff --git a/lib/sys_types.in.h b/lib/sys_types.in.h
index 7f8c1c4..e7e1a22 100644
--- a/lib/sys_types.in.h
+++ b/lib/sys_types.in.h
@@ -1,6 +1,6 @@
/* Provide a more complete sys/types.h.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-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
diff --git a/lib/tempname.c b/lib/tempname.c
index da81263..0aad061 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -1,6 +1,6 @@
/* tempname.c - generate the name of a temporary file.
- Copyright (C) 1991-2003, 2005-2007, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1991-2003, 2005-2007, 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
diff --git a/lib/tempname.h b/lib/tempname.h
index 4020c73..abb9265 100644
--- a/lib/tempname.h
+++ b/lib/tempname.h
@@ -1,6 +1,6 @@
/* Create a temporary file or directory.
- Copyright (C) 2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 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
diff --git a/lib/time.in.h b/lib/time.in.h
index 3128f44..3f942b7 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -1,6 +1,6 @@
/* A more-standard <time.h>.
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
@@ -37,6 +37,12 @@
# define _@GUARD_PREFIX@_TIME_H
+/* mingw's <time.h> provides the functions asctime_r, ctime_r, gmtime_r,
+ localtime_r only if <unistd.h> or <pthread.h> has been included before. */
+# if defined __MINGW32__
+# include <unistd.h>
+# endif
+
# @INCLUDE_NEXT@ @NEXT_TIME_H@
/* NetBSD 5.0 mis-defines NULL. */
@@ -84,8 +90,8 @@ struct timespec
# endif
# if !GNULIB_defined_struct_time_t_must_be_integral
-/* Per http://austingroupbugs.net/view.php?id=327, POSIX requires
- time_t to be an integer type, even though C99 permits floating
+/* https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html
+ requires time_t to be an integer type, even though C99 permits floating
point. We don't know of any implementation that uses floating
point, and it is much easier to write code that doesn't have to
worry about that corner case, so we force the issue. */
@@ -97,7 +103,7 @@ struct __time_t_must_be_integral {
/* Sleep for at least RQTP seconds unless interrupted, If interrupted,
return -1 and store the remaining time into RMTP. See
- <http://www.opengroup.org/susv3xsh/nanosleep.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html>. */
# if @GNULIB_NANOSLEEP@
# if @REPLACE_NANOSLEEP@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -149,12 +155,14 @@ _GL_CXXALIAS_RPL (mktime, time_t, (struct tm *__tp));
# else
_GL_CXXALIAS_SYS (mktime, time_t, (struct tm *__tp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mktime);
+# endif
# endif
/* Convert TIMER to RESULT, assuming local time and UTC respectively. See
- <http://www.opengroup.org/susv3xsh/localtime_r.html> and
- <http://www.opengroup.org/susv3xsh/gmtime_r.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/localtime_r.html> and
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime_r.html>. */
# if @GNULIB_TIME_R@
# if @REPLACE_LOCALTIME_R@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -203,8 +211,8 @@ _GL_CXXALIASWARN (gmtime_r);
# endif
/* Convert TIMER to RESULT, assuming local time and UTC respectively. See
- <http://www.opengroup.org/susv3xsh/localtime.html> and
- <http://www.opengroup.org/susv3xsh/gmtime.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/localtime.html> and
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime.html>. */
# if @GNULIB_LOCALTIME@ || @REPLACE_LOCALTIME@
# if @REPLACE_LOCALTIME@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -217,7 +225,9 @@ _GL_CXXALIAS_RPL (localtime, struct tm *, (time_t const *__timer));
# else
_GL_CXXALIAS_SYS (localtime, struct tm *, (time_t const *__timer));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (localtime);
+# endif
# endif
# if 0 || @REPLACE_GMTIME@
@@ -237,7 +247,7 @@ _GL_CXXALIASWARN (gmtime);
/* Parse BUF as a timestamp, assuming FORMAT specifies its layout, and store
the resulting broken-down time into TM. See
- <http://www.opengroup.org/susv3xsh/strptime.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/strptime.html>. */
# if @GNULIB_STRPTIME@
# if ! @HAVE_STRPTIME@
_GL_FUNCDECL_SYS (strptime, char *, (char const *restrict __buf,
@@ -252,7 +262,7 @@ _GL_CXXALIASWARN (strptime);
# endif
/* Convert *TP to a date and time string. See
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ctime.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/ctime.html>. */
# if @GNULIB_CTIME@
# if @REPLACE_CTIME@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -264,11 +274,13 @@ _GL_CXXALIAS_RPL (ctime, char *, (time_t const *__tp));
# else
_GL_CXXALIAS_SYS (ctime, char *, (time_t const *__tp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (ctime);
+# endif
# endif
/* Convert *TP to a date and time string. See
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html>. */
# if @GNULIB_STRFTIME@
# if @REPLACE_STRFTIME@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -283,7 +295,9 @@ _GL_CXXALIAS_RPL (strftime, size_t, (char *__buf, size_t __bufsize,
_GL_CXXALIAS_SYS (strftime, size_t, (char *__buf, size_t __bufsize,
const char *__fmt, const struct tm *__tp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (strftime);
+# endif
# endif
# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 66f254d..d6176ad 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1,5 +1,5 @@
/* Substitute for and wrapper around <unistd.h>.
- Copyright (C) 2003-2018 Free Software Foundation, Inc.
+ Copyright (C) 2003-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
@@ -21,7 +21,7 @@
#endif
@PRAGMA_COLUMNS@
-#ifdef _GL_INCLUDING_UNISTD_H
+#if @HAVE_UNISTD_H@ && defined _GL_INCLUDING_UNISTD_H
/* Special invocation convention:
- On Mac OS X 10.3.9 we have a sequence of nested includes
<unistd.h> -> <signal.h> -> <pthread.h> -> <unistd.h>
@@ -52,7 +52,10 @@
#define _@GUARD_PREFIX@_UNISTD_H
/* NetBSD 5.0 mis-defines NULL. Also get size_t. */
-#include <stddef.h>
+/* But avoid namespace pollution on glibc systems. */
+#ifndef __GLIBC__
+# include <stddef.h>
+#endif
/* mingw doesn't define the SEEK_* or *_FILENO macros in <unistd.h>. */
/* MSVC declares 'unlink' in <stdio.h>, not in <unistd.h>. We must include
@@ -68,9 +71,11 @@
# include <stdio.h>
#endif
-/* Cygwin 1.7.1 declares unlinkat in <fcntl.h>, not in <unistd.h>. */
+/* Cygwin 1.7.1 and Android 4.3 declare unlinkat in <fcntl.h>, not in
+ <unistd.h>. */
/* But avoid namespace pollution on glibc systems. */
-#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) && defined __CYGWIN__ \
+#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) \
+ && (defined __CYGWIN__ || defined __ANDROID__) \
&& ! defined __GLIBC__
# include <fcntl.h>
#endif
@@ -113,17 +118,18 @@
# include <netdb.h>
#endif
-/* MSVC defines off_t in <sys/types.h>.
- May also define off_t to a 64-bit type on native Windows. */
-#if !@HAVE_UNISTD_H@ || @WINDOWS_64_BIT_OFF_T@
-/* Get off_t. */
-# include <sys/types.h>
+/* Android 4.3 declares fchownat in <sys/stat.h>, not in <unistd.h>. */
+/* But avoid namespace pollution on glibc systems. */
+#if (@GNULIB_FCHOWNAT@ || defined GNULIB_POSIXCHECK) && defined __ANDROID__ \
+ && !defined __GLIBC__
+# include <sys/stat.h>
#endif
-#if (@GNULIB_READ@ || @GNULIB_WRITE@ \
- || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \
- || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK)
-/* Get ssize_t. */
+/* 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
@@ -135,7 +141,7 @@
/* Get getopt(), optarg, optind, opterr, optopt. */
-#if @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT
+#if @GNULIB_GETOPT_POSIX@ && @GNULIB_UNISTD_H_GETOPT@ && !defined _GL_SYSTEM_GETOPT
# include <getopt-cdefs.h>
# include <getopt-pfx-core.h>
#endif
@@ -247,10 +253,28 @@ _GL_INLINE_HEADER_BEGIN
/* Declare overridden functions. */
-#if defined GNULIB_POSIXCHECK
+#if @GNULIB_ACCESS@
+# if @REPLACE_ACCESS@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef access
+# define access rpl_access
+# endif
+_GL_FUNCDECL_RPL (access, int, (const char *file, int mode)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (access, int, (const char *file, int mode));
+# else
+_GL_CXXALIAS_SYS (access, int, (const char *file, int mode));
+# endif
+_GL_CXXALIASWARN (access);
+#elif defined GNULIB_POSIXCHECK
+# undef access
+# if HAVE_RAW_DECL_ACCESS
/* The access() function is a security risk. */
-_GL_WARN_ON_USE (access, "the access function is a security risk - "
+_GL_WARN_ON_USE (access, "access does not always support X_OK - "
+ "use gnulib module access for portability; "
+ "also, this function is a security risk - "
"use the gnulib module faccessat instead");
+# endif
#endif
@@ -271,7 +295,7 @@ _GL_WARN_ON_USE (chown, "chdir is not always in <unistd.h> - "
to GID (if GID is not -1). Follow symbolic links.
Return 0 if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/chown.html. */
# if @REPLACE_CHOWN@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef chown
@@ -322,6 +346,24 @@ _GL_WARN_ON_USE (close, "close does not portably work on sockets - "
#endif
+#if @GNULIB_COPY_FILE_RANGE@
+# if !@HAVE_COPY_FILE_RANGE@
+_GL_FUNCDECL_SYS (copy_file_range, ssize_t, (int ifd, off_t *ipos,
+ int ofd, off_t *opos,
+ size_t len, unsigned flags));
+_GL_CXXALIAS_SYS (copy_file_range, ssize_t, (int ifd, off_t *ipos,
+ int ofd, off_t *opos,
+ size_t len, unsigned flags));
+# endif
+_GL_CXXALIASWARN (copy_file_range);
+#elif defined GNULIB_POSIXCHECK
+/* Assume copy_file_range is always declared. */
+_GL_WARN_ON_USE (copy_file_range,
+ "copy_file_range is unportable - "
+ "use gnulib module copy_file_range for portability");
+#endif
+
+
#if @GNULIB_DUP@
# if @REPLACE_DUP@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -347,7 +389,7 @@ _GL_WARN_ON_USE (dup, "dup is unportable - "
NEWFD = OLDFD, otherwise close NEWFD first if it is open.
Return newfd if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/dup2.html>. */
# if @REPLACE_DUP2@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define dup2 rpl_dup2
@@ -502,7 +544,7 @@ _GL_WARN_ON_USE (faccessat, "faccessat is not portable - "
the given file descriptor is open.
Return 0 if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchdir.html>. */
# if ! @HAVE_FCHDIR@
_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/));
@@ -563,7 +605,7 @@ _GL_WARN_ON_USE (fchownat, "fchownat is not portable - "
/* Synchronize changes to a file.
Return 0 if successful, otherwise -1 and errno set.
See POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html>. */
# if !@HAVE_FDATASYNC@ || !@HAVE_DECL_FDATASYNC@
_GL_FUNCDECL_SYS (fdatasync, int, (int fd));
# endif
@@ -582,7 +624,7 @@ _GL_WARN_ON_USE (fdatasync, "fdatasync is unportable - "
/* Synchronize changes, including metadata, to a file.
Return 0 if successful, otherwise -1 and errno set.
See POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html>. */
# if !@HAVE_FSYNC@
_GL_FUNCDECL_SYS (fsync, int, (int fd));
# endif
@@ -601,7 +643,7 @@ _GL_WARN_ON_USE (fsync, "fsync is unportable - "
/* Change the size of the file to which FD is opened to become equal to LENGTH.
Return 0 if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html>. */
# if @REPLACE_FTRUNCATE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef ftruncate
@@ -631,7 +673,7 @@ _GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - "
Return BUF if successful, or NULL if the directory couldn't be determined
or SIZE was too small.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html>.
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getcwd.html>.
Additionally, the gnulib module 'getcwd' guarantees the following GNU
extension: If BUF is NULL, an array is allocated with 'malloc'; the array
is SIZE bytes long, unless SIZE == 0, in which case it is as big as
@@ -707,7 +749,9 @@ _GL_CXXALIAS_RPL (getdtablesize, int, (void));
# if !@HAVE_GETDTABLESIZE@
_GL_FUNCDECL_SYS (getdtablesize, int, (void));
# endif
-_GL_CXXALIAS_SYS (getdtablesize, int, (void));
+/* Need to cast, because on AIX, the parameter list is
+ (...). */
+_GL_CXXALIAS_SYS_CAST (getdtablesize, int, (void));
# endif
_GL_CXXALIASWARN (getdtablesize);
#elif defined GNULIB_POSIXCHECK
@@ -791,7 +835,7 @@ _GL_WARN_ON_USE (gethostname, "gethostname is unportable - "
/* Returns the user's login name, or NULL if it cannot be found. Upon error,
returns NULL with errno set.
- See <http://www.opengroup.org/susv3xsh/getlogin.html>.
+ See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getlogin.html>.
Most programs don't need to use this function, because the information is
available through environment variables:
@@ -820,7 +864,7 @@ _GL_WARN_ON_USE (getlogin, "getlogin is unportable - "
the case that the login name cannot be found but no specific error is
provided (this case is hopefully rare but is left open by the POSIX spec).
- See <http://www.opengroup.org/susv3xsh/getlogin.html>.
+ See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getlogin.html>.
Most programs don't need to use this function, because the information is
available through environment variables:
@@ -861,6 +905,11 @@ _GL_WARN_ON_USE (getlogin_r, "getlogin_r is unportable - "
_GL_FUNCDECL_RPL (getpagesize, int, (void));
_GL_CXXALIAS_RPL (getpagesize, int, (void));
# else
+/* On HP-UX, getpagesize exists, but it is not declared in <unistd.h> even if
+ the compiler options -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 are used. */
+# if defined __hpux
+_GL_FUNCDECL_SYS (getpagesize, int, (void));
+# endif
# if !@HAVE_GETPAGESIZE@
# if !defined getpagesize
/* This is for POSIX systems. */
@@ -1055,7 +1104,7 @@ _GL_WARN_ON_USE (isatty, "isatty has portability problems on native Windows - "
to GID (if GID is not -1). Do not follow symbolic links.
Return 0 if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lchown.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/lchown.html>. */
# if @REPLACE_LCHOWN@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef lchown
@@ -1085,7 +1134,7 @@ _GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - "
/* Create a new hard link for an existing file.
Return 0 if successful, otherwise -1 and errno set.
See POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/link.html>. */
# if @REPLACE_LINK@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define link rpl_link
@@ -1151,7 +1200,7 @@ _GL_WARN_ON_USE (linkat, "linkat is unportable - "
/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END.
Return the new offset if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html>. */
# if @REPLACE_LSEEK@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define lseek rpl_lseek
@@ -1223,7 +1272,7 @@ _GL_WARN_ON_USE (pipe2, "pipe2 is unportable - "
Return the number of bytes placed into BUF if successful, otherwise
set errno and return -1. 0 indicates EOF.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html>. */
# if @REPLACE_PREAD@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef pread
@@ -1258,7 +1307,7 @@ _GL_WARN_ON_USE (pread, "pread is unportable - "
Return the number of bytes written if successful, otherwise
set errno and return -1. 0 indicates nothing written. See the
POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html>. */
# if @REPLACE_PWRITE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef pwrite
@@ -1291,7 +1340,7 @@ _GL_WARN_ON_USE (pwrite, "pwrite is unportable - "
#if @GNULIB_READ@
/* Read up to COUNT bytes from file descriptor FD into the buffer starting
at BUF. See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html>. */
# if @REPLACE_READ@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef read
@@ -1315,7 +1364,7 @@ _GL_CXXALIASWARN (read);
bytes of it into BUF. Return the number of bytes placed into BUF if
successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>. */
# if @REPLACE_READLINK@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define readlink rpl_readlink
@@ -1425,7 +1474,7 @@ _GL_WARN_ON_USE (sethostname, "sethostname is unportable - "
/* Pause the execution of the current thread for N seconds.
Returns the number of seconds left to sleep.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html>. */
# if @REPLACE_SLEEP@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef sleep
@@ -1509,7 +1558,7 @@ _GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - "
/* Change the size of the file designated by FILENAME to become equal to LENGTH.
Return 0 if successful, otherwise -1 and errno set.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html>. */
# if @REPLACE_TRUNCATE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef truncate
@@ -1616,7 +1665,7 @@ _GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - "
/* Pause the execution of the current thread for N microseconds.
Returns 0 on completion, or -1 on range error.
See the POSIX:2001 specification
- <http://www.opengroup.org/susv3xsh/usleep.html>. */
+ <https://pubs.opengroup.org/onlinepubs/009695399/functions/usleep.html>. */
# if @REPLACE_USLEEP@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef usleep
@@ -1628,7 +1677,9 @@ _GL_CXXALIAS_RPL (usleep, int, (useconds_t n));
# if !@HAVE_USLEEP@
_GL_FUNCDECL_SYS (usleep, int, (useconds_t n));
# endif
-_GL_CXXALIAS_SYS (usleep, int, (useconds_t n));
+/* Need to cast, because on Haiku, the first parameter is
+ unsigned int n. */
+_GL_CXXALIAS_SYS_CAST (usleep, int, (useconds_t n));
# endif
_GL_CXXALIASWARN (usleep);
#elif defined GNULIB_POSIXCHECK
@@ -1643,7 +1694,7 @@ _GL_WARN_ON_USE (usleep, "usleep is unportable - "
#if @GNULIB_WRITE@
/* Write up to COUNT bytes starting at BUF to file descriptor FD.
See the POSIX:2008 specification
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>. */
# if @REPLACE_WRITE@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# undef write
diff --git a/lib/unlocked-io.h b/lib/unlocked-io.h
index e3f0fcf..e7f7199 100644
--- a/lib/unlocked-io.h
+++ b/lib/unlocked-io.h
@@ -1,6 +1,6 @@
/* Prefer faster, non-thread-safe stdio functions if available.
- Copyright (C) 2001-2004, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2004, 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
diff --git a/lib/unused-parameter.h b/lib/unused-parameter.h
index 40a0ff8..f5cf21e 100644
--- a/lib/unused-parameter.h
+++ b/lib/unused-parameter.h
@@ -1,5 +1,5 @@
/* A C macro for declaring that specific function parameters are not used.
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ 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
diff --git a/lib/verify.h b/lib/verify.h
index 3b57dde..d9ab89a 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -1,6 +1,6 @@
/* Compile-time assert-like macros.
- Copyright (C) 2005-2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2005-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
@@ -21,31 +21,37 @@
#define _GL_VERIFY_H
-/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert works as per C11.
- This is supported by GCC 4.6.0 and later, in C mode, and its use
- here generates easier-to-read diagnostics when verify (R) fails.
+/* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC)
+ works as per C11. This is supported by GCC 4.6.0 and later, in C
+ mode.
- Define _GL_HAVE_STATIC_ASSERT to 1 if static_assert works as per C++11.
- This will likely be supported by future GCC versions, in C++ mode.
+ Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as
+ per C2X, and define _GL_HAVE_STATIC_ASSERT1 if static_assert (R)
+ works as per C++17. This is supported by GCC 9.1 and later.
- Use this only with GCC. If we were willing to slow 'configure'
- down we could also use it with other compilers, but since this
- affects only the quality of diagnostics, why bother? */
-#if (4 < __GNUC__ + (6 <= __GNUC_MINOR__) \
- && (201112L <= __STDC_VERSION__ || !defined __STRICT_ANSI__) \
- && !defined __cplusplus)
-# define _GL_HAVE__STATIC_ASSERT 1
-#endif
-/* The condition (99 < __GNUC__) is temporary, until we know about the
- first G++ release that supports static_assert. */
-#if (99 < __GNUC__) && defined __cplusplus
-# define _GL_HAVE_STATIC_ASSERT 1
+ Support compilers claiming conformance to the relevant standard,
+ and also support GCC when not pedantic. If we were willing to slow
+ 'configure' down we could also use it with other compilers, but
+ since this affects only the quality of diagnostics, why bother? */
+#ifndef __cplusplus
+# if (201112L <= __STDC_VERSION__ \
+ || (!defined __STRICT_ANSI__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)))
+# define _GL_HAVE__STATIC_ASSERT 1
+# endif
+# if (202000L <= __STDC_VERSION__ \
+ || (!defined __STRICT_ANSI__ && 9 <= __GNUC__))
+# define _GL_HAVE__STATIC_ASSERT1 1
+# endif
+#else
+# if 201703L <= __cplusplus || 9 <= __GNUC__
+# define _GL_HAVE_STATIC_ASSERT1 1
+# endif
#endif
/* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other
system headers, defines a conflicting _Static_assert that is no
better than ours; override it. */
-#ifndef _GL_HAVE_STATIC_ASSERT
+#ifndef _GL_HAVE__STATIC_ASSERT
# include <stddef.h>
# undef _Static_assert
#endif
@@ -143,9 +149,9 @@
which do not support _Static_assert, also do not warn about the
last declaration mentioned above.
- * GCC warns if -Wnested-externs is enabled and verify() is used
+ * GCC warns if -Wnested-externs is enabled and 'verify' is used
within a function body; but inside a function, you can always
- arrange to use verify_expr() instead.
+ arrange to use verify_expr instead.
* In C++, any struct definition inside sizeof is invalid.
Use a template type to work around the problem. */
@@ -197,48 +203,61 @@ template <int w>
#endif
/* Verify requirement R at compile-time, as a declaration without a
- trailing ';'. If R is false, fail at compile-time, preferably
- with a diagnostic that includes the string-literal DIAGNOSTIC.
+ trailing ';'. If R is false, fail at compile-time.
+
+ This macro requires three or more arguments but uses at most the first
+ two, so that the _Static_assert macro optionally defined below supports
+ both the C11 two-argument syntax and the C2X one-argument syntax.
Unfortunately, unlike C11, this implementation must appear as an
ordinary declaration, and cannot appear inside struct { ... }. */
-#ifdef _GL_HAVE__STATIC_ASSERT
-# define _GL_VERIFY _Static_assert
+#if defined _GL_HAVE__STATIC_ASSERT
+# define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
#else
-# define _GL_VERIFY(R, DIAGNOSTIC) \
+# define _GL_VERIFY(R, DIAGNOSTIC, ...) \
extern int (*_GL_GENSYM (_gl_verify_function) (void)) \
[_GL_VERIFY_TRUE (R, DIAGNOSTIC)]
#endif
/* _GL_STATIC_ASSERT_H is defined if this code is copied into assert.h. */
#ifdef _GL_STATIC_ASSERT_H
-# if !defined _GL_HAVE__STATIC_ASSERT && !defined _Static_assert
-# define _Static_assert(R, DIAGNOSTIC) _GL_VERIFY (R, DIAGNOSTIC)
+# if !defined _GL_HAVE__STATIC_ASSERT1 && !defined _Static_assert
+# define _Static_assert(...) \
+ _GL_VERIFY (__VA_ARGS__, "static assertion failed", -)
# endif
-# if !defined _GL_HAVE_STATIC_ASSERT && !defined static_assert
+# if !defined _GL_HAVE_STATIC_ASSERT1 && !defined static_assert
# define static_assert _Static_assert /* C11 requires this #define. */
# endif
#endif
/* @assert.h omit start@ */
+#if 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))
+# define _GL_HAS_BUILTIN_TRAP 1
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_TRAP __has_builtin (__builtin_trap)
+#else
+# define _GL_HAS_BUILTIN_TRAP 0
+#endif
+
+#if 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
+# define _GL_HAS_BUILTIN_UNREACHABLE 1
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_UNREACHABLE __has_builtin (__builtin_unreachable)
+#else
+# define _GL_HAS_BUILTIN_UNREACHABLE 0
+#endif
+
/* Each of these macros verifies that its argument R is nonzero. To
be portable, R should be an integer constant expression. Unlike
assert (R), there is no run-time overhead.
There are two macros, since no single macro can be used in all
- contexts in C. verify_true (R) is for scalar contexts, including
+ contexts in C. verify_expr (R, E) is for scalar contexts, including
integer constant expression contexts. verify (R) is for declaration
contexts, e.g., the top level. */
-/* Verify requirement R at compile-time, as an integer constant expression.
- Return 1. This is equivalent to verify_expr (R, 1).
-
- verify_true is obsolescent; please use verify_expr instead. */
-
-#define verify_true(R) _GL_VERIFY_TRUE (R, "verify_true (" #R ")")
-
/* Verify requirement R at compile-time. Return the value of the
expression E. */
@@ -246,31 +265,28 @@ template <int w>
(_GL_VERIFY_TRUE (R, "verify_expr (" #R ", " #E ")") ? (E) : (E))
/* Verify requirement R at compile-time, as a declaration without a
- trailing ';'. */
+ trailing ';'. verify (R) acts like static_assert (R) except that
+ it is portable to C11/C++14 and earlier, it can issue better
+ diagnostics, and its name is shorter and may be more convenient. */
-#ifdef __GNUC__
-# define verify(R) _GL_VERIFY (R, "verify (" #R ")")
+#ifdef __PGI
+/* PGI barfs if R is long. */
+# define verify(R) _GL_VERIFY (R, "verify (...)", -)
#else
-/* PGI barfs if R is long. Play it safe. */
-# define verify(R) _GL_VERIFY (R, "verify (...)")
-#endif
-
-#ifndef __has_builtin
-# define __has_builtin(x) 0
+# define verify(R) _GL_VERIFY (R, "verify (" #R ")", -)
#endif
-/* Assume that R always holds. This lets the compiler optimize
- accordingly. R should not have side-effects; it may or may not be
- evaluated. Behavior is undefined if R is false. */
+/* Assume that R always holds. Behavior is undefined if R is false,
+ fails to evaluate, or has side effects. Although assuming R can
+ help a compiler generate better code or diagnostics, performance
+ can suffer if R uses hard-to-optimize features such as function
+ calls not inlined by the compiler. */
-#if (__has_builtin (__builtin_unreachable) \
- || 4 < __GNUC__ + (5 <= __GNUC_MINOR__))
+#if _GL_HAS_BUILTIN_UNREACHABLE
# define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
#elif 1200 <= _MSC_VER
# define assume(R) __assume (R)
-#elif ((defined GCC_LINT || defined lint) \
- && (__has_builtin (__builtin_trap) \
- || 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))))
+#elif (defined GCC_LINT || defined lint) && _GL_HAS_BUILTIN_TRAP
/* Doing it this way helps various packages when configured with
--enable-gcc-warnings, which compiles with -Dlint. It's nicer
when 'assume' silences warnings even with older GCCs. */
diff --git a/lib/version-etc-fsf.c b/lib/version-etc-fsf.c
index 098a634..20fa0d0 100644
--- a/lib/version-etc-fsf.c
+++ b/lib/version-etc-fsf.c
@@ -1,5 +1,5 @@
/* Variable with FSF copyright information, for version-etc.
- Copyright (C) 1999-2006, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-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
diff --git a/lib/version-etc.c b/lib/version-etc.c
index dfec8ad..506f017 100644
--- a/lib/version-etc.c
+++ b/lib/version-etc.c
@@ -1,5 +1,5 @@
/* Print --version and bug-reporting information in a consistent format.
- Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999-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
@@ -37,7 +37,7 @@
# define PACKAGE PACKAGE_TARNAME
#endif
-enum { COPYRIGHT_YEAR = 2018 };
+enum { COPYRIGHT_YEAR = 2020 };
/* The three functions below display the --version information the
standard way.
@@ -82,14 +82,17 @@ version_etc_arn (FILE *stream,
locale. Otherwise, do not translate "(C)"; leave it as-is. */
fprintf (stream, version_etc_copyright, _("(C)"), COPYRIGHT_YEAR);
- fputs (_("\
-\n\
-License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.\n\
+ fputs ("\n", stream);
+
+ /* TRANSLATORS: The %s placeholder is the web address of the GPL license. */
+ fprintf (stream, _("\
+License GPLv3+: GNU GPL version 3 or later <%s>.\n\
This is free software: you are free to change and redistribute it.\n\
There is NO WARRANTY, to the extent permitted by law.\n\
-\n\
"),
- stream);
+ "https://gnu.org/licenses/gpl.html");
+
+ fputs ("\n", stream);
switch (n_authors)
{
@@ -238,11 +241,12 @@ version_etc (FILE *stream,
void
emit_bug_reporting_address (void)
{
+ fputs ("\n", stdout);
/* TRANSLATORS: The placeholder indicates the bug-reporting address
for this package. Please add _another line_ saying
"Report translation bugs to <...>\n" with the address for translation
bugs (typically your translation team's web or email address). */
- printf (_("\nReport bugs to: %s\n"), PACKAGE_BUGREPORT);
+ printf (_("Report bugs to: %s\n"), PACKAGE_BUGREPORT);
#ifdef PACKAGE_PACKAGER_BUG_REPORTS
printf (_("Report %s bugs to: %s\n"), PACKAGE_PACKAGER,
PACKAGE_PACKAGER_BUG_REPORTS);
@@ -250,9 +254,9 @@ emit_bug_reporting_address (void)
#ifdef PACKAGE_URL
printf (_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
#else
- printf (_("%s home page: <https://www.gnu.org/software/%s/>\n"),
- PACKAGE_NAME, PACKAGE);
+ printf (_("%s home page: <%s>\n"),
+ PACKAGE_NAME, "https://www.gnu.org/software/" PACKAGE "/");
#endif
- fputs (_("General help using GNU software: <https://www.gnu.org/gethelp/>\n"),
- stdout);
+ printf (_("General help using GNU software: <%s>\n"),
+ "https://www.gnu.org/gethelp/");
}
diff --git a/lib/version-etc.h b/lib/version-etc.h
index 3b06bf9..73cad56 100644
--- a/lib/version-etc.h
+++ b/lib/version-etc.h
@@ -1,5 +1,5 @@
/* Print --version and bug-reporting information in a consistent format.
- Copyright (C) 1999, 2003, 2005, 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2003, 2005, 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
diff --git a/lib/warn-on-use.h b/lib/warn-on-use.h
index 72d67cc..1be2cbb 100644
--- a/lib/warn-on-use.h
+++ b/lib/warn-on-use.h
@@ -1,5 +1,5 @@
/* A C macro for emitting warnings if a function is used.
- Copyright (C) 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2010-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
diff --git a/lib/wchar.in.h b/lib/wchar.in.h
index 51a5dda..63a02a4 100644
--- a/lib/wchar.in.h
+++ b/lib/wchar.in.h
@@ -1,6 +1,6 @@
/* A substitute for ISO C99 <wchar.h>, for platforms that have issues.
- Copyright (C) 2007-2018 Free Software Foundation, Inc.
+ Copyright (C) 2007-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
@@ -19,7 +19,7 @@
/*
* ISO C 99 <wchar.h> for platforms that have issues.
- * <http://www.opengroup.org/susv3xbd/wchar.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wchar.h.html>
*
* For now, this just ensures proper prerequisite inclusion order and
* the declaration of wcwidth().
@@ -33,7 +33,8 @@
#if (((defined __need_mbstate_t || defined __need_wint_t) \
&& !defined __MINGW32__) \
|| (defined __hpux \
- && ((defined _INTTYPES_INCLUDED && !defined strtoimax) \
+ && ((defined _INTTYPES_INCLUDED \
+ && !defined _GL_FINISHED_INCLUDING_SYSTEM_INTTYPES_H) \
|| defined _GL_JUST_INCLUDE_SYSTEM_WCHAR_H)) \
|| (defined __MINGW32__ && defined __STRING_H_SOURCED__) \
|| defined _GL_ALREADY_INCLUDING_WCHAR_H)
@@ -137,12 +138,16 @@ typedef unsigned int rpl_wint_t;
/* Override mbstate_t if it is too small.
On IRIX 6.5, sizeof (mbstate_t) == 1, which is not sufficient for
- implementing mbrtowc for encodings like UTF-8. */
-#if !(@HAVE_MBSINIT@ && @HAVE_MBRTOWC@) || @REPLACE_MBSTATE_T@
+ implementing mbrtowc for encodings like UTF-8.
+ On AIX and MSVC, mbrtowc needs to be overridden, but mbstate_t exists and is
+ large enough and overriding it would cause problems in C++ mode. */
+#if !(((defined _WIN32 && !defined __CYGWIN__) || @HAVE_MBSINIT@) && @HAVE_MBRTOWC@) || @REPLACE_MBSTATE_T@
# if !GNULIB_defined_mbstate_t
+# if !(defined _AIX || defined _MSC_VER)
typedef int rpl_mbstate_t;
-# undef mbstate_t
-# define mbstate_t rpl_mbstate_t
+# undef mbstate_t
+# define mbstate_t rpl_mbstate_t
+# endif
# define GNULIB_defined_mbstate_t 1
# endif
#endif
@@ -161,9 +166,12 @@ _GL_CXXALIAS_RPL (btowc, wint_t, (int c));
# if !@HAVE_BTOWC@
_GL_FUNCDECL_SYS (btowc, wint_t, (int c) _GL_ATTRIBUTE_PURE);
# endif
-_GL_CXXALIAS_SYS (btowc, wint_t, (int c));
+/* Need to cast, because on mingw, the return type is 'unsigned short'. */
+_GL_CXXALIAS_SYS_CAST (btowc, wint_t, (int c));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (btowc);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef btowc
# if HAVE_RAW_DECL_BTOWC
@@ -189,7 +197,9 @@ _GL_FUNCDECL_SYS (wctob, int, (wint_t wc) _GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wctob, int, (wint_t wc));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wctob);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wctob
# if HAVE_RAW_DECL_WCTOB
@@ -214,7 +224,9 @@ _GL_FUNCDECL_SYS (mbsinit, int, (const mbstate_t *ps));
# endif
_GL_CXXALIAS_SYS (mbsinit, int, (const mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbsinit);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef mbsinit
# if HAVE_RAW_DECL_MBSINIT
@@ -243,7 +255,9 @@ _GL_FUNCDECL_SYS (mbrtowc, size_t,
_GL_CXXALIAS_SYS (mbrtowc, size_t,
(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbrtowc);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef mbrtowc
# if HAVE_RAW_DECL_MBRTOWC
@@ -268,7 +282,9 @@ _GL_FUNCDECL_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps));
# endif
_GL_CXXALIAS_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbrlen);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef mbrlen
# if HAVE_RAW_DECL_MBRLEN
@@ -301,7 +317,9 @@ _GL_CXXALIAS_SYS (mbsrtowcs, size_t,
(wchar_t *dest, const char **srcp, size_t len,
mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (mbsrtowcs);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef mbsrtowcs
# if HAVE_RAW_DECL_MBSRTOWCS
@@ -361,7 +379,9 @@ _GL_FUNCDECL_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps));
# endif
_GL_CXXALIAS_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcrtomb);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcrtomb
# if HAVE_RAW_DECL_WCRTOMB
@@ -394,7 +414,9 @@ _GL_CXXALIAS_SYS (wcsrtombs, size_t,
(char *dest, const wchar_t **srcp, size_t len,
mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsrtombs);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsrtombs
# if HAVE_RAW_DECL_WCSRTOMBS
@@ -419,7 +441,7 @@ _GL_CXXALIAS_RPL (wcsnrtombs, size_t,
(char *dest, const wchar_t **srcp, size_t srclen, size_t len,
mbstate_t *ps));
# else
-# if !@HAVE_WCSNRTOMBS@
+# if !@HAVE_WCSNRTOMBS@ || (defined __cplusplus && defined __sun)
_GL_FUNCDECL_SYS (wcsnrtombs, size_t,
(char *dest, const wchar_t **srcp, size_t srclen, size_t len,
mbstate_t *ps)
@@ -429,7 +451,9 @@ _GL_CXXALIAS_SYS (wcsnrtombs, size_t,
(char *dest, const wchar_t **srcp, size_t srclen, size_t len,
mbstate_t *ps));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsnrtombs);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsnrtombs
# if HAVE_RAW_DECL_WCSNRTOMBS
@@ -455,7 +479,9 @@ _GL_FUNCDECL_SYS (wcwidth, int, (wchar_t) _GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcwidth, int, (wchar_t));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcwidth);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcwidth
# if HAVE_RAW_DECL_WCWIDTH
@@ -484,7 +510,7 @@ _GL_CXXALIAS_SYS_CAST2 (wmemchr,
_GL_CXXALIASWARN1 (wmemchr, wchar_t *, (wchar_t *s, wchar_t c, size_t n));
_GL_CXXALIASWARN1 (wmemchr, const wchar_t *,
(const wchar_t *s, wchar_t c, size_t n));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemchr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -505,7 +531,9 @@ _GL_FUNCDECL_SYS (wmemcmp, int,
# endif
_GL_CXXALIAS_SYS (wmemcmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemcmp);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemcmp
# if HAVE_RAW_DECL_WMEMCMP
@@ -523,7 +551,9 @@ _GL_FUNCDECL_SYS (wmemcpy, wchar_t *,
# endif
_GL_CXXALIAS_SYS (wmemcpy, wchar_t *,
(wchar_t *dest, const wchar_t *src, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemcpy);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemcpy
# if HAVE_RAW_DECL_WMEMCPY
@@ -542,7 +572,9 @@ _GL_FUNCDECL_SYS (wmemmove, wchar_t *,
# endif
_GL_CXXALIAS_SYS (wmemmove, wchar_t *,
(wchar_t *dest, const wchar_t *src, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemmove);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemmove
# if HAVE_RAW_DECL_WMEMMOVE
@@ -558,7 +590,9 @@ _GL_WARN_ON_USE (wmemmove, "wmemmove is unportable - "
_GL_FUNCDECL_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n));
# endif
_GL_CXXALIAS_SYS (wmemset, wchar_t *, (wchar_t *s, wchar_t c, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wmemset);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wmemset
# if HAVE_RAW_DECL_WMEMSET
@@ -574,7 +608,9 @@ _GL_WARN_ON_USE (wmemset, "wmemset is unportable - "
_GL_FUNCDECL_SYS (wcslen, size_t, (const wchar_t *s) _GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcslen, size_t, (const wchar_t *s));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcslen);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcslen
# if HAVE_RAW_DECL_WCSLEN
@@ -607,7 +643,9 @@ _GL_WARN_ON_USE (wcsnlen, "wcsnlen is unportable - "
_GL_FUNCDECL_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src));
# endif
_GL_CXXALIAS_SYS (wcscpy, wchar_t *, (wchar_t *dest, const wchar_t *src));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscpy);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscpy
# if HAVE_RAW_DECL_WCSCPY
@@ -641,7 +679,9 @@ _GL_FUNCDECL_SYS (wcsncpy, wchar_t *,
# endif
_GL_CXXALIAS_SYS (wcsncpy, wchar_t *,
(wchar_t *dest, const wchar_t *src, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsncpy);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsncpy
# if HAVE_RAW_DECL_WCSNCPY
@@ -676,7 +716,9 @@ _GL_WARN_ON_USE (wcpncpy, "wcpncpy is unportable - "
_GL_FUNCDECL_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src));
# endif
_GL_CXXALIAS_SYS (wcscat, wchar_t *, (wchar_t *dest, const wchar_t *src));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscat);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscat
# if HAVE_RAW_DECL_WCSCAT
@@ -694,7 +736,9 @@ _GL_FUNCDECL_SYS (wcsncat, wchar_t *,
# endif
_GL_CXXALIAS_SYS (wcsncat, wchar_t *,
(wchar_t *dest, const wchar_t *src, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsncat);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsncat
# if HAVE_RAW_DECL_WCSNCAT
@@ -711,7 +755,9 @@ _GL_FUNCDECL_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcscmp, int, (const wchar_t *s1, const wchar_t *s2));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscmp);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscmp
# if HAVE_RAW_DECL_WCSCMP
@@ -730,7 +776,9 @@ _GL_FUNCDECL_SYS (wcsncmp, int,
# endif
_GL_CXXALIAS_SYS (wcsncmp, int,
(const wchar_t *s1, const wchar_t *s2, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsncmp);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsncmp
# if HAVE_RAW_DECL_WCSNCMP
@@ -783,7 +831,9 @@ _GL_WARN_ON_USE (wcsncasecmp, "wcsncasecmp is unportable - "
_GL_FUNCDECL_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2));
# endif
_GL_CXXALIAS_SYS (wcscoll, int, (const wchar_t *s1, const wchar_t *s2));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscoll);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscoll
# if HAVE_RAW_DECL_WCSCOLL
@@ -801,7 +851,9 @@ _GL_WARN_ON_USE (wcscoll, "wcscoll is unportable - "
_GL_FUNCDECL_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n));
# endif
_GL_CXXALIAS_SYS (wcsxfrm, size_t, (wchar_t *s1, const wchar_t *s2, size_t n));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsxfrm);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsxfrm
# if HAVE_RAW_DECL_WCSXFRM
@@ -845,7 +897,7 @@ _GL_CXXALIAS_SYS_CAST2 (wcschr,
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wcschr, wchar_t *, (wchar_t *wcs, wchar_t wc));
_GL_CXXALIASWARN1 (wcschr, const wchar_t *, (const wchar_t *wcs, wchar_t wc));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcschr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -875,7 +927,7 @@ _GL_CXXALIAS_SYS_CAST2 (wcsrchr,
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
_GL_CXXALIASWARN1 (wcsrchr, wchar_t *, (wchar_t *wcs, wchar_t wc));
_GL_CXXALIASWARN1 (wcsrchr, const wchar_t *, (const wchar_t *wcs, wchar_t wc));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsrchr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -895,7 +947,9 @@ _GL_FUNCDECL_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcscspn, size_t, (const wchar_t *wcs, const wchar_t *reject));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcscspn);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcscspn
# if HAVE_RAW_DECL_WCSCSPN
@@ -913,7 +967,9 @@ _GL_FUNCDECL_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept)
_GL_ATTRIBUTE_PURE);
# endif
_GL_CXXALIAS_SYS (wcsspn, size_t, (const wchar_t *wcs, const wchar_t *accept));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsspn);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsspn
# if HAVE_RAW_DECL_WCSSPN
@@ -944,7 +1000,7 @@ _GL_CXXALIASWARN1 (wcspbrk, wchar_t *,
(wchar_t *wcs, const wchar_t *accept));
_GL_CXXALIASWARN1 (wcspbrk, const wchar_t *,
(const wchar_t *wcs, const wchar_t *accept));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcspbrk);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -977,7 +1033,7 @@ _GL_CXXALIASWARN1 (wcsstr, wchar_t *,
(wchar_t *haystack, const wchar_t *needle));
_GL_CXXALIASWARN1 (wcsstr, const wchar_t *,
(const wchar_t *haystack, const wchar_t *needle));
-# else
+# elif __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsstr);
# endif
#elif defined GNULIB_POSIXCHECK
@@ -991,13 +1047,26 @@ _GL_WARN_ON_USE (wcsstr, "wcsstr is unportable - "
/* Divide WCS into tokens separated by characters in DELIM. */
#if @GNULIB_WCSTOK@
-# if !@HAVE_WCSTOK@
+# if @REPLACE_WCSTOK@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef wcstok
+# define wcstok rpl_wcstok
+# endif
+_GL_FUNCDECL_RPL (wcstok, wchar_t *,
+ (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+_GL_CXXALIAS_RPL (wcstok, wchar_t *,
+ (wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+# else
+# if !@HAVE_WCSTOK@
_GL_FUNCDECL_SYS (wcstok, wchar_t *,
(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
-# endif
+# endif
_GL_CXXALIAS_SYS (wcstok, wchar_t *,
(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr));
+# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcstok);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcstok
# if HAVE_RAW_DECL_WCSTOK
@@ -1025,7 +1094,9 @@ _GL_FUNCDECL_SYS (wcswidth, int, (const wchar_t *s, size_t n)
# endif
_GL_CXXALIAS_SYS (wcswidth, int, (const wchar_t *s, size_t n));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcswidth);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcswidth
# if HAVE_RAW_DECL_WCSWIDTH
@@ -1036,7 +1107,7 @@ _GL_WARN_ON_USE (wcswidth, "wcswidth is unportable - "
/* Convert *TP to a date and time wide string. See
- <http://pubs.opengroup.org/onlinepubs/9699919799/functions/wcsftime.html>. */
+ <https://pubs.opengroup.org/onlinepubs/9699919799/functions/wcsftime.html>. */
#if @GNULIB_WCSFTIME@
# if @REPLACE_WCSFTIME@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
@@ -1057,7 +1128,9 @@ _GL_FUNCDECL_SYS (wcsftime, size_t, (wchar_t *__buf, size_t __bufsize,
_GL_CXXALIAS_SYS (wcsftime, size_t, (wchar_t *__buf, size_t __bufsize,
const wchar_t *__fmt, const struct tm *__tp));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wcsftime);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wcsftime
# if HAVE_RAW_DECL_WCSFTIME
diff --git a/lib/wcrtomb.c b/lib/wcrtomb.c
index 8f01972..06105f1 100644
--- a/lib/wcrtomb.c
+++ b/lib/wcrtomb.c
@@ -1,5 +1,5 @@
/* Convert wide character to multibyte character.
- Copyright (C) 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 2008-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
@@ -26,20 +26,46 @@
size_t
wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
+#undef wcrtomb
{
- /* This implementation of wcrtomb on top of wctomb() supports only
- stateless encodings. ps must be in the initial state. */
+ /* This implementation of wcrtomb supports only stateless encodings.
+ ps must be in the initial state. */
if (ps != NULL && !mbsinit (ps))
{
errno = EINVAL;
return (size_t)(-1);
}
+#if !HAVE_WCRTOMB /* IRIX 6.5 */ \
+ || WCRTOMB_RETVAL_BUG /* Solaris 11.3, MSVC */ \
+ || WCRTOMB_C_LOCALE_BUG /* Android */
if (s == NULL)
/* We know the NUL wide character corresponds to the NUL character. */
return 1;
else
+#endif
{
+#if HAVE_WCRTOMB
+# if WCRTOMB_C_LOCALE_BUG /* Android */
+ /* Implement consistently with mbrtowc(): through a 1:1 correspondence,
+ as in ISO-8859-1. */
+ if (wc >= 0 && wc <= 0xff)
+ {
+ *s = (unsigned char) wc;
+ return 1;
+ }
+ else
+ {
+ errno = EILSEQ;
+ return (size_t)(-1);
+ }
+# else
+ return wcrtomb (s, wc, ps);
+# endif
+#else /* IRIX 6.5 */
+ /* Fallback for platforms that don't have wcrtomb().
+ Implement on top of wctomb().
+ This code is not multithread-safe. */
int ret = wctomb (s, wc);
if (ret >= 0)
@@ -49,5 +75,6 @@ wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
errno = EILSEQ;
return (size_t)(-1);
}
+#endif
}
}
diff --git a/lib/wctob.c b/lib/wctob.c
index 070f97a..7d08863 100644
--- a/lib/wctob.c
+++ b/lib/wctob.c
@@ -1,5 +1,5 @@
/* Convert wide character to unibyte character.
- Copyright (C) 2008, 2010-2018 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2010-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/wctomb-impl.h b/lib/wctomb-impl.h
index 58c3c0c..cca56bb 100644
--- a/lib/wctomb-impl.h
+++ b/lib/wctomb-impl.h
@@ -1,5 +1,5 @@
/* Convert wide character to multibyte character.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2011.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/wctomb.c b/lib/wctomb.c
index 47addc4..55ec077 100644
--- a/lib/wctomb.c
+++ b/lib/wctomb.c
@@ -1,5 +1,5 @@
/* Convert wide character to multibyte character.
- Copyright (C) 2011-2018 Free Software Foundation, Inc.
+ Copyright (C) 2011-2020 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2011.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/wctype.in.h b/lib/wctype.in.h
index 3c6e5f2..df72be4 100644
--- a/lib/wctype.in.h
+++ b/lib/wctype.in.h
@@ -1,6 +1,6 @@
/* A substitute for ISO C99 <wctype.h>, for platforms that lack it.
- Copyright (C) 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 2006-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
@@ -19,7 +19,7 @@
/*
* ISO C 99 <wctype.h> for platforms that lack it.
- * <http://www.opengroup.org/susv3xbd/wctype.h.html>
+ * <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wctype.h.html>
*
* iswctype, towctrans, towlower, towupper, wctrans, wctype,
* wctrans_t, and wctype_t are not yet implemented.
@@ -133,33 +133,113 @@ typedef unsigned int rpl_wint_t;
/* FreeBSD 4.4 to 4.11 has <wctype.h> but lacks the functions.
Linux libc5 has <wctype.h> and the functions but they are broken.
+ mingw and MSVC have <wctype.h> and the functions but they take a wchar_t
+ as argument, not an rpl_wint_t.
Assume all 11 functions (all isw* except iswblank) are implemented the
same way, or not at all. */
# if ! @HAVE_ISWCNTRL@ || @REPLACE_ISWCNTRL@
-/* IRIX 5.3 has macros but no functions, its isw* macros refer to an
- undefined variable _ctmp_ and to <ctype.h> macros like _P, and they
- refer to system functions like _iswctype that are not in the
- standard C library. Rather than try to get ancient buggy
- implementations like this to work, just disable them. */
-# undef iswalnum
-# undef iswalpha
-# undef iswblank
-# undef iswcntrl
-# undef iswdigit
-# undef iswgraph
-# undef iswlower
-# undef iswprint
-# undef iswpunct
-# undef iswspace
-# undef iswupper
-# undef iswxdigit
-# undef towlower
-# undef towupper
+# if @GNULIB_OVERRIDES_WINT_T@ /* implies @REPLACE_ISWCNTRL@ */
+
+_GL_WCTYPE_INLINE int
+rpl_iswalnum (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswalnum ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswalpha (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswalpha ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswblank (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswblank ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswcntrl (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswcntrl ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswdigit (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswdigit ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswgraph (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswgraph ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswlower (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswlower ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswprint (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswprint ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswpunct (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswpunct ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswspace (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswspace ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswupper (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswupper ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE int
+rpl_iswxdigit (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? iswxdigit ((wchar_t) wc) : 0);
+}
+
+_GL_WCTYPE_INLINE wint_t
+rpl_towlower (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? (wchar_t) towlower ((wchar_t) wc) : wc);
+}
+
+_GL_WCTYPE_INLINE wint_t
+rpl_towupper (wint_t wc)
+{
+ return ((wchar_t) wc == wc ? (wchar_t) towupper ((wchar_t) wc) : wc);
+}
-/* Linux libc5 has <wctype.h> and the functions but they are broken. */
-# if @REPLACE_ISWCNTRL@
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef iswalnum
+# undef iswalpha
+# undef iswblank
+# undef iswcntrl
+# undef iswdigit
+# undef iswgraph
+# undef iswlower
+# undef iswprint
+# undef iswpunct
+# undef iswspace
+# undef iswupper
+# undef iswxdigit
+# undef towlower
+# undef towupper
# define iswalnum rpl_iswalnum
# define iswalpha rpl_iswalpha
# define iswblank rpl_iswblank
@@ -172,21 +252,62 @@ typedef unsigned int rpl_wint_t;
# define iswspace rpl_iswspace
# define iswupper rpl_iswupper
# define iswxdigit rpl_iswxdigit
-# endif
-# endif
-# if @REPLACE_TOWLOWER@
-# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define towlower rpl_towlower
# define towupper rpl_towupper
# endif
-# endif
+
+# else
+
+/* IRIX 5.3 has macros but no functions, its isw* macros refer to an
+ undefined variable _ctmp_ and to <ctype.h> macros like _P, and they
+ refer to system functions like _iswctype that are not in the
+ standard C library. Rather than try to get ancient buggy
+ implementations like this to work, just disable them. */
+# undef iswalnum
+# undef iswalpha
+# undef iswblank
+# undef iswcntrl
+# undef iswdigit
+# undef iswgraph
+# undef iswlower
+# undef iswprint
+# undef iswpunct
+# undef iswspace
+# undef iswupper
+# undef iswxdigit
+# undef towlower
+# undef towupper
+
+/* Linux libc5 has <wctype.h> and the functions but they are broken. */
+# if @REPLACE_ISWCNTRL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define iswalnum rpl_iswalnum
+# define iswalpha rpl_iswalpha
+# define iswblank rpl_iswblank
+# define iswcntrl rpl_iswcntrl
+# define iswdigit rpl_iswdigit
+# define iswgraph rpl_iswgraph
+# define iswlower rpl_iswlower
+# define iswprint rpl_iswprint
+# define iswpunct rpl_iswpunct
+# define iswspace rpl_iswspace
+# define iswupper rpl_iswupper
+# define iswxdigit rpl_iswxdigit
+# endif
+# endif
+# if @REPLACE_TOWLOWER@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define towlower rpl_towlower
+# define towupper rpl_towupper
+# endif
+# endif
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswalnum
-# else
+# else
iswalnum
-# endif
+# endif
(wint_t wc)
{
return ((wc >= '0' && wc <= '9')
@@ -194,88 +315,88 @@ iswalnum
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswalpha
-# else
+# else
iswalpha
-# endif
+# endif
(wint_t wc)
{
return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswblank
-# else
+# else
iswblank
-# endif
+# endif
(wint_t wc)
{
return wc == ' ' || wc == '\t';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswcntrl
-# else
+# else
iswcntrl
-# endif
+# endif
(wint_t wc)
{
return (wc & ~0x1f) == 0 || wc == 0x7f;
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswdigit
-# else
+# else
iswdigit
-# endif
+# endif
(wint_t wc)
{
return wc >= '0' && wc <= '9';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswgraph
-# else
+# else
iswgraph
-# endif
+# endif
(wint_t wc)
{
return wc >= '!' && wc <= '~';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswlower
-# else
+# else
iswlower
-# endif
+# endif
(wint_t wc)
{
return wc >= 'a' && wc <= 'z';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswprint
-# else
+# else
iswprint
-# endif
+# endif
(wint_t wc)
{
return wc >= ' ' && wc <= '~';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswpunct
-# else
+# else
iswpunct
-# endif
+# endif
(wint_t wc)
{
return (wc >= '!' && wc <= '~'
@@ -284,11 +405,11 @@ iswpunct
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswspace
-# else
+# else
iswspace
-# endif
+# endif
(wint_t wc)
{
return (wc == ' ' || wc == '\t'
@@ -296,22 +417,22 @@ iswspace
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswupper
-# else
+# else
iswupper
-# endif
+# endif
(wint_t wc)
{
return wc >= 'A' && wc <= 'Z';
}
_GL_WCTYPE_INLINE int
-# if @REPLACE_ISWCNTRL@
+# if @REPLACE_ISWCNTRL@
rpl_iswxdigit
-# else
+# else
iswxdigit
-# endif
+# endif
(wint_t wc)
{
return ((wc >= '0' && wc <= '9')
@@ -319,27 +440,29 @@ iswxdigit
}
_GL_WCTYPE_INLINE wint_t
-# if @REPLACE_TOWLOWER@
+# if @REPLACE_TOWLOWER@
rpl_towlower
-# else
+# else
towlower
-# endif
+# endif
(wint_t wc)
{
return (wc >= 'A' && wc <= 'Z' ? wc - 'A' + 'a' : wc);
}
_GL_WCTYPE_INLINE wint_t
-# if @REPLACE_TOWLOWER@
+# if @REPLACE_TOWLOWER@
rpl_towupper
-# else
+# else
towupper
-# endif
+# endif
(wint_t wc)
{
return (wc >= 'a' && wc <= 'z' ? wc - 'a' + 'A' : wc);
}
+# endif
+
# elif @GNULIB_ISWBLANK@ && (! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@)
/* Only the iswblank function is missing. */
@@ -354,7 +477,7 @@ _GL_FUNCDECL_SYS (iswblank, int, (wint_t wc));
# endif
-# if defined __MINGW32__
+# if defined __MINGW32__ && !@GNULIB_OVERRIDES_WINT_T@
/* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t.
The functions towlower and towupper are implemented in the MSVCRT library
@@ -387,7 +510,7 @@ rpl_towupper (wint_t wc)
# define towupper rpl_towupper
# endif
-# endif /* __MINGW32__ */
+# endif /* __MINGW32__ && !@GNULIB_OVERRIDES_WINT_T@ */
# define GNULIB_defined_wctype_functions 1
#endif
@@ -417,6 +540,7 @@ _GL_CXXALIAS_SYS (iswspace, int, (wint_t wc));
_GL_CXXALIAS_SYS (iswupper, int, (wint_t wc));
_GL_CXXALIAS_SYS (iswxdigit, int, (wint_t wc));
#endif
+#if __GLIBC__ >= 2
_GL_CXXALIASWARN (iswalnum);
_GL_CXXALIASWARN (iswalpha);
_GL_CXXALIASWARN (iswcntrl);
@@ -428,6 +552,7 @@ _GL_CXXALIASWARN (iswpunct);
_GL_CXXALIASWARN (iswspace);
_GL_CXXALIASWARN (iswupper);
_GL_CXXALIASWARN (iswxdigit);
+#endif
#if @GNULIB_ISWBLANK@
# if @REPLACE_ISWCNTRL@ || @REPLACE_ISWBLANK@
@@ -435,7 +560,9 @@ _GL_CXXALIAS_RPL (iswblank, int, (wint_t wc));
# else
_GL_CXXALIAS_SYS (iswblank, int, (wint_t wc));
# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (iswblank);
+# endif
#endif
#if !@HAVE_WCTYPE_T@
@@ -451,7 +578,9 @@ typedef void * wctype_t;
_GL_FUNCDECL_SYS (wctype, wctype_t, (const char *name));
# endif
_GL_CXXALIAS_SYS (wctype, wctype_t, (const char *name));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wctype);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wctype
# if HAVE_RAW_DECL_WCTYPE
@@ -464,11 +593,22 @@ _GL_WARN_ON_USE (wctype, "wctype is unportable - "
The argument WC must be either a wchar_t value or WEOF.
The argument DESC must have been returned by the wctype() function. */
#if @GNULIB_ISWCTYPE@
-# if !@HAVE_WCTYPE_T@
+# if @GNULIB_OVERRIDES_WINT_T@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# undef iswctype
+# define iswctype rpl_iswctype
+# endif
+_GL_FUNCDECL_RPL (iswctype, int, (wint_t wc, wctype_t desc));
+_GL_CXXALIAS_RPL (iswctype, int, (wint_t wc, wctype_t desc));
+# else
+# if !@HAVE_WCTYPE_T@
_GL_FUNCDECL_SYS (iswctype, int, (wint_t wc, wctype_t desc));
-# endif
+# endif
_GL_CXXALIAS_SYS (iswctype, int, (wint_t wc, wctype_t desc));
+# endif
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (iswctype);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef iswctype
# if HAVE_RAW_DECL_ISWCTYPE
@@ -484,8 +624,10 @@ _GL_CXXALIAS_RPL (towupper, wint_t, (wint_t wc));
_GL_CXXALIAS_SYS (towlower, wint_t, (wint_t wc));
_GL_CXXALIAS_SYS (towupper, wint_t, (wint_t wc));
#endif
+#if __GLIBC__ >= 2
_GL_CXXALIASWARN (towlower);
_GL_CXXALIASWARN (towupper);
+#endif
#if !@HAVE_WCTRANS_T@
# if !GNULIB_defined_wctrans_t
@@ -500,7 +642,9 @@ typedef void * wctrans_t;
_GL_FUNCDECL_SYS (wctrans, wctrans_t, (const char *name));
# endif
_GL_CXXALIAS_SYS (wctrans, wctrans_t, (const char *name));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (wctrans);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef wctrans
# if HAVE_RAW_DECL_WCTRANS
@@ -517,7 +661,9 @@ _GL_WARN_ON_USE (wctrans, "wctrans is unportable - "
_GL_FUNCDECL_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc));
# endif
_GL_CXXALIAS_SYS (towctrans, wint_t, (wint_t wc, wctrans_t desc));
+# if __GLIBC__ >= 2
_GL_CXXALIASWARN (towctrans);
+# endif
#elif defined GNULIB_POSIXCHECK
# undef towctrans
# if HAVE_RAW_DECL_TOWCTRANS
diff --git a/lib/windows-initguard.h b/lib/windows-initguard.h
new file mode 100644
index 0000000..c4be45a
--- /dev/null
+++ b/lib/windows-initguard.h
@@ -0,0 +1,35 @@
+/* Init guards, somewhat like spinlocks (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#ifndef _WINDOWS_INITGUARD_H
+#define _WINDOWS_INITGUARD_H
+
+#define WIN32_LEAN_AND_MEAN /* avoid including junk */
+#include <windows.h>
+
+typedef struct
+ {
+ volatile int done;
+ volatile LONG started;
+ }
+ glwthread_initguard_t;
+
+#define GLWTHREAD_INITGUARD_INIT { 0, -1 }
+
+#endif /* _WINDOWS_INITGUARD_H */
diff --git a/lib/windows-mutex.c b/lib/windows-mutex.c
new file mode 100644
index 0000000..7eb38a2
--- /dev/null
+++ b/lib/windows-mutex.c
@@ -0,0 +1,95 @@
+/* Plain mutexes (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#include <config.h>
+
+/* Specification. */
+#include "windows-mutex.h"
+
+#include <errno.h>
+
+void
+glwthread_mutex_init (glwthread_mutex_t *mutex)
+{
+ InitializeCriticalSection (&mutex->lock);
+ mutex->guard.done = 1;
+}
+
+int
+glwthread_mutex_lock (glwthread_mutex_t *mutex)
+{
+ if (!mutex->guard.done)
+ {
+ if (InterlockedIncrement (&mutex->guard.started) == 0)
+ /* This thread is the first one to need this mutex. Initialize it. */
+ glwthread_mutex_init (mutex);
+ else
+ {
+ /* Don't let mutex->guard.started grow and wrap around. */
+ InterlockedDecrement (&mutex->guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this mutex. */
+ while (!mutex->guard.done)
+ Sleep (0);
+ }
+ }
+ EnterCriticalSection (&mutex->lock);
+ return 0;
+}
+
+int
+glwthread_mutex_trylock (glwthread_mutex_t *mutex)
+{
+ if (!mutex->guard.done)
+ {
+ if (InterlockedIncrement (&mutex->guard.started) == 0)
+ /* This thread is the first one to need this mutex. Initialize it. */
+ glwthread_mutex_init (mutex);
+ else
+ {
+ /* Don't let mutex->guard.started grow and wrap around. */
+ InterlockedDecrement (&mutex->guard.started);
+ /* Let another thread finish initializing this mutex, and let it also
+ lock this mutex. */
+ return EBUSY;
+ }
+ }
+ if (!TryEnterCriticalSection (&mutex->lock))
+ return EBUSY;
+ return 0;
+}
+
+int
+glwthread_mutex_unlock (glwthread_mutex_t *mutex)
+{
+ if (!mutex->guard.done)
+ return EINVAL;
+ LeaveCriticalSection (&mutex->lock);
+ return 0;
+}
+
+int
+glwthread_mutex_destroy (glwthread_mutex_t *mutex)
+{
+ if (!mutex->guard.done)
+ return EINVAL;
+ DeleteCriticalSection (&mutex->lock);
+ mutex->guard.done = 0;
+ return 0;
+}
diff --git a/lib/windows-mutex.h b/lib/windows-mutex.h
new file mode 100644
index 0000000..748b988
--- /dev/null
+++ b/lib/windows-mutex.h
@@ -0,0 +1,51 @@
+/* Plain mutexes (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#ifndef _WINDOWS_MUTEX_H
+#define _WINDOWS_MUTEX_H
+
+#define WIN32_LEAN_AND_MEAN /* avoid including junk */
+#include <windows.h>
+
+#include "windows-initguard.h"
+
+typedef struct
+ {
+ glwthread_initguard_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock;
+ }
+ glwthread_mutex_t;
+
+#define GLWTHREAD_MUTEX_INIT { GLWTHREAD_INITGUARD_INIT }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void glwthread_mutex_init (glwthread_mutex_t *mutex);
+extern int glwthread_mutex_lock (glwthread_mutex_t *mutex);
+extern int glwthread_mutex_trylock (glwthread_mutex_t *mutex);
+extern int glwthread_mutex_unlock (glwthread_mutex_t *mutex);
+extern int glwthread_mutex_destroy (glwthread_mutex_t *mutex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WINDOWS_MUTEX_H */
diff --git a/lib/windows-once.c b/lib/windows-once.c
new file mode 100644
index 0000000..c431bd6
--- /dev/null
+++ b/lib/windows-once.c
@@ -0,0 +1,62 @@
+/* Once-only control (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#include <config.h>
+
+/* Specification. */
+#include "windows-once.h"
+
+#include <stdlib.h>
+
+void
+glwthread_once (glwthread_once_t *once_control, void (*initfunction) (void))
+{
+ if (once_control->inited <= 0)
+ {
+ if (InterlockedIncrement (&once_control->started) == 0)
+ {
+ /* This thread is the first one to come to this once_control. */
+ InitializeCriticalSection (&once_control->lock);
+ EnterCriticalSection (&once_control->lock);
+ once_control->inited = 0;
+ initfunction ();
+ once_control->inited = 1;
+ LeaveCriticalSection (&once_control->lock);
+ }
+ else
+ {
+ /* Don't let once_control->started grow and wrap around. */
+ InterlockedDecrement (&once_control->started);
+ /* Some other thread has already started the initialization.
+ Yield the CPU while waiting for the other thread to finish
+ initializing and taking the lock. */
+ while (once_control->inited < 0)
+ Sleep (0);
+ if (once_control->inited <= 0)
+ {
+ /* Take the lock. This blocks until the other thread has
+ finished calling the initfunction. */
+ EnterCriticalSection (&once_control->lock);
+ LeaveCriticalSection (&once_control->lock);
+ if (!(once_control->inited > 0))
+ abort ();
+ }
+ }
+ }
+}
diff --git a/lib/windows-once.h b/lib/windows-once.h
new file mode 100644
index 0000000..d31717e
--- /dev/null
+++ b/lib/windows-once.h
@@ -0,0 +1,47 @@
+/* Once-only control (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#ifndef _WINDOWS_ONCE_H
+#define _WINDOWS_ONCE_H
+
+#define WIN32_LEAN_AND_MEAN /* avoid including junk */
+#include <windows.h>
+
+typedef struct
+ {
+ volatile int inited;
+ volatile LONG started;
+ CRITICAL_SECTION lock;
+ }
+ glwthread_once_t;
+
+#define GLWTHREAD_ONCE_INIT { -1, -1 }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void glwthread_once (glwthread_once_t *once_control,
+ void (*initfunction) (void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WINDOWS_ONCE_H */
diff --git a/lib/windows-recmutex.c b/lib/windows-recmutex.c
new file mode 100644
index 0000000..db3c40c
--- /dev/null
+++ b/lib/windows-recmutex.c
@@ -0,0 +1,127 @@
+/* Plain recursive mutexes (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#include <config.h>
+
+/* Specification. */
+#include "windows-recmutex.h"
+
+#include <errno.h>
+
+void
+glwthread_recmutex_init (glwthread_recmutex_t *mutex)
+{
+ mutex->owner = 0;
+ mutex->depth = 0;
+ InitializeCriticalSection (&mutex->lock);
+ mutex->guard.done = 1;
+}
+
+int
+glwthread_recmutex_lock (glwthread_recmutex_t *mutex)
+{
+ if (!mutex->guard.done)
+ {
+ if (InterlockedIncrement (&mutex->guard.started) == 0)
+ /* This thread is the first one to need this mutex. Initialize it. */
+ glwthread_recmutex_init (mutex);
+ else
+ {
+ /* Don't let mutex->guard.started grow and wrap around. */
+ InterlockedDecrement (&mutex->guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this mutex. */
+ while (!mutex->guard.done)
+ Sleep (0);
+ }
+ }
+ {
+ DWORD self = GetCurrentThreadId ();
+ if (mutex->owner != self)
+ {
+ EnterCriticalSection (&mutex->lock);
+ mutex->owner = self;
+ }
+ if (++(mutex->depth) == 0) /* wraparound? */
+ {
+ mutex->depth--;
+ return EAGAIN;
+ }
+ }
+ return 0;
+}
+
+int
+glwthread_recmutex_trylock (glwthread_recmutex_t *mutex)
+{
+ if (!mutex->guard.done)
+ {
+ if (InterlockedIncrement (&mutex->guard.started) == 0)
+ /* This thread is the first one to need this mutex. Initialize it. */
+ glwthread_recmutex_init (mutex);
+ else
+ {
+ /* Don't let mutex->guard.started grow and wrap around. */
+ InterlockedDecrement (&mutex->guard.started);
+ /* Let another thread finish initializing this mutex, and let it also
+ lock this mutex. */
+ return EBUSY;
+ }
+ }
+ {
+ DWORD self = GetCurrentThreadId ();
+ if (mutex->owner != self)
+ {
+ if (!TryEnterCriticalSection (&mutex->lock))
+ return EBUSY;
+ mutex->owner = self;
+ }
+ if (++(mutex->depth) == 0) /* wraparound? */
+ {
+ mutex->depth--;
+ return EAGAIN;
+ }
+ }
+ return 0;
+}
+
+int
+glwthread_recmutex_unlock (glwthread_recmutex_t *mutex)
+{
+ if (mutex->owner != GetCurrentThreadId ())
+ return EPERM;
+ if (mutex->depth == 0)
+ return EINVAL;
+ if (--(mutex->depth) == 0)
+ {
+ mutex->owner = 0;
+ LeaveCriticalSection (&mutex->lock);
+ }
+ return 0;
+}
+
+int
+glwthread_recmutex_destroy (glwthread_recmutex_t *mutex)
+{
+ if (mutex->owner != 0)
+ return EBUSY;
+ DeleteCriticalSection (&mutex->lock);
+ mutex->guard.done = 0;
+ return 0;
+}
diff --git a/lib/windows-recmutex.h b/lib/windows-recmutex.h
new file mode 100644
index 0000000..3b315e5
--- /dev/null
+++ b/lib/windows-recmutex.h
@@ -0,0 +1,57 @@
+/* Plain recursive mutexes (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#ifndef _WINDOWS_RECMUTEX_H
+#define _WINDOWS_RECMUTEX_H
+
+#define WIN32_LEAN_AND_MEAN /* avoid including junk */
+#include <windows.h>
+
+#include "windows-initguard.h"
+
+/* The native Windows documentation says that CRITICAL_SECTION already
+ implements a recursive lock. But we need not rely on it: It's easy to
+ implement a recursive lock without this assumption. */
+
+typedef struct
+ {
+ glwthread_initguard_t guard; /* protects the initialization */
+ DWORD owner;
+ unsigned long depth;
+ CRITICAL_SECTION lock;
+ }
+ glwthread_recmutex_t;
+
+#define GLWTHREAD_RECMUTEX_INIT { GLWTHREAD_INITGUARD_INIT, 0, 0 }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void glwthread_recmutex_init (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_lock (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_trylock (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_unlock (glwthread_recmutex_t *mutex);
+extern int glwthread_recmutex_destroy (glwthread_recmutex_t *mutex);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WINDOWS_RECMUTEX_H */
diff --git a/lib/windows-rwlock.c b/lib/windows-rwlock.c
new file mode 100644
index 0000000..aafc5dd
--- /dev/null
+++ b/lib/windows-rwlock.c
@@ -0,0 +1,373 @@
+/* Read-write locks (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#include <config.h>
+
+/* Specification. */
+#include "windows-rwlock.h"
+
+#include <errno.h>
+#include <stdlib.h>
+
+/* In this file, the waitqueues are implemented as circular arrays. */
+#define glwthread_waitqueue_t glwthread_carray_waitqueue_t
+
+static void
+glwthread_waitqueue_init (glwthread_waitqueue_t *wq)
+{
+ wq->array = NULL;
+ wq->count = 0;
+ wq->alloc = 0;
+ wq->offset = 0;
+}
+
+/* Enqueues the current thread, represented by an event, in a wait queue.
+ Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */
+static HANDLE
+glwthread_waitqueue_add (glwthread_waitqueue_t *wq)
+{
+ HANDLE event;
+ unsigned int index;
+
+ if (wq->count == wq->alloc)
+ {
+ unsigned int new_alloc = 2 * wq->alloc + 1;
+ HANDLE *new_array =
+ (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
+ if (new_array == NULL)
+ /* No more memory. */
+ return INVALID_HANDLE_VALUE;
+ /* Now is a good opportunity to rotate the array so that its contents
+ starts at offset 0. */
+ if (wq->offset > 0)
+ {
+ unsigned int old_count = wq->count;
+ unsigned int old_alloc = wq->alloc;
+ unsigned int old_offset = wq->offset;
+ unsigned int i;
+ if (old_offset + old_count > old_alloc)
+ {
+ unsigned int limit = old_offset + old_count - old_alloc;
+ for (i = 0; i < limit; i++)
+ new_array[old_alloc + i] = new_array[i];
+ }
+ for (i = 0; i < old_count; i++)
+ new_array[i] = new_array[old_offset + i];
+ wq->offset = 0;
+ }
+ wq->array = new_array;
+ wq->alloc = new_alloc;
+ }
+ /* Whether the created event is a manual-reset one or an auto-reset one,
+ does not matter, since we will wait on it only once. */
+ event = CreateEvent (NULL, TRUE, FALSE, NULL);
+ if (event == INVALID_HANDLE_VALUE)
+ /* No way to allocate an event. */
+ return INVALID_HANDLE_VALUE;
+ index = wq->offset + wq->count;
+ if (index >= wq->alloc)
+ index -= wq->alloc;
+ wq->array[index] = event;
+ wq->count++;
+ return event;
+}
+
+/* Notifies the first thread from a wait queue and dequeues it. */
+static void
+glwthread_waitqueue_notify_first (glwthread_waitqueue_t *wq)
+{
+ SetEvent (wq->array[wq->offset + 0]);
+ wq->offset++;
+ wq->count--;
+ if (wq->count == 0 || wq->offset == wq->alloc)
+ wq->offset = 0;
+}
+
+/* Notifies all threads from a wait queue and dequeues them all. */
+static void
+glwthread_waitqueue_notify_all (glwthread_waitqueue_t *wq)
+{
+ unsigned int i;
+
+ for (i = 0; i < wq->count; i++)
+ {
+ unsigned int index = wq->offset + i;
+ if (index >= wq->alloc)
+ index -= wq->alloc;
+ SetEvent (wq->array[index]);
+ }
+ wq->count = 0;
+ wq->offset = 0;
+}
+
+void
+glwthread_rwlock_init (glwthread_rwlock_t *lock)
+{
+ InitializeCriticalSection (&lock->lock);
+ glwthread_waitqueue_init (&lock->waiting_readers);
+ glwthread_waitqueue_init (&lock->waiting_writers);
+ lock->runcount = 0;
+ lock->guard.done = 1;
+}
+
+int
+glwthread_rwlock_rdlock (glwthread_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glwthread_rwlock_init (lock);
+ else
+ {
+ /* Don't let lock->guard.started grow and wrap around. */
+ InterlockedDecrement (&lock->guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ }
+ EnterCriticalSection (&lock->lock);
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow, and whether no writer is waiting. The latter
+ condition is because POSIX recommends that "write locks shall take
+ precedence over read locks", to avoid "writer starvation". */
+ if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ HANDLE event = glwthread_waitqueue_add (&lock->waiting_readers);
+ if (event != INVALID_HANDLE_VALUE)
+ {
+ DWORD result;
+ LeaveCriticalSection (&lock->lock);
+ /* Wait until another thread signals this event. */
+ result = WaitForSingleObject (event, INFINITE);
+ if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+ abort ();
+ CloseHandle (event);
+ /* The thread which signalled the event already did the bookkeeping:
+ removed us from the waiting_readers, incremented lock->runcount. */
+ if (!(lock->runcount > 0))
+ abort ();
+ return 0;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount + 1 > 0));
+ }
+ }
+ lock->runcount++;
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glwthread_rwlock_wrlock (glwthread_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glwthread_rwlock_init (lock);
+ else
+ {
+ /* Don't let lock->guard.started grow and wrap around. */
+ InterlockedDecrement (&lock->guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ }
+ EnterCriticalSection (&lock->lock);
+ /* Test whether no readers or writers are currently running. */
+ if (!(lock->runcount == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_writers. */
+ HANDLE event = glwthread_waitqueue_add (&lock->waiting_writers);
+ if (event != INVALID_HANDLE_VALUE)
+ {
+ DWORD result;
+ LeaveCriticalSection (&lock->lock);
+ /* Wait until another thread signals this event. */
+ result = WaitForSingleObject (event, INFINITE);
+ if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+ abort ();
+ CloseHandle (event);
+ /* The thread which signalled the event already did the bookkeeping:
+ removed us from the waiting_writers, set lock->runcount = -1. */
+ if (!(lock->runcount == -1))
+ abort ();
+ return 0;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount == 0));
+ }
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glwthread_rwlock_init (lock);
+ else
+ {
+ /* Don't let lock->guard.started grow and wrap around. */
+ InterlockedDecrement (&lock->guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ }
+ /* It's OK to wait for this critical section, because it is never taken for a
+ long time. */
+ EnterCriticalSection (&lock->lock);
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow, and whether no writer is waiting. The latter
+ condition is because POSIX recommends that "write locks shall take
+ precedence over read locks", to avoid "writer starvation". */
+ if (!(lock->runcount + 1 > 0 && lock->waiting_writers.count == 0))
+ {
+ /* This thread would have to wait for a while. Return instead. */
+ LeaveCriticalSection (&lock->lock);
+ return EBUSY;
+ }
+ lock->runcount++;
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glwthread_rwlock_init (lock);
+ else
+ {
+ /* Don't let lock->guard.started grow and wrap around. */
+ InterlockedDecrement (&lock->guard.started);
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ }
+ /* It's OK to wait for this critical section, because it is never taken for a
+ long time. */
+ EnterCriticalSection (&lock->lock);
+ /* Test whether no readers or writers are currently running. */
+ if (!(lock->runcount == 0))
+ {
+ /* This thread would have to wait for a while. Return instead. */
+ LeaveCriticalSection (&lock->lock);
+ return EBUSY;
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glwthread_rwlock_unlock (glwthread_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ EnterCriticalSection (&lock->lock);
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ abort ();
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ {
+ LeaveCriticalSection (&lock->lock);
+ return EPERM;
+ }
+ lock->runcount--;
+ }
+ if (lock->runcount == 0)
+ {
+ /* POSIX recommends that "write locks shall take precedence over read
+ locks", to avoid "writer starvation". */
+ if (lock->waiting_writers.count > 0)
+ {
+ /* Wake up one of the waiting writers. */
+ lock->runcount--;
+ glwthread_waitqueue_notify_first (&lock->waiting_writers);
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ lock->runcount += lock->waiting_readers.count;
+ glwthread_waitqueue_notify_all (&lock->waiting_readers);
+ }
+ }
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glwthread_rwlock_destroy (glwthread_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ if (lock->runcount != 0)
+ return EBUSY;
+ DeleteCriticalSection (&lock->lock);
+ if (lock->waiting_readers.array != NULL)
+ free (lock->waiting_readers.array);
+ if (lock->waiting_writers.array != NULL)
+ free (lock->waiting_writers.array);
+ lock->guard.done = 0;
+ return 0;
+}
diff --git a/lib/windows-rwlock.h b/lib/windows-rwlock.h
new file mode 100644
index 0000000..ae5b82f
--- /dev/null
+++ b/lib/windows-rwlock.h
@@ -0,0 +1,68 @@
+/* Read-write locks (native Windows implementation).
+ Copyright (C) 2005-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/>. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-win32.h. */
+
+#ifndef _WINDOWS_RWLOCK_H
+#define _WINDOWS_RWLOCK_H
+
+#define WIN32_LEAN_AND_MEAN /* avoid including junk */
+#include <windows.h>
+
+#include "windows-initguard.h"
+
+/* It is impossible to implement read-write locks using plain locks, without
+ introducing an extra thread dedicated to managing read-write locks.
+ Therefore here we need to use the low-level Event type. */
+
+typedef struct
+ {
+ HANDLE *array; /* array of waiting threads, each represented by an event */
+ unsigned int count; /* number of waiting threads */
+ unsigned int alloc; /* length of allocated array */
+ unsigned int offset; /* index of first waiting thread in array */
+ }
+ glwthread_carray_waitqueue_t;
+typedef struct
+ {
+ glwthread_initguard_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock; /* protects the remaining fields */
+ glwthread_carray_waitqueue_t waiting_readers; /* waiting readers */
+ glwthread_carray_waitqueue_t waiting_writers; /* waiting writers */
+ int runcount; /* number of readers running, or -1 when a writer runs */
+ }
+ glwthread_rwlock_t;
+
+#define GLWTHREAD_RWLOCK_INIT { GLWTHREAD_INITGUARD_INIT }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void glwthread_rwlock_init (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_rdlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_wrlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_tryrdlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_trywrlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_unlock (glwthread_rwlock_t *lock);
+extern int glwthread_rwlock_destroy (glwthread_rwlock_t *lock);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WINDOWS_RWLOCK_H */
diff --git a/lib/xalloc-die.c b/lib/xalloc-die.c
index bfe6109..68559de 100644
--- a/lib/xalloc-die.c
+++ b/lib/xalloc-die.c
@@ -1,6 +1,6 @@
/* Report a memory allocation failure and exit.
- Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2018 Free Software
+ Copyright (C) 1997-2000, 2002-2004, 2006, 2009-2020 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 3426e10..13ee230 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -1,6 +1,6 @@
/* xalloc-oversized.h -- memory allocation size checking
- Copyright (C) 1990-2000, 2003-2004, 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2003-2004, 2006-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
diff --git a/lib/xalloc.h b/lib/xalloc.h
index c419a2d..9563b0b 100644
--- a/lib/xalloc.h
+++ b/lib/xalloc.h
@@ -1,6 +1,6 @@
/* xalloc.h -- malloc with out-of-memory checking
- Copyright (C) 1990-2000, 2003-2004, 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2003-2004, 2006-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
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
index 9a30d67..4868736 100644
--- a/lib/xmalloc.c
+++ b/lib/xmalloc.c
@@ -1,6 +1,6 @@
/* xmalloc.c -- malloc with out of memory checking
- Copyright (C) 1990-2000, 2002-2006, 2008-2018 Free Software Foundation, Inc.
+ Copyright (C) 1990-2000, 2002-2006, 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
@@ -76,14 +76,14 @@ x2realloc (void *p, size_t *pn)
return x2nrealloc (p, pn, 1);
}
-/* Allocate S bytes of zeroed memory dynamically, with error checking.
+/* Allocate N bytes of zeroed memory dynamically, with error checking.
There's no need for xnzalloc (N, S), since it would be equivalent
to xcalloc (N, S). */
void *
-xzalloc (size_t s)
+xzalloc (size_t n)
{
- return memset (xmalloc (s), 0, s);
+ return xcalloc (n, 1);
}
/* Allocate zeroed memory for N elements of S bytes, with error